Runtime fullscreen toggle

Awesome.
Does it work reliably ?

I just found a minor bug related to the origin of the client area when switching back to windowed, actually. I’ll fix it today. Apart from that, I’ve only tested on this PC, which is Windows 7 64 with a nvidia card, btw. So it’s too soon to say, but no crashes so far.

Just fixed the above issue, so now it’s reliable 100%. Only thing is that the window is placed at 0,0 when going back to Windowed. We have to make some changes so that Panda is able to remember the windowed origin, which is what you’d expect.

Expanding on your original question, I realized you were probably asking if it’s reliable because switching the window object is a tricky business. But we are not doing that anymore, the window remains intact, I’m just issuing SetWindowLong calls to redecorate the same Window. So yeah, it’s pretty reliable cause nothing is being altered inside Panda.

I just fixed it for the Unix/X11 case, toggling is now working perfectly.
Weird thing is, I had to pass 1 or 0 rather than _NET_WM_STATE_ADD or _NET_WM_STATE_REMOVE to the window manager, otherwise it wouldn’t work.

^ what he said would be nice an all in one package which can make it easier. Would be cool if it could auto detect the resolution and then adjust itself to that

Does this work on the Mac and if so how would I integrate it into my game?

No, sorry, it doesn’t work for Mac.

Question… how is that better than just setting the full screen your self? I mean I know it’s less over all code, but less control over all no?

      #Make the screen fullscreen or back to windower.
      if (self.keyMap["fullscreen"]!=0):
        if self.CanWork == True:
          if task.time >= self.CommandWait + .25:
            self.CanWork = False
            props = WindowProperties()
            if self.full == 0:
              props.setFullscreen(False)
              props.setUndecorated(False)
              screenx = int(base.pipe.getDisplayWidth()/2) - (int(self.ScreenWidth)/2)
              screeny = int(base.pipe.getDisplayHeight()/2) - (int(self.ScreenHeight)/2)
              self.TempScreenSizeRX = int(self.ScreenWidth)
              self.TempScreenSizeRY = int(self.ScreenHeight)
              props.setOrigin(screenx,screeny)
              props.setSize(int(self.ScreenWidth),int(self.ScreenHeight))
              self.myScrolledList.refresh()
              self.full = 1
            elif self.full == 1:
              props.setFullscreen(True)
              props.setOrigin(0,0)
              self.TempScreenSizeRX = int(base.pipe.getDisplayWidth())
              self.TempScreenSizeRY = int(base.pipe.getDisplayHeight())
              props.setSize(int(base.pipe.getDisplayWidth()),int(base.pipe.getDisplayHeight()))
              self.myScrolledList.refresh()
              self.full = 0
            base.win.requestProperties(props)
        else:
          self.CommandWait = task.time
          self.CanWork = True

      if self.CanWork == False:
        if task.time >= self.CommandWait + .1:
          self.CommandWait = task.time
          self.CanWork = True

Hi,

WindowProperties wp;
window->get_graphics_window()->request_properties(wp);
if (wp.get_fullscreen())
    wp.set_fullscreen(false);
else
    wp.set_fullscreen(true);
window->get_graphics_window()->request_properties(wp);

wp.get_fullscreen() seems to be always true. What am I missing?

Thanks!

You want to get the existing property set to determine the current properties, and then create a new ‘delta’ WindowProperties object that holds your changes.

const WindowProperties oldp = window->get_graphics_window()->get_properties();
WindowProperties newp;
if (oldp.get_fullscreen()) 
    newp.set_fullscreen(false); 
else 
    newp.set_fullscreen(true); 
window->get_graphics_window()->request_properties(newp);

Thank you very much rdb for the fast and accurate reply. That worked a treat :slight_smile:

However I understand that works because request_properties() will make a kind of “OR” or “XOR” operation with the properties like in bitwise operations somehow preserving current values and changing only the different ones(did I get that right?). But is there any reason why one should make this delta in a new set of properties? It seems to work fine if I use the same object:

WindowProperties wp = window->get_graphics_window()->get_properties();
wp.set_fullscreen(!wp.get_fullscreen());
window->get_graphics_window()->request_properties(wp);

Or will this spoil some of the values in the current set? Or will it be slower?

Regards

It doesn’t do a XOR operation. request_properties(wp) takes a new property set, asks the window manager to apply those properties, and then puts the properties that were successfully set into the WindowProperties object that is returned by get_properties().

If you use the same object, then all properties will be re-applied and not just the ‘fullscreen’ one, which is probably not a good idea.

All right, got that! Thanks again rdb!

Hi,
I know this is an old thread, I am testing this solution on Panda3d 1.9.1 and 1.10, Win10 and after a “few” toggles I get an error from Panda that reads:

:display:windisplay(error): Videocard has no supported display resolutions at specified res (1926 x 1109 x 32)

This also happens with lower resolutions.

Python code,

    def toggleFullScreen(self):
        new_wp = WindowProperties()
        old_wp = base.win.getProperties()
        if old_wp.getFullscreen():
            new_wp.setFullscreen(False)
        else:
            new_wp.setFullscreen(True)
        #new_wp.setSize(1920,1080)
        base.win.requestProperties(new_wp)

If I remove the commented line to force the size every time it works fine.
What strikes me is that it works for a few times (toggling) and then it breaks and I can no longer go to full screen.
It is not that I have a particular need for this, I was simply testing that I could switch and realized that only worked for a couple of times.

Panda is not doing anything at all when this happens.

Printing (as str) those variables gives this (I start from FULLSCREEN ON)

TOGGLE
Old properties: origin=(0, 0) size=(1920, 1080) title=“Panda” !undecorated fixed_size fullscreen foreground !minimized open !cursor_hidden absolute
New properties: !fullscreen
TOGGLE
Old properties: origin=(0, 0) size=(1920, 1080) title=“Panda” !undecorated fixed_size !fullscreen foreground !minimized open !cursor_hidden absolute
New properties: fullscreen
TOGGLE
Old properties: origin=(0, 0) size=(1920, 1080) title=“Panda” !undecorated fixed_size fullscreen foreground !minimized open !cursor_hidden absolute
New properties: !fullscreen
TOGGLE
Old properties: origin=(0, 0) size=(1920, 1080) title=“Panda” !undecorated fixed_size !fullscreen foreground !minimized open !cursor_hidden absolute
New properties: fullscreen
TOGGLE
Old properties: origin=(0, 0) size=(1926, 1109) title=“Panda” !undecorated fixed_size fullscreen foreground !minimized open !cursor_hidden absolute
New properties: !fullscreen
TOGGLE
Old properties: origin=(0, 0) size=(1926, 1109) title=“Panda” !undecorated fixed_size !fullscreen foreground !minimized open !cursor_hidden absolute
New properties: fullscreen
TOGGLE
:display:windisplay(error): Videocard has no supported display resolutions at specified res (1926 x 1109 x 32)
:display:windisplay(warning): Switching to fullscreen mode failed!

I wait a about a second between toggles.
any thoughts ?
Thanks

You need to make sure to always set the size to a reasonable resolution size when going to fullscreen. I’m not sure why your window is becoming larger but I do know that you can’t always rely on the window being of a size that is appropriate for fullscreen mode.

I do want to point out that this thread is no longer very relevant since fullscreen toggle is nowadays implemented out of the box in Panda.