Strange sdl side-effect on unrelated windows - python

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

Related

Python/Linux - Check if some other app is fullscreen

I have developed a controller for RGB LEDs on the back of my monitor, and I would like to control them so that they match the average color on the screen when I have a full screen app running, such as a movie.
I already have the whole controller up and running in the background, but I got stuck trying to figure out how to determine if there is some app running full-screen or not. How could i do it? I am using python3 on Debian testing.
Thanks a lot for any help!
I found an answer here and modified it a bit to make it more usable. Here is my code that works on gnome. You might have to adjust the escaped windows names for other gdms.
import Xlib.display
#Find out if fullscreen app is running
screen = Xlib.display.Display().screen()
root_win = screen.root
def is_fullscreen():
#cycle through all windows
for window in root_win.query_tree()._data['children']:
width = window.get_geometry()._data["width"]
height = window.get_geometry()._data["height"]
#if window is full screen, check it the window name
if width == screen.width_in_pixels and height == screen.height_in_pixels:
if window.get_wm_name() in ['Media viewer', 'mutter guard window']:
continue
#return true if window name is not one of the gnome windows
return True
#if we reach this, no fs window is open
return False

Integrate Pygame in PySimpleGUI

I have a game written with a Pygame loop and it currently draws everything happening in the pygame window. I now want to integrate this window into a larger PySimpleGUI window to have nice functionality around the game. Is this possible?
I tried to use the code from here. The problem is that I get an error like this which comes from VIDEODRIVER at line 25:
pygame.error: windib not available
I changed this to 'windows' but then the Pygame window is separated from the PySimpleGUI as a different window.
Can I make the pygame loop as a window INSIDE the PySimpleGUI? Thank you.
It looks like the detached window is an open, unresolved issue with pygame 2.
If you're able to downgrade to pygame 1.9.6, the linked demo works as expected on Windows after changing the line 25 to:
os.environ['SDL_VIDEODRIVER'] = 'windows' as described.
As said there,
This line only work on windows:
os.environ['SDL_VIDEODRIVER'] = 'windib'
So make a code to skip it when the os is not Windows.
import platform
if platform.system == "Windows":
os.environ['SDL_VIDEODRIVER'] = 'windib'

pygame fullscreen on second monitor [duplicate]

I am using pygame to program a simple behavioral test. I'm running it on my macbook pro and have almost all the functionality working. However, during testing I'll have a second, external monitor that the subject sees and the laptop monitor. I'd like to have the game so up fullscreen on the external monitor and not on the laptop's monitor so that I can monitor performance. Currently, the start of the file looks something like:
#! /usr/bin/env python2.6
import pygame
import sys
stdscr = curses.initscr()
pygame.init()
screen = pygame.display.set_mode((1900, 1100), pygame.RESIZABLE)
I was thinking of starting the game in a resizable screen, but that OS X has problems resizing the window.
Pygame doesn't support two displays in a single pygame process(yet). See the question here and developer answer immediately after, where he says
Once SDL 1.3 is finished then pygame will get support for using multiple windows in the same process.
So, your options are:
Use multiple processes. Two pygame instances, each maximized on its own screen, communicating back and forth (you could use any of: the very cool python multiprocessing module, local TCP, pipes, writing/reading files, etc)
Set the same resolution on both of your displays, and create a large (wide) window that spans them with your information on one half and the user display on the other. Then manually place the window so that the user side is on their screen and yours is on the laptop screen. It's hacky, but might a better use of your time than engineering a better solution ("If it's studpid and it works, it ain't stupid" ;).
Use pyglet, which is similar to pygame and supports full screen windows: pyglet.window.Window(fullscreen=True, screens[1])
Good luck.
I do not know if you can do this in OS X, but this is worth mentioning for the Windows users out there, if you just want to have your program to run full screen on the second screen and you are on windows, just set the other screen as the main one.
The setting can be found under Rearrange Your Displays in settings.
So far for me anything that I can run on my main display can run this way, no need to change your code.
I did something silly but it works.
i get the number of monitors with get_monitors()
than i use SDL to change the pygame window's display position by adding to it the width of the smallest screen, to be sure that the window will be positionned in the second monitor.
from screeninfo import get_monitors
numberOfmonitors = 0
smallScreenWidth = 9999
for monitor in get_monitors():
#getting the smallest screen width
smallScreenWidth = min(smallScreenWidth, monitor.width)
numberOfmonitors += 1
if numberOfmonitors > 1:
x = smallScreenWidth
y = 0
#this will position the pygame window in the second monitor
os.environ['SDL_VIDEO_WINDOW_POS'] = "%d,%d" % (x,y)
#you can check with a small window
#screen = pygame.display.set_mode((100,100))
#or go full screen in second monitor
screen = pygame.display.set_mode((0, 0), pygame.FULLSCREEN)
#if you want to do other tasks on the laptop (first monitor) while the pygame window is being displayed on the second monitor, you shoudn't use fullscreen but instead get the second monitor's width and heigh using monitor.width and monitor.height, and set the display mode like
screen = pygame.display.set_mode((width,height))
display = pyglet.canvas.get_display()
display = display.get_screens()
win = pyglet.window.Window(screen=display[1])
------------------------------------------------------
screen=display[Номер монитора]
------------------------------------------------------
display = pyglet.canvas.get_display()
display = display.get_screens()
print(display) # Все мониторы которые есть

PySDL2: Creating a borderless window

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())

pySDL2 Display without End Loop

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.

Categories