Re: [AD] ALLEGRO_FULLSCREEN_WINDOW flag

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


On Sat, 2010-01-23 at 23:22 +0100, Elias Pschernig wrote:
> The attached patch adds a new display flag called
> ALLEGRO_FULLSCREEN_WINDOW which makes al_create_display ignore the
> passed width and height and instead creates a fullscreen window as big
> as the desktop. It's ignored under Windows and OSX for now.
> 

Ok, we discussed this a bit on allegro.cc in the meantime.

The need for both "real fullscreen" and "fake fullscreen" got clear in
the allegro.cc thread I think. According to X-G in Windows it's possible
to have two fullscreen modes with the exact same resolution/refresh
rate/pixel format - but one allows instant alt-tab and additional
monitors keep working, e.g. when you want to have a video or website
running in one. The other mode makes alt-tab take several seconds (even
though the monitor resolution is not changed) and messes with additional
monitors. However the "real fullscreen" may have better performance
(most likely depends on the gfx card).

It means Allegro won't be able to make the decision so we should support
both. (In X11 the situation seems to be the same as Windows, once we
support XRandR a "real fullscreen" and "fake fullscreen" will be quite
different even if the monitor resolution isn't affected.)

With my proposed flag, the user would have to explicitly set the
ALLEGRO_FULLSCREEN_WINDOW to get a "fake fullscreen" mode. The
width/height actually wouldn't be ignored as in my first version of the
patch, but (at least in X11) be passed as window dimensions. When
toggling the window out of fullscreen state it's the size it would get
then. So I think we can't simply use 0/0 to replace the flag as was
suggested.

The attached patch mainly updates the documentation to reflect the
meaning of the initial width/height and also explains the difference to
ALLEGRO_FULLSCREEN in case the same pixel dimension would be passed with
that flag.

-- 
Elias Pschernig <elias.pschernig@xxxxxxxxxx>
diff --git a/docs/src/refman/display.txt b/docs/src/refman/display.txt
index f94a766..cde1c23 100644
--- a/docs/src/refman/display.txt
+++ b/docs/src/refman/display.txt
@@ -127,6 +127,23 @@ reasonable combination of the following:
 
 * ALLEGRO_FULLSCREEN - prefer a fullscreen mode
 
+* ALLEGRO_FULLSCREEN_WINDOW
+
+  Make the window span the entire screen. Unlike ALLEGRO_FULLSCREEN this
+  will never attempt to modify the screen resolution. Instead the pixel
+  dimensions of the created display will be the same as the desktop.
+
+  The passed width and height are only used if the window is switched
+  out of fullscreen mode later but will be ignored initially.
+
+  Under Windows and X11 a fullscreen display created with this flag
+  will behave differently from one created with the ALLEGRO_FULLSCREEN
+  flag - even if the ALLEGRO_FULLSCREEN display is passed the desktop
+  dimensions. The exact difference is platform dependent, but some
+  things which may be different is how alt-tab works, how fast you can
+  toggle between fullscreen/windowed mode or how additional monitors
+  behave while your display is in fullscreen mode.
+
 * ALLEGRO_RESIZABLE - the display is resizable (only applicable if combined
 with ALLEGRO_WINDOWED)
 
diff --git a/include/allegro5/display_new.h b/include/allegro5/display_new.h
index 4770a3b..6f34e68 100644
--- a/include/allegro5/display_new.h
+++ b/include/allegro5/display_new.h
@@ -23,7 +23,8 @@
 //#define ALLEGRO_SINGLEBUFFER 32
 #define ALLEGRO_NOFRAME      64
 #define ALLEGRO_GENERATE_EXPOSE_EVENTS 128
-
+//is something using 256? didn't seem to work...
+#define ALLEGRO_FULLSCREEN_WINDOW 512
 
 /* Possible parameters for al_set_display_option.
  * Make sure to update ALLEGRO_EXTRA_DISPLAY_SETTINGS if you modify
diff --git a/include/allegro5/internal/aintern_xglx.h b/include/allegro5/internal/aintern_xglx.h
index 8d1ff8b..637f51b 100644
--- a/include/allegro5/internal/aintern_xglx.h
+++ b/include/allegro5/internal/aintern_xglx.h
@@ -151,6 +151,7 @@ void _al_xglx_restore_video_mode(ALLEGRO_SYSTEM_XGLX *s);
 void _al_xglx_free_mode_infos(ALLEGRO_SYSTEM_XGLX *s);
 void _al_xglx_fullscreen_to_display(ALLEGRO_SYSTEM_XGLX *s,
    ALLEGRO_DISPLAY_XGLX *d);
+void _al_xglx_toggle_fullscreen_window(ALLEGRO_DISPLAY *display, bool onoff);
 
 /* glx_config */
 void _al_xglx_config_select_visual(ALLEGRO_DISPLAY_XGLX *glx);
diff --git a/src/x/xdisplay.c b/src/x/xdisplay.c
index a5c3d58..ae7800e 100644
--- a/src/x/xdisplay.c
+++ b/src/x/xdisplay.c
@@ -34,7 +34,8 @@ static void setup_gl(ALLEGRO_DISPLAY *d)
 
 static void set_size_hints(ALLEGRO_DISPLAY *d, int w, int h)
 {
-   if (!(d->flags & ALLEGRO_RESIZABLE)) {
+   if (!(d->flags & ALLEGRO_RESIZABLE)
+      && !(d->flags & ALLEGRO_FULLSCREEN_WINDOW)) {
       ALLEGRO_SYSTEM_XGLX *system = (void *)al_get_system_driver();
       ALLEGRO_DISPLAY_XGLX *glx = (void *)d;
       XSizeHints *hints = XAllocSizeHints();;
@@ -177,6 +178,12 @@ static void xdpy_toggle_frame(ALLEGRO_DISPLAY *display, bool onoff)
 }
 
 
+static Bool resize_predicate(Display *display, XEvent *event, XPointer arg)
+{
+   if (event->type == ConfigureNotify) return True;
+   return False;
+}
+
 
 static bool xdpy_toggle_display_flag(ALLEGRO_DISPLAY *display, int flag,
    bool onoff)
@@ -304,6 +311,8 @@ static ALLEGRO_DISPLAY *xdpy_create_display(int w, int h)
    int new_x, new_y;
    al_get_new_window_position(&new_x, &new_y);
    if (new_x != INT_MAX && new_y != INT_MAX) {
+      ALLEGRO_DEBUG("Force window position to %d, %d.\n",
+         new_x, new_y);
       XWindowChanges wch;
       wch.x = new_x;
       wch.y = new_y;
@@ -322,6 +331,28 @@ static ALLEGRO_DISPLAY *xdpy_create_display(int w, int h)
       _al_cond_wait(&d->mapped, &system->lock);
    }
 
+   /* We can do this at any time, but if we already have a mapped
+    * window when switching to fullscreen it will use the same
+    * monitor (with the MetaCity version I'm using here right now).
+    */
+   if (display->flags & ALLEGRO_FULLSCREEN_WINDOW) {
+      _al_xglx_toggle_fullscreen_window(display, true);
+
+      /* Wait for the resize event so we can create the initial
+       * OpenGL view already with the full size.
+       */
+      XSync(system->x11display, False);
+      XEvent e;
+      XIfEvent(system->x11display, &e, resize_predicate, NULL);
+
+      XWindowAttributes xwa;
+      XGetWindowAttributes(system->x11display, d->window, &xwa);
+      display->w = xwa.width;
+      display->h = xwa.height;
+      ALLEGRO_INFO("Using ALLEGRO_FULLSCREEN_WINDOW of %d x %d\n",
+         display->w, display->h);
+   }
+
    if (!_al_xglx_config_create_context(d)) {
       ALLEGRO_ERROR("Failed to create a context.\n");
       _AL_FREE(d);
@@ -403,7 +434,6 @@ static ALLEGRO_DISPLAY *xdpy_create_display(int w, int h)
          display->extra_settings.settings[ALLEGRO_VSYNC] = 0;
       }
    }
-   
 
    d->invisible_cursor = None; /* Will be created on demand. */
    d->current_cursor = None; /* Initially, we use the root cursor. */
diff --git a/src/x/xfullscreen.c b/src/x/xfullscreen.c
index 057cc49..6074970 100644
--- a/src/x/xfullscreen.c
+++ b/src/x/xfullscreen.c
@@ -235,4 +235,38 @@ void _al_xglx_free_mode_infos(ALLEGRO_SYSTEM_XGLX *s)
 
 #endif /* !ALLEGRO_XWINDOWS_WITH_XF86VIDMODE */
 
+static bool got_atoms;
+static Atom _NET_WM_STATE;
+static Atom _NET_WM_STATE_FULLSCREEN;
+#define X11_ATOM_STRING(x) x = XInternAtom(x11, #x, False);
+
+void _al_xglx_toggle_fullscreen_window(ALLEGRO_DISPLAY *display, bool onoff)
+{
+   ALLEGRO_SYSTEM_XGLX *system = (void *)al_get_system_driver();
+   ALLEGRO_DISPLAY_XGLX *glx = (ALLEGRO_DISPLAY_XGLX *)display;
+   Display *x11 = system->x11display;
+   
+   if (!got_atoms) {
+      X11_ATOM_STRING(_NET_WM_STATE)
+      X11_ATOM_STRING(_NET_WM_STATE_FULLSCREEN)
+      got_atoms = true;
+   }
+
+   XEvent xev;
+   xev.xclient.type = ClientMessage;
+   xev.xclient.serial = 0;
+   xev.xclient.send_event = True;
+   xev.xclient.message_type = _NET_WM_STATE;
+   xev.xclient.window = glx->window;
+   xev.xclient.format = 32;
+   xev.xclient.data.l[0] = onoff ? 1 : 0; /* 0 = off, 1 = on, 2 = toggle */
+   xev.xclient.data.l[1] = _NET_WM_STATE_FULLSCREEN;
+   xev.xclient.data.l[2] = 0;
+   xev.xclient.data.l[3] = 0;
+   xev.xclient.data.l[4] = 0;
+
+   XSendEvent(x11, DefaultRootWindow(x11), False,
+      SubstructureRedirectMask | SubstructureNotifyMask, &xev);
+}
+
 /* vim: set sts=3 sw=3 et: */


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