Re: [AD] Fullscreen problems on Linux

[ Thread Index | Date Index | More lists.liballeg.org/allegro-developers Archives ]


I had another go at it. The problem was again CMake. This time it works, but I'd like if as many people as possible can test on different WMs. I tested the defaults (Metacity?, Compiz) on Ubuntu 10.04 and 14.04. Patch attached.

Thanks,
Trent

On 14-07-07 10:24 AM, Trent Gamblin wrote:
OK, I thought that might be how it worked which is why I started working
on it.The problem I ran into was probably the same thing that prevented
the old way of working (CMake not picking up deps) so I might try it
again later on.

Trent

On 2014-07-07 10:12 AM, Beoran wrote:
I checked the SDL code again, and no, this seems to be a different
code path
from their fullscreen window which they call
SDL_WINDOW_FULLSCREEN_DESKTOP.

The way mode switching through the vm is supposed to work is that you
set a
_NET_WM_STATE_FULLSCREEN on the _NET_WM_STATE property, and the window
manager
is supposed to pick that up, switch to a full-screen resolution equal
to that of your window
size and treat your window as a fullscreen one. Supposedly, the WM should
set full screen even if the window isn't of a correct size, arguably
to the supported mode
with size closest the window's size.

So in theory you don't have to know which modes are supported
by the hardware.... Of course, far from all windows managers support
this, and if they do,
the results are mixed, and the window managers disagree on whether the
window should be resizable
for them to resize it or not. But compiz apparently supports this
correctly if you do
make the window resizable.

However for determining the available video modes SDL still uses
either XRandr
or Xinerama independent of whether it uses the WM for switching modes
or not.
So , we can still get the mode list from XRandr and use that.
You can look in SDL_x11modes.c for the nitty gritty.

Kind Regards,

B.


Op 07-07-14 17:17, Trent Gamblin schreef:
I’m not sure that what SDL is doing there isn’t what we call fullscreen
window.

Anyhow, two things. First I found out that CMake was screwing up and not
picking up some headers or libraries so it works as before now. Second, I
assumed it wasn’t fullscreen window and started implementing it anyway but
there’s no way to get a mode list anyway so it failed there.

Trent
------------------------------------------------------------------------------
Open source business process management suite built on Java and Eclipse
Turn processes into business applications with Bonita BPM Community Edition
Quickly connect people, data, and systems into organized workflows
Winner of BOSSIE, CODIE, OW2 and Gartner awards
http://p.sf.net/sfu/Bonitasoft

------------------------------------------------------------------------------
Open source business process management suite built on Java and Eclipse
Turn processes into business applications with Bonita BPM Community Edition
Quickly connect people, data, and systems into organized workflows
Winner of BOSSIE, CODIE, OW2 and Gartner awards
http://p.sf.net/sfu/Bonitasoft

diff --git a/src/x/xrandr.c b/src/x/xrandr.c
index 36f3857..4448dff 100644
--- a/src/x/xrandr.c
+++ b/src/x/xrandr.c
@@ -6,8 +6,14 @@
 
 #ifdef ALLEGRO_XWINDOWS_WITH_XRANDR
 
+#include <X11/Xatom.h>
+
 ALLEGRO_DEBUG_CHANNEL("xrandr")
 
+#define _NET_WM_STATE_REMOVE    0l
+#define _NET_WM_STATE_ADD       1l
+#define _NET_WM_STATE_TOGGLE    2l
+
 typedef struct xrandr_screen xrandr_screen;
 typedef struct xrandr_crtc xrandr_crtc;
 typedef struct xrandr_output xrandr_output;
@@ -79,6 +85,94 @@ struct xrandr_rect {
    int y2;
 };
 
+/*---------------------------------------------------------------------------*/
+
+/* The following code uses the window manager to set a fullscreen mode when supported */
+
+static bool set_fullscreen_via_net_wm(ALLEGRO_SYSTEM_XGLX *s, ALLEGRO_DISPLAY_XGLX *d)
+{
+   Display *display = s->x11display;
+#define GET_ATOM(X) X = XInternAtom(display, #X, False)
+   Atom _NET_WM_STATE = GET_ATOM(_NET_WM_STATE);
+   Atom _NET_WM_STATE_FULLSCREEN = GET_ATOM(_NET_WM_STATE_FULLSCREEN);
+#undef GET_ATOM
+
+   XEvent e;
+
+   /* Compiz refuses fullscreen toggle if we're not resizable, so update the hints so we
+      can be resized to the fullscreen resolution (or reset so we're not resizable again) */
+   XSizeHints *sizehints = XAllocSizeHints();
+   long flags = 0;
+
+   XGetWMNormalHints(display, d->window, sizehints, &flags);
+   /* set the resize flags on */
+   /* we are going fullscreen so turn the flags off */
+   sizehints->flags &= ~(PMinSize | PMaxSize);
+   XSetWMNormalHints(display, d->window, sizehints);
+   XFree(sizehints);
+
+   memset(&e, 0, sizeof(e));
+   e.xany.type = ClientMessage;
+   e.xclient.message_type = _NET_WM_STATE;
+   e.xclient.format = 32;
+   e.xclient.window = d->window;
+   e.xclient.data.l[0] =_NET_WM_STATE_ADD;
+   e.xclient.data.l[1] = _NET_WM_STATE_FULLSCREEN;
+   e.xclient.data.l[3] = 0l;
+
+   XSendEvent(display, RootWindow(display, DefaultScreen(display)), 0,
+            SubstructureNotifyMask | SubstructureRedirectMask, &e);
+
+   XFlush(display);
+
+   return true;
+}
+
+static bool have_net_supporting_wm(Display *display)
+{
+   Atom _NET_SUPPORTING_WM_CHECK;
+   int status, real_format;
+   Atom real_type;
+   unsigned long items_read = 0, items_left = 0;
+   unsigned char *propdata = NULL;
+   Window wm_window = 0;
+
+   XSync(display, False);
+
+   _NET_SUPPORTING_WM_CHECK = XInternAtom(display, "_NET_SUPPORTING_WM_CHECK", False);
+   status = XGetWindowProperty(display, DefaultRootWindow(display), _NET_SUPPORTING_WM_CHECK, 0L, 1L, False, XA_WINDOW, &real_type, &real_format, &items_read, &items_left, &propdata);
+   if (status == Success) {
+      if (items_read) {
+         wm_window = ((Window*)propdata)[0];
+      }
+      if (propdata) {
+         XFree(propdata);
+         propdata = NULL;
+      }
+   }
+
+   if (wm_window) {
+      status = XGetWindowProperty(display, wm_window, _NET_SUPPORTING_WM_CHECK, 0L, 1L, False, XA_WINDOW, &real_type, &real_format, &items_read, &items_left, &propdata);
+      if (status != Success || !items_read || wm_window != ((Window*)propdata)[0]) {
+         wm_window = None;
+      }
+      if (status == Success && propdata) {
+         XFree(propdata);
+         propdata = NULL;
+      }
+   }
+
+   XSync(display, False);
+
+   if (!wm_window) {
+      return false;
+   }
+
+   return true;
+}
+
+/*---------------------------------------------------------------------------*/
+
 static void xrandr_copy_mode(xrandr_mode *mode, XRRModeInfo *rrmode)
 {
    mode->id     = rrmode->id;
@@ -503,7 +597,15 @@ static bool xrandr_set_mode(ALLEGRO_SYSTEM_XGLX *s, ALLEGRO_DISPLAY_XGLX *d, int
 {
    int adapter = _al_xglx_get_adapter(s, d, false);
    int xscreen = _al_xglx_get_xscreen(s, adapter);
-   
+
+   if (have_net_supporting_wm(s->x11display)) {
+      bool ret;
+      _al_mutex_lock(&s->lock);
+      ret = set_fullscreen_via_net_wm(s, d);
+      _al_mutex_unlock(&s->lock);
+      return ret;
+   }
+
    xrandr_screen *screen = _al_vector_ref(&s->xrandr_screens, xscreen);
    
    xrandr_crtc *crtc = xrandr_map_to_crtc(s, xscreen, adapter);


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/