Re: [AD] RFC - Linux WM Fullscreen Patch

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


Here's yet another patch. I'll apply this one if there are no new results. This patch adds a config variable called force_netwm_fullscreen_off. It also makes al_resize_display work correctly in most cases whereas it wasn't tested before, so consecutive modesets didn't work well.

On 14-08-06 03:43 PM, trent@xxxxxxxxxx wrote:

I finally had a chance to have a go at the ALLEGRO_FULLSCREEN_VIRTUAL code (attached.)

 

The patch isn’t necessarily considered ready to go. There are some problems. On KDE I get a nearly fullscreen display that’s shifted up about 20 pixels. On XFCE it works sometimes, but if the panel is positioned a certain way the display doesn’t cover it. On Compiz it seems to work.

 

I had to modify the primitives addon which is perhaps the ugliest part, as primitives and transforms seems to be different. The patch jimmies in the ALLEGRO_FULLSCREEN_VIRTUAL flag into ex_bitmap, ex_prim, cosmic protector and speed. Seems to work with and without the flag in those examples with this patch.

 

Wondering if anyone has ideas on how to fix XFCE and KDE? Also extra testing is highly appreciated.


Thanks.



------------------------------------------------------------------------------
Infragistics Professional
Build stunning WinForms apps today!
Reboot your WinForms applications with our WinForms controls. 
Build a bridge from your legacy apps to the future.
http://pubads.g.doubleclick.net/gampad/clk?id=153845071&iu=/4140/ostg.clktrk



diff --git a/cmake/FileList.cmake b/cmake/FileList.cmake
index ede9c57..007dddd 100644
--- a/cmake/FileList.cmake
+++ b/cmake/FileList.cmake
@@ -114,6 +114,7 @@ set(ALLEGRO_SRC_X_FILES
     src/x/xrandr.c
     src/x/xsystem.c
     src/x/xwindow.c
+    src/x/xwmfullscreen.c
     src/linux/lhaptic.c
     src/linux/ljoynu.c
     )
diff --git a/include/allegro5/internal/aintern_xdisplay.h b/include/allegro5/internal/aintern_xdisplay.h
index a8e616d..d353376 100644
--- a/include/allegro5/internal/aintern_xdisplay.h
+++ b/include/allegro5/internal/aintern_xdisplay.h
@@ -92,6 +92,8 @@ struct ALLEGRO_XWIN_DISPLAY_OVERRIDABLE_INTERFACE
 bool _al_xwin_set_gtk_display_overridable_interface(uint32_t check_version,
    const ALLEGRO_XWIN_DISPLAY_OVERRIDABLE_INTERFACE *vt);
 
+bool x_try_fullscreen_via_netwm(ALLEGRO_SYSTEM_XGLX *s, ALLEGRO_DISPLAY_XGLX *d);
+
 #endif /* !ALLEGRO_RASPBERRYPI */
 
 #endif
diff --git a/src/x/xfullscreen.c b/src/x/xfullscreen.c
index 0651e46..1e35b53 100644
--- a/src/x/xfullscreen.c
+++ b/src/x/xfullscreen.c
@@ -364,7 +364,9 @@ static bool xfvm_set_mode(ALLEGRO_SYSTEM_XGLX *s, ALLEGRO_DISPLAY_XGLX *d, int w
 {
    int mode_idx = -1;
    int adapter = _al_xglx_get_adapter(s, d, false);
-   
+
+   x_try_fullscreen_via_netwm(s, d);
+
 #ifdef ALLEGRO_XWINDOWS_WITH_XINERAMA
    /* TwinView workarounds, nothing to do here, since we can't really change or restore modes */
    if (s->xinerama_available && s->xinerama_screen_count != s->xfvm_screen_count) {
diff --git a/src/x/xrandr.c b/src/x/xrandr.c
index 36f3857..201b018 100644
--- a/src/x/xrandr.c
+++ b/src/x/xrandr.c
@@ -503,7 +503,9 @@ 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);
-   
+
+   x_try_fullscreen_via_netwm(s, d);
+
    xrandr_screen *screen = _al_vector_ref(&s->xrandr_screens, xscreen);
    
    xrandr_crtc *crtc = xrandr_map_to_crtc(s, xscreen, adapter);
diff --git a/src/x/xwmfullscreen.c b/src/x/xwmfullscreen.c
new file mode 100644
index 0000000..a46eb43
--- /dev/null
+++ b/src/x/xwmfullscreen.c
@@ -0,0 +1,138 @@
+#include <X11/Xlib.h>
+
+#include "allegro5/allegro.h"
+#include "allegro5/internal/aintern_x.h"
+#include "allegro5/internal/aintern_xdisplay.h"
+#include "allegro5/internal/aintern_xfullscreen.h"
+#include "allegro5/internal/aintern_xsystem.h"
+
+#include <X11/Xatom.h>
+
+ALLEGRO_DEBUG_CHANNEL("display")
+
+#define _NET_WM_STATE_REMOVE    0l
+#define _NET_WM_STATE_ADD       1l
+#define _NET_WM_STATE_TOGGLE    2l
+
+#define GET_ATOM(X) XInternAtom(display, #X, False)
+
+static bool netwm_fullscreen_allowed(void)
+{
+   ALLEGRO_CONFIG *cfg;
+
+   cfg = al_get_system_config();
+   if (cfg) {
+      char const *value = al_get_config_value(cfg,
+	 "graphics", "force_netwm_fullscreen_off");
+      if (value) {
+         return !atoi(value);
+      }
+   }
+
+   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;
+}
+
+bool x_try_fullscreen_via_netwm(ALLEGRO_SYSTEM_XGLX *s, ALLEGRO_DISPLAY_XGLX *d)
+{
+   Display *display = s->x11display;
+   Atom _NET_WM_STATE;
+   Atom _NET_WM_STATE_FULLSCREEN;
+
+   if (!netwm_fullscreen_allowed()) {
+      return false;
+   }
+
+   if (!have_net_supporting_wm(s->x11display)) {
+      return false;
+   }
+
+   _NET_WM_STATE = GET_ATOM(_NET_WM_STATE);
+   _NET_WM_STATE_FULLSCREEN = GET_ATOM(_NET_WM_STATE_FULLSCREEN);
+
+   if (d->is_mapped) {
+      XEvent e;
+
+      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);
+   }
+   else {
+      Atom _NET_WM_STATE_MAXIMIZED_VERT = GET_ATOM(_NET_WM_STATE_MAXIMIZED_VERT);
+      Atom _NET_WM_STATE_MAXIMIZED_HORZ = GET_ATOM(_NET_WM_STATE_MAXIMIZED_HORZ);
+      Atom _NET_WM_STATE_FOCUSED = GET_ATOM(_NET_WM_STATE_FOCUSED);
+
+      Atom atoms[4];
+
+      atoms[0] = _NET_WM_STATE_MAXIMIZED_VERT;
+      atoms[1] = _NET_WM_STATE_MAXIMIZED_HORZ;
+      atoms[2] = _NET_WM_STATE_FULLSCREEN;
+      atoms[3] = _NET_WM_STATE_FOCUSED;
+
+      XChangeProperty(display, d->window, _NET_WM_STATE, XA_ATOM, 32, PropModeReplace, (unsigned char *)atoms, 4);
+   }
+
+   XFlush(display);
+
+   return true;
+}
+


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