[RFC] Un-trapping mouse while running fullscreen (SDL limitation/design-flaw)
#16
althekiller Wrote:Keep in mind that one of the goals of XBMC is platform neutrality. Something like this would need to be able to be implemented win32 and osx as well.
Good to know. In that case SDL really does seem like the proper place for this stuff. However is this even an issue on win32 and osX? I'll test my dual head setup in windows XP.

I did some poking around in the SDL source, and it looks like there is no technical reason that SDL_WM_GrabInput has no effect in fullscreen mode - in fact there is added code to make it behave this way. It is possible that on some platform it would take more than just removing that code, but on X11 it really does look that easy. I doubt they will be open to changing this behavior, since some applications might rely on it. However maybe we could add a new grab input function that works even in fullscreen? I'm going to try to get GrabInput to work in fullscreen mode to verify my suspicions.
Reply
#17
bdallen Wrote:I'm going to try to get GrabInput to work in fullscreen mode to verify my suspicions.
Uncommented lines 1867-1869 in SDL_video.c, and now SDL_WM_GrabInput (SDL_GRAB_OFF) works in fullscreen mode. This convinces me that SDL fullscreen is not fundamentally different, at least in X11. However removing those lines causes some odd behavior - for example if I run my demo app in fullscreen, then move the mouse to my second screen and focus, the sdl app pops into a window. Then it pops back when I refocus on the sdl app.

I'm going to ask about this on the SDL mailing list. I don't think there are any serious technical barriers, but the idea that fullscreen mode and input grabbing go together shows itself in many different places in the SDL code. Making input grabbing optional would take some very careful coding.

bdallen Wrote:What follows is a bunch of poorly informed speculation about the nature of SDL fullscreen. Hopefully someone else will find it interesting, or take the time to substantiate or refute it.
So ya... I now think that my speculation was completely wrong. Looks like an API design issue more than anything else.
Reply
#18
bdallen Wrote:However is this even an issue on win32 and osX? I'll test my dual head setup in windows XP.

I believe that this is an issue with win32. I don't have exact setup of two monitors connected to one computer, but I am using Synergy to share my mouse with a second computer. If I move the mouse onto that Windows XP Synergy client (which is running XBMC), the mouse immediately become unusable. It automatically moves to the upper left corner. The mouse directly connected to the XBMC computer still works though, just not the mouse from the Synergy server. It was suggested in http://trac.xbmc.org/ticket/4843 that SDL might be the problem, however, having no personal experience with SDL, I could be way off base.
Reply
#19
bdallen Wrote:Is there a performance hit when running (SDL_WINDOW_MAXIMIZED | SDL_WINDOW_BORDERLESS) vs fullscreen?
I haven't ever done any empirical testing to see if there is a performance penalty to not being in a fullscreen mode but I can tell you that if there is one it is not significant. Frame rates in a fullscreen vs maximized window are similar, with one being faster one run and the other being faster on the next run but both within what I'd consider standard deviation for my system which has 100 processes running at any given time.

For what it is worth, you can modify Surface.cpp thusly:
Code:
Index: Surface.cpp
===================================================================
--- Surface.cpp    (revision 15635)
+++ Surface.cpp    (working copy)
@@ -303,7 +303,7 @@
   {
#endif
#ifndef __APPLE__
-    int options = SDL_OPENGL | (fullscreen?SDL_FULLSCREEN:0);
+    int options = SDL_OPENGL | (fullscreen?SDL_NOFRAME:0);
#endif
     SDL_GL_SetAttribute(SDL_GL_RED_SIZE,   m_iRedSize);
     SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, m_iGreenSize);
@@ -339,6 +339,13 @@
     if (m_SDLSurface)
     {
       m_bOK = true;
+      if (fullscreen)
+      {
+        struct SDL_SysWMinfo wmInfo;
+        SDL_VERSION(&wmInfo.version);
+        if (SDL_GetWMInfo(&wmInfo) == -1)
+          ::MoveWindow(wmInfo.window, 0, 0, m_iWidth, m_iHeight, true);
+      }
     }

     if (!b_glewInit)
And under win32 you get a fullscreen borderless window with no mouse capture, just like you'd expect. The window has to be moved because SDL creates it in the default position.

The Linux code is different because XBMC uses the HAS_GLX codepath which I can't follow too well. I tried doing something similar by modifying GraphicContext.cpp and CSurface::ResizeSurface() appropriately but kept getting BadWindow errors when trying to move the window. Even when I didn't move the window I'd end up getting a decorated window every time after the first call. I know jack about X11 so I'm not sure where to go from there, sorry.
Reply
#20
CapnBry Wrote:The Linux code is different because XBMC uses the HAS_GLX codepath which I can't follow too well. I tried doing something similar by modifying GraphicContext.cpp and CSurface::ResizeSurface() appropriately but kept getting BadWindow errors when trying to move the window. Even when I didn't move the window I'd end up getting a decorated window every time after the first call. I know jack about X11 so I'm not sure where to go from there, sorry.
I didn't realize that SDL has a NOFRAME option. That may be a better solution than using EWMH - I'll see if I can get it working.

Are you interested in trying to get a patch accepted? If you can get it working on win32, I think I can get it working in X11. That leaves OS X, assuming that no one is dual-heading their xbox. Any volunteers?

CapnBry Wrote:Don't use fullscreen mode because that's what fullscreen mode does; getting it to not do that would be like trying to get a leopard to change its spots. What you want is a borderless maximized window.
I've come to agree with you on this point regarding SDL_FULLSCREEN in 1.2 - I can make it not grab by commenting out three lines, but I break many things. Doing it properly does not look fun - it might be easier to implement a whole new mode. And this would have to be done on all platforms with a pointing device and multiple displays.

However in 1.3 the iconification-on-lost-focus behavior for SDL_WINDOW_FULLSCREEN seems arbitrary. Why isn't there an option to disable the iconification-on-lost-focus behavior, like there is for grabbing? If FULLSCREEN really does have potential performance optimizations, then FULLSCREEN with no grab and no iconification would really be different (and better for some applications) than (SDL_WINDOW_MAXIMIZED | SDL_WINDOW_BORDERLESS). Perhaps this is not the place to split hairs about API design, but I'm curious if you have any insight into why this is being done.
Reply
#21
bdallen Wrote:However in 1.3 the iconification-on-lost-focus behavior for SDL_WINDOW_FULLSCREEN seems arbitrary. Why isn't there an option to disable the iconification-on-lost-focus behavior, like there is for grabbing? If FULLSCREEN really does have potential performance optimizations, then FULLSCREEN with no grab and no iconification would really be different (and better for some applications) than (SDL_WINDOW_MAXIMIZED | SDL_WINDOW_BORDERLESS). Perhaps this is not the place to split hairs about API design, but I'm curious if you have any insight into why this is being done.
It isn't arbitrary at all. Undew win32, FULLSCREEN isn't a very good term for what you're requesting when you pass SDL_FULLSCREEN to SDL_SetVideoMode.

What you're requesting is a temporary change in resolution of the primary display and then create a window to fill that new resolution. Think of when you want to play a 720p video and you're running your desktop at 1600x1200. You swap the resolution to 1280x720 and start playing the video. Now suddenly you decide you want to browse the web. When focus leaves XBMC, resolution should return to desktop resolution. Well what should that 1280x720 video window now do? Rather than leave a window that thought it was fullscreen but now is half the size of the screen dangling over your desktop, the window is minimized. If you switch back to that window, your display resolution will switch back to 1280x720 fullscreen again.

That's what FULLSCREEN means. It implies "take up the whole screen" but the real purpose of it is to change the resolution and capture input, and when the window loses focus to reverse those changes and iconify.

Just thinking out lout here but what we should do is identify our goals here change the XBMC preferences to match those goals. What varieties of window do we need?
  • Windowed mode: A fixed size decorated window with borders.
  • Maximized mode: A fixed size borderless window with no decoration that is topmost and the size of the current screen resolution.
The next question is how does the user tell XBMC it wants it to switch the resolution. Maybe I'm creating too many options? How about something more along of three options
  • Resolution
  • Windowed?
  • Display (if not windowed)
If not windowed then XBMC does not FULLSCREEN but rather permanently switches resolution to this new mode. Display is used only if there are multiple displays on the user's system.
Reply
#22
CapnBry Wrote:That's what FULLSCREEN means. It implies "take up the whole screen" but the real purpose of it is to change the resolution and capture input, and when the window loses focus to reverse those changes and iconify.
Thanks - that makes sense. And I can't think of a better name than "FULLSCREEN" that's not too long.

CapnBry Wrote:How about something more along of three options
  • Resolution
  • Windowed?
  • Display (if not windowed)
If not windowed then XBMC does not FULLSCREEN but rather permanently switches resolution to this new mode. Display is used only if there are multiple displays on the user's system.
Now that you've pointed out the resolution change issue, I think changing display resolution and not changing back is undesirable. Also if we go to all the trouble of implementing resolution changes without SDL, then changing back on quit should be easy.

Another option would be to use FULLSCREEN for the resolution change scenario, but just add a "maximized" mode that takes up the fullscreen but doesn't change resolution and doesn't grab. If someone wanted automatic resolution change and no-grab, they could use another tool - in modern X11 xrandr can do this. This solution is less complete, but we wouldn't need to implement resolution change. The options might look like this:
  • Display Mode: Windowed, Fullscreen, Maximized
  • Resolution (not displayed for mode Maximized)
  • Display (if multi-head detected)

Is there something like xrandr for Windows and OS X? If not, how hard would it be to implement resolution change? We could always adapt code from SDL.
Reply
#23
Changing the resolution for the display is really easy. Here's what I'm thinking and maybe you can tell me if this is possible under Linux.

Monitor: Dell 2001FPW (Display 0)
Resolution: 1680x1050 @60Hz
Windowed: (checkbox)

The monitor list would be grayed for systems with only one detected display and the resolution list would vary based on the selected display. The \ hotkey would be change from the "fullscreen" purpose to toggling windowed mode. Going out of windowed mode will switch the resolution of the selected display (if needed) and maximize the window to fill those dimensions. Of course when XBMC exits it will reset the display back to the original resolution.

I think we could skip the fullscreen vs maximized distinction because I'm thinking to get the same effect you just run non-windowed at the resolution you want and there's less confusion about the fullscreen vs maximized distinction.

Maybe we should start another thread about this since it isn't Linux-specific and get some input from the project manager types. I'd also say it shouldn't go into Atlantis since this is a feature and we're past the feature freeze.
Reply
#24
I'm sold on removing the fullscreen/maximized distinction, and I think that's a good way of laying out the options. What should we call the project? Maybe "New fullscreen and display configuration framework"? We definitely need feedback from the project managers and other programmers.

Resolution change is pretty straight forward in Linux if we only support XServers with the randr extension. Otherwise it's a bit of a pain, although we could yank a bunch of code out SDL.

Choosing the display is a bit more complicated. With separate screen dual-heading, display changes would require a restart. However I think I can handle that case using just the X11 API and setting the DISPLAY environment variable with putenv. I'm not so sure about Xinerama, TwinView, etc however. I think in those cases it will amount to setting the top right corner of the window to start at the corner of the correct display.

Getting the monitor names in Linux might be possible with a modern X extension, but I'm not sure. That is the sort of enhancement that could be added later - most linux users are used to referring to displays by number.
Reply
#25
Ouch changing the resolution sounds complicated under the separate screen dual heading scenario. I've never had much luck with running dual displays under Linux with the exception of clone mode. I know the current ATI driver doesn't even support running the two screens at different resolutions in their X "Big Desktop" mode so I'm wondering if that's even worth trying to implement on that platform.

Under linux if there are actually two DISPLAYs like :0 and :1 that means the Linux version really doesn't need to worry about it because the user can just export the display they want XBMC to appear on before launching right?

Windows has it much easier but we still can't use SDL to change the resolution of the second display.

Getting a window running maximized on the second screen is super simple though. When we're running dual head we just see two displays and one of them has a nonzero "position". 1 call to SDL_putenv("SDL_VIDEO_WINDOW_POS=offsetXxoffsetY") and the SDL window appears in the proper place. This could easily be added to the RESOLUTION_INFO and windows users are good to go for getting XBMC frameless and maximized on the secondary display.

Maybe that's a good first step?
Reply
#26
CapnBry Wrote:Under linux if there are actually two DISPLAYs like :0 and :1 that means the Linux version really doesn't need to worry about it because the user can just export the display they want XBMC to appear on before launching right?
Actually with two screens on one X-Server, you get :0.0 and :0.1, but it amounts to the same thing. We probably could get away with not implementing anything for this case, since it is as easy as running 'DISPLAY=:0.1 xbmc'.

I think the MergedFB (ati) and TwinView both provide Xinerama information, so that may be all we need to support. We could also support "one big desktop" setups by allowing manual offsets - or will SDL_VIDEO_WINDOW_POS already do this? I'll test if it works in Linux also.

However I have no idea how XRandR and legacy mechanisms for resolution change interact with Xinerama, or MergedFB/TwinView. There may be some graphics driver specific issues here. XRandR works great for separate screen dual heading, but I'm not sure about the legacy mechanisms. I guess we just need to do as well as SDL...
Reply
#27
Some more thoughts about fullscreen and SDL 1.3/2:

What we've been talking about is a screen mode that changes resolution and automatically restores the resolution on exit, but allows the mouse to leave the window and move to the another display without forcing a resolution change or minimization. However on Alt-Tab you would probably want the minimization/resolution change behavior of SDL_WINDOW_FULLSCREEN in 1.3. I still think it would be useful if the behavior of SDL fullscreen were more configurable, because here we have a practical situation where we want some of the behaviors but not others. Or maybe the mode just shouldn't minimize if focus goes to another display, but that may be hard to detect. If that doesn't happen, is SDL 2 going to have a resolution change API? It seems like this would just amount to uncoupling resolution change from FULLSCREEN mode. Resolution change in Linux is enough of a mess (if you want to support X without XRandR) that this really ought to be in a library, so multiple applications can make use of it.
Reply
#28
bdallen Wrote:Resolution change in Linux is enough of a mess (if you want to support X without XRandR) that this really ought to be in a library, so multiple applications can make use of it.
Well hello xfullscreen...
Reply
#29
I hope the 'fullscreen-maximized' solution you are proposing comes to fruition. I have spent the last several days and nights trying to force just such a set up for my touchscreen under a variety of window managers and utilities to no avail. This would be invaluable to kiosk and car audio users.
Reply
#30
funkknob Wrote:I hope the 'fullscreen-maximized' solution you are proposing comes to fruition.
Setting display resolutions in Linux, in the most cross X-server/dual-head configuration way possible, is far more confusing than I'd anticipated. I probably won't have a chance to work on this seriously for a while (until my thesis is done). If someone wants to take over that would be great. However if not I'll pick it up again in December. I also want to get KDE 4 to work with separate X-screens, and it seems like there is some overlap there in the knowledge required.

There is also the option of just adding the "maximized non-grab" fullscreen mode, which is confusing to users but much easier to implement. Perhaps this is a good temporary fix until a more complete solution is developed?
Reply

Logout Mark Read Team Forum Stats Members Help
[RFC] Un-trapping mouse while running fullscreen (SDL limitation/design-flaw)1