I've been trying to find how I might create a borderless window (One not created using the typical windows border) in PySDL2.
I've looked at what resources I could find online, but haven't been able to pinpoint anything that would tell me how to accomplish this, despite it being apparently possible.
Research:
This link states that in most cases you have a border and title bar around your window, but never went into any more detail as to how to manipulate it.
I looked at some API references for SDL's Window, and did not see that borders could be manipulated at all. (Not stated that they couldn't be, just no mention)
Despite not finding anything PySDL2 related, I did find at this link that:
sdl.setWindowBordered(window, bordered)
Sets the border state of a window.
Unfortunately, I'm unable to get this to work within my simple example script.
Thanks for looking!
You need to make sure you have the flag: SDL_WINDOW_BORDERLESS.
Full example:
import sys
import sdl2.ext
sdl2.ext.init()
window = sdl2.ext.Window("Hello World!", size=(640, 480), flags=sdl2.SDL_WINDOW_BORDERLESS)
window.show()
processor = sdl2.ext.TestEventProcessor()
processor.run(window)
Modifying your script slightly we get:
import sys
import sdl2.ext
def run():
sdl2.ext.init()
W = sdl2.ext.Window("Default",size=(400,300), flags=sdl2.SDL_WINDOW_BORDERLESS)
W.show()
running = True
while running:
events = sdl2.ext.get_events()
for event in events:
if event.type == sdl2.SDL_QUIT:
running = False
break
W.refresh()
return 0
if __name__ == "__main__":
sys.exit(run())
Related
I'm making a pseudo transparent window in pygame with the intent of displaying varied info like a "HUD"
The script uses PIL to grab an image of the desktop and use it as the background of the window.
A simple version:
import pygame as py
from ctypes import windll
import ImageGrab, Image
SetWindowPos = windll.user32.SetWindowPos
py.init()
def get_image():
im = ImageGrab.grab((0,0,window_x,window_y))
mode = im.mode
size = im.size
data = im.tobytes()
im = py.image.fromstring(data,size,mode)
return im
window_x = 1920
window_y = 100
background = py.Surface((window_x,window_y))
background.blit(get_image(),(0,0))
window_pos = (0,0)
screen = py.display.set_mode((window_x,window_y),py.HWSURFACE|py.NOFRAME)
SetWindowPos(py.display.get_wm_info()['window'],-1,0,0,0,0,0x0001)
clock = py.time.Clock()
done = False
while not done:
for event in py.event.get():
if event.type == py.QUIT:
done = True
screen.blit(background,(0,0))
py.display.flip()
clock.tick(30)
py.quit()
This creates a Pygame window at the top of the screen.
My problem is that the Pygame window blocks any mouse interaction with anything beneath it.
Is there a way to allow mouse events to be ignored and go 'through' the window, like for example clicking on a desktop icon, underneath a Pygame window.
You will need to do a bit of an extra hacking which is outside what PyGame gives you. It should be possible to render the PyGame canvas into another windowing framework in Python and try to use advanced features of that library to achieve this.
In Windows
One example is wxWidgets. As described in this thread, which sounds quite similar to what you are trying to achieve, the user has setup a window which can be clicked through and is transparent.
Also see this another Stackoverflow Post which mentions how to handle the Hit Testing in C#. Posting code from that post here:
protected override void WndProc(ref Message m)
{
if (m.Msg == (int)WM_NCHITTEST)
m.Result = (IntPtr)HTTRANSPARENT;
else
base.WndProc(ref m);
}
It is possible to do similar testing in Python using win32 APIs. This is a piece of Python code that does exactly this. Locate the part where the programmer sets up the callback for the event (something like win32con.WM_NCHITTEST: self.onChi, where self.onChi is the callback).
I hope this gives you a starting point. I doubt there is anything readymade that you will find out of the box but these should give you some pointers on what to look for.
This is an old question, but I have ran into it quite a few times and only now got it to work right. Here is the relevant bit.
import win32api
import win32con
import win32gui
fuchsia = (255, 0, 128) # Transparency color
hwnd = pygame.display.get_wm_info()["window"] # Handle
styles = win32gui.GetWindowLong(hwnd, win32con.GWL_EXSTYLE)
styles = win32con.WS_EX_LAYERED | win32con.WS_EX_TRANSPARENT
win32gui.SetWindowLong(hwnd, win32con.GWL_EXSTYLE, styles)
win32gui.SetLayeredWindowAttributes(hwnd, win32api.RGB(*fuchsia), 0, win32con.LWA_COLORKEY)
I'm making a pseudo transparent window in pygame with the intent of displaying varied info like a "HUD"
The script uses PIL to grab an image of the desktop and use it as the background of the window.
A simple version:
import pygame as py
from ctypes import windll
import ImageGrab, Image
SetWindowPos = windll.user32.SetWindowPos
py.init()
def get_image():
im = ImageGrab.grab((0,0,window_x,window_y))
mode = im.mode
size = im.size
data = im.tobytes()
im = py.image.fromstring(data,size,mode)
return im
window_x = 1920
window_y = 100
background = py.Surface((window_x,window_y))
background.blit(get_image(),(0,0))
window_pos = (0,0)
screen = py.display.set_mode((window_x,window_y),py.HWSURFACE|py.NOFRAME)
SetWindowPos(py.display.get_wm_info()['window'],-1,0,0,0,0,0x0001)
clock = py.time.Clock()
done = False
while not done:
for event in py.event.get():
if event.type == py.QUIT:
done = True
screen.blit(background,(0,0))
py.display.flip()
clock.tick(30)
py.quit()
This creates a Pygame window at the top of the screen.
My problem is that the Pygame window blocks any mouse interaction with anything beneath it.
Is there a way to allow mouse events to be ignored and go 'through' the window, like for example clicking on a desktop icon, underneath a Pygame window.
You will need to do a bit of an extra hacking which is outside what PyGame gives you. It should be possible to render the PyGame canvas into another windowing framework in Python and try to use advanced features of that library to achieve this.
In Windows
One example is wxWidgets. As described in this thread, which sounds quite similar to what you are trying to achieve, the user has setup a window which can be clicked through and is transparent.
Also see this another Stackoverflow Post which mentions how to handle the Hit Testing in C#. Posting code from that post here:
protected override void WndProc(ref Message m)
{
if (m.Msg == (int)WM_NCHITTEST)
m.Result = (IntPtr)HTTRANSPARENT;
else
base.WndProc(ref m);
}
It is possible to do similar testing in Python using win32 APIs. This is a piece of Python code that does exactly this. Locate the part where the programmer sets up the callback for the event (something like win32con.WM_NCHITTEST: self.onChi, where self.onChi is the callback).
I hope this gives you a starting point. I doubt there is anything readymade that you will find out of the box but these should give you some pointers on what to look for.
This is an old question, but I have ran into it quite a few times and only now got it to work right. Here is the relevant bit.
import win32api
import win32con
import win32gui
fuchsia = (255, 0, 128) # Transparency color
hwnd = pygame.display.get_wm_info()["window"] # Handle
styles = win32gui.GetWindowLong(hwnd, win32con.GWL_EXSTYLE)
styles = win32con.WS_EX_LAYERED | win32con.WS_EX_TRANSPARENT
win32gui.SetWindowLong(hwnd, win32con.GWL_EXSTYLE, styles)
win32gui.SetLayeredWindowAttributes(hwnd, win32api.RGB(*fuchsia), 0, win32con.LWA_COLORKEY)
When playing with sdl2 via pysdl2 I noticed this strange side-effect where once the sdl script runs unrelated windows which would normally become translucent when moved do now stay opaque.
I wouldn't mind all that much if it weren't for the nagging feeling
that this indicates that I'm doing something fundamentally wrong.
Anyone able to enlighten me as to what the heck is going on here?
Here is my script:
import sdl2
import sdl2.ext as se
import time
def main():
k = 2
event_buffer = (k * sdl2.SDL_Event)()
se.init()
window = se.Window("what the ?", size=(400, 300))
window.show()
while True:
window.refresh()
time.sleep(0.01)
sdl2.SDL_PumpEvents()
sdl2.SDL_PeepEvents(event_buffer, k, sdl2.SDL_GETEVENT,
sdl2.SDL_FIRSTEVENT, sdl2.SDL_LASTEVENT)
for event in event_buffer:
if not event.type:
continue
elif event.type == sdl2.SDL_QUIT:
se.quit()
break
else:
pass
event.type = 0
else:
continue
break
if __name__ == '__main__':
main()
And here are a before and an after screen grab:
The System Settings window of my KDE 5.45.0 desktop without the sdl script running, showing the relevant setting Desktop Effects>Translucency. Notice how the window is translucent because I'm dragging it while taking the picture.
The same but with the sdl script running. Notice how the window despite my vigorously dragging it stays stubbornly opaque.
I can also reproduce this in my Ubuntu desktop with Unity, so it's definitely not a problem of your KDE desktop. I think this is a bug in pysdl2 and this solution should be a temporary workaround until it gets fixed but in the meanwhile, you can just add this inside your while loop:
window.get_surface()
The issue is already reported here: https://github.com/marcusva/py-sdl2/issues/139
I'm making a pseudo transparent window in pygame with the intent of displaying varied info like a "HUD"
The script uses PIL to grab an image of the desktop and use it as the background of the window.
A simple version:
import pygame as py
from ctypes import windll
import ImageGrab, Image
SetWindowPos = windll.user32.SetWindowPos
py.init()
def get_image():
im = ImageGrab.grab((0,0,window_x,window_y))
mode = im.mode
size = im.size
data = im.tobytes()
im = py.image.fromstring(data,size,mode)
return im
window_x = 1920
window_y = 100
background = py.Surface((window_x,window_y))
background.blit(get_image(),(0,0))
window_pos = (0,0)
screen = py.display.set_mode((window_x,window_y),py.HWSURFACE|py.NOFRAME)
SetWindowPos(py.display.get_wm_info()['window'],-1,0,0,0,0,0x0001)
clock = py.time.Clock()
done = False
while not done:
for event in py.event.get():
if event.type == py.QUIT:
done = True
screen.blit(background,(0,0))
py.display.flip()
clock.tick(30)
py.quit()
This creates a Pygame window at the top of the screen.
My problem is that the Pygame window blocks any mouse interaction with anything beneath it.
Is there a way to allow mouse events to be ignored and go 'through' the window, like for example clicking on a desktop icon, underneath a Pygame window.
You will need to do a bit of an extra hacking which is outside what PyGame gives you. It should be possible to render the PyGame canvas into another windowing framework in Python and try to use advanced features of that library to achieve this.
In Windows
One example is wxWidgets. As described in this thread, which sounds quite similar to what you are trying to achieve, the user has setup a window which can be clicked through and is transparent.
Also see this another Stackoverflow Post which mentions how to handle the Hit Testing in C#. Posting code from that post here:
protected override void WndProc(ref Message m)
{
if (m.Msg == (int)WM_NCHITTEST)
m.Result = (IntPtr)HTTRANSPARENT;
else
base.WndProc(ref m);
}
It is possible to do similar testing in Python using win32 APIs. This is a piece of Python code that does exactly this. Locate the part where the programmer sets up the callback for the event (something like win32con.WM_NCHITTEST: self.onChi, where self.onChi is the callback).
I hope this gives you a starting point. I doubt there is anything readymade that you will find out of the box but these should give you some pointers on what to look for.
This is an old question, but I have ran into it quite a few times and only now got it to work right. Here is the relevant bit.
import win32api
import win32con
import win32gui
fuchsia = (255, 0, 128) # Transparency color
hwnd = pygame.display.get_wm_info()["window"] # Handle
styles = win32gui.GetWindowLong(hwnd, win32con.GWL_EXSTYLE)
styles = win32con.WS_EX_LAYERED | win32con.WS_EX_TRANSPARENT
win32gui.SetWindowLong(hwnd, win32con.GWL_EXSTYLE, styles)
win32gui.SetLayeredWindowAttributes(hwnd, win32api.RGB(*fuchsia), 0, win32con.LWA_COLORKEY)
In every pySLD2 example I've found, I've seen a loop at the end of the code to keep the window open until closure. For example:
#!/usr/bin/env python
"""
The code is placed into public domain
by anatoly techtonik <techtonik#gmail.com>
"""
import sdl2
import sdl2.ext as lib
lib.init()
window = lib.Window('', size=(300, 100))
window.show()
renderer = lib.Renderer(window)
renderer.draw_point([10,10], lib.Color(255,255,255))
renderer.present()
####Specifically this loop####
running = True
while running:
for e in lib.get_events():
if e.type == sdl2.SDL_QUIT:
running = False
break
if e.type == sdl2.SDL_KEYDOWN:
if e.key.keysym.sym == sdl2.SDLK_ESCAPE:
running = False
break
All event handlers I've seen have been blocking. Is there a way, like I have seen done in standard SDL, to simply call initialization and updating functions on a window that stays open. I am writing to write this as an external library that I can call independently from any project.
Any ideas? Thanks!
EDIT: As per request for a way to do this in standard SDL, this works. Just call the init function to set up the screen and it will stay until you close it.
You are misinterpreting the example - this is an additional hook (screen.c) to be set up in the main loop.
SDL uses the main loop approach to deal with events, update the window display, etc. Yes, there is a way to work around that. Create your very own window and use whatever approach to keep it open, get the window handle via the SDL_SysWM* functions and update the window's display buffer.
This however involves some glue code and also requires you to do the window handling on your own.