DO NOT REPLY TO THIS MESSAGE.  INSTEAD, POST ANY RESPONSES TO THE LINK BELOW.

[STR New]

Link: http://www.fltk.org/str.php?L2641
Version: 1.3-current


The FLTK window method fullscreen() does not do what most people refers to
as "fullscreen". A fullscreen should cover the "full" screen, completely
hide any other application and OS widget. The current FLTK implementation
basically puts up what can be described as a maximized window without
borders. It also lacks in terms of functionality: The applications
currently needs to keep track of the non-fullscreen coordinates and the
fullscreen state. If the X WM initiates the fullscreen mode (possible with
EWMH window managers), the app is not notified and it's internal state is
out of sync. 

The attached patch adds a complete (to my knowledge) full screen support
for all platforms, even multi monitor systems. It requires the patch in
#2640. 

A few comments about the patch:

* A new API: fullscreen_off() without arguments

* A new API: fullscreen_active(), to request the current fullscreen state

* A new event: FL_FULLSCREEN

* The X11 implementation supports EWMH but falls back to
override_redirect+grab. 

The "fullscreen" test application has also been modified somewhat:

* It uses the FL_FULLSCREEN event to properly track the fullscreen state

* It provides an input field, to allow for testing that the input focus
works correctly

* It uses the fullscreen_off() function without arguments


Link: http://www.fltk.org/str.php?L2641
Version: 1.3-current
Index: src/Fl_Window_fullscreen.cxx
===================================================================
--- src/Fl_Window_fullscreen.cxx        (revision 8678)
+++ src/Fl_Window_fullscreen.cxx        (arbetskopia)
@@ -60,39 +60,48 @@
 #endif
 }
 
+void fullscreen_x(Fl_Window *w);
+void fullscreen_off_x();
+void fullscreen_off_x(Fl_Window *w, int X, int Y, int W, int H);
+
+/* Note: The previous implementation toggled border(). With this new
+   implementation this is not necessary. Additionally, if we do that,
+   the application may lose focus when switching out of fullscreen
+   mode with some window managers. Besides, the API does not say that
+   the FLTK border state should be toggled; it only says that the
+   borders should not be *visible*. 
+*/
 void Fl_Window::fullscreen() {
-#ifndef WIN32
-  //this would clobber the fake wm, since it relies on the border flags to
-  //determine its thickness
-  border(0);
-#endif
-#if defined(__APPLE__) || defined(WIN32) || defined(USE_X11)
-  int sx, sy, sw, sh;
-  Fl::screen_xywh(sx, sy, sw, sh, x(), y(), w(), h());
-  // if we are on the main screen, we will leave the system menu bar 
unobstructed
-  if (Fl::x()>=sx && Fl::y()>=sy && Fl::x()+Fl::w()<=sx+sw && 
Fl::y()+Fl::h()<=sy+sh) {
-    sx = Fl::x(); sy = Fl::y(); 
-    sw = Fl::w(); sh = Fl::h();
+  if (shown() && !(flags() & Fl_Widget::FULLSCREEN)) {
+    no_fullscreen_x = x();
+    no_fullscreen_y = y();
+    no_fullscreen_w = w();
+    no_fullscreen_h = h();
+    fullscreen_x(this);
+  } else {
+    set_flag(FULLSCREEN);
   }
-  if (x()==sx) x(sx+1); // make sure that we actually execute the resize
-#if defined(USE_X11)
-  resize(0, 0, w(), h()); // work around some quirks in X11
-#endif
-  resize(sx, sy, sw, sh);
-#else
-  if (!x()) x(1); // make sure that we actually execute the resize
-  resize(0,0,Fl::w(),Fl::h());
-#endif
 }
 
 void Fl_Window::fullscreen_off(int X,int Y,int W,int H) {
-  // this order produces less blinking on IRIX:
-  resize(X,Y,W,H);
-#ifndef WIN32
-  border(1);
-#endif
+  if (shown() && (flags() & Fl_Widget::FULLSCREEN)) {
+    fullscreen_off_x(this, X, Y, W, H);
+  } else {
+    clear_flag(FULLSCREEN);
+  }
+  no_fullscreen_x = no_fullscreen_y = no_fullscreen_w = no_fullscreen_h = 0;
 }
 
+void Fl_Window::fullscreen_off() {
+  if (!no_fullscreen_x && !no_fullscreen_y) {
+    // Window was initially created fullscreen - default to current monitor
+    no_fullscreen_x = x();
+    no_fullscreen_y = y();
+  }
+  fullscreen_off(no_fullscreen_x, no_fullscreen_y, no_fullscreen_w, 
no_fullscreen_h);
+}
+
+
 //
 // End of "$Id$".
 //
Index: src/Fl_Window.cxx
===================================================================
--- src/Fl_Window.cxx   (revision 8678)
+++ src/Fl_Window.cxx   (arbetskopia)
@@ -59,6 +59,10 @@
   resizable(0);
   size_range_set = 0;
   minw = maxw = minh = maxh = 0;
+  no_fullscreen_x = 0;
+  no_fullscreen_y = 0;
+  no_fullscreen_w = w();
+  no_fullscreen_h = h();
   callback((Fl_Callback*)default_callback);
 }
 
Index: src/screen_xywh.cxx
===================================================================
Index: src/Fl_win32.cxx
===================================================================
--- src/Fl_win32.cxx    (revision 8678)
+++ src/Fl_win32.cxx    (arbetskopia)
@@ -1302,6 +1302,11 @@
   X+=xoff;
   Y+=yoff;
 
+  if (w->flags() & Fl_Widget::FULLSCREEN) {
+    X = Y = 0;
+    bx = by = bt = 0;
+  }
+
   return ret;
 }
 
@@ -1352,6 +1357,46 @@
   }
 }
 
+static void make_fullscreen(Fl_Window *w, Window xid, int X, int Y, int W, int 
H) {
+  int sx, sy, sw, sh;
+  Fl::screen_xywh(sx, sy, sw, sh, X, Y, W, H);
+  w->resize(sx, sy, sw, sh);
+  DWORD flags = GetWindowLong(xid, GWL_STYLE);
+  flags = flags & ~(WS_THICKFRAME|WS_CAPTION);
+  SetWindowLong(xid, GWL_STYLE, flags);
+  SetWindowPos(xid, HWND_TOP, sx, sy, sw, sh, SWP_NOSIZE | SWP_FRAMECHANGED);
+}
+
+void fullscreen_x(Fl_Window *w) {
+  w->_set_fullscreen();
+  make_fullscreen(w, fl_xid(w), w->x(), w->y(), w->w(), w->h());
+  Fl::handle(FL_FULLSCREEN, w);
+}
+
+void fullscreen_off_x(Fl_Window *w, int X, int Y, int W, int H) {
+  w->_clear_fullscreen();
+  w->resize(X, Y, W, H);
+  DWORD style = GetWindowLong(fl_xid(w), GWL_STYLE);
+  int x, y, bt, bx, by;
+  switch (Fl_X::fake_X_wm(w, x, y, bt, bx, by)) {
+  case 0: 
+    break;
+  case 1: 
+    style |= WS_CAPTION; 
+    break;
+  case 2: 
+    if (w->border()) {
+      style |= WS_THICKFRAME | WS_CAPTION; 
+    }
+    break;
+  }
+  SetWindowLong(fl_xid(w), GWL_STYLE, style);
+  SetWindowPos(fl_xid(w), HWND_TOP, 0, 0, 0, 0, 
+              SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | 
SWP_FRAMECHANGED);
+  Fl::handle(FL_FULLSCREEN, w);
+}
+
+
 ////////////////////////////////////////////////////////////////
 
 /*
@@ -1548,6 +1593,18 @@
   );
   if (lab) free(lab);
 
+  if (w->flags() & Fl_Widget::FULLSCREEN) {
+  /* We need to make sure that the fullscreen is created on the
+     default monitor, ie the desktop where the shortcut is located
+     etc. This requires that CreateWindow is called with CW_USEDEFAULT
+     for x and y. We can then use GetWindowRect to determine which
+     monitor the window was placed on. */
+    RECT rect;
+    GetWindowRect(x->xid, &rect);
+    make_fullscreen(w, x->xid, rect.left, rect.top, 
+                   rect.right - rect.left, rect.bottom - rect.top);
+  }
+
   x->next = Fl_X::first;
   Fl_X::first = x;
 
@@ -1563,7 +1620,7 @@
   // If we've captured the mouse, we dont want to activate any
   // other windows from the code, or we lose the capture.
   ShowWindow(x->xid, !showit ? SW_SHOWMINNOACTIVE :
-            (Fl::grab() || (style & WS_POPUP)) ? SW_SHOWNOACTIVATE : 
SW_SHOWNORMAL);
+            (Fl::grab() || (styleEx & WS_EX_TOOLWINDOW)) ? SW_SHOWNOACTIVATE : 
SW_SHOWNORMAL);
 
   // Register all windows for potential drag'n'drop operations
   fl_OleInitialize();
Index: src/Fl_x.cxx
===================================================================
--- src/Fl_x.cxx        (revision 8678)
+++ src/Fl_x.cxx        (arbetskopia)
@@ -328,6 +328,9 @@
 Atom fl_XaTextUriList;
 Atom fl_NET_WM_NAME;                   // utf8 aware window label
 Atom fl_NET_WM_ICON_NAME;              // utf8 aware window icon name
+Atom fl_NET_SUPPORTING_WM_CHECK;
+Atom fl_NET_WM_STATE;
+Atom fl_NET_WM_STATE_FULLSCREEN;
 
 /*
   X defines 32-bit-entities to have a format value of max. 32,
@@ -625,6 +628,9 @@
   fl_XaTextUriList      = XInternAtom(d, "text/uri-list",       0);
   fl_NET_WM_NAME        = XInternAtom(d, "_NET_WM_NAME",        0);
   fl_NET_WM_ICON_NAME   = XInternAtom(d, "_NET_WM_ICON_NAME",   0);
+  fl_NET_SUPPORTING_WM_CHECK = XInternAtom(d, "_NET_SUPPORTING_WM_CHECK", 0);
+  fl_NET_WM_STATE       = XInternAtom(d, "_NET_WM_STATE",       0);
+  fl_NET_WM_STATE_FULLSCREEN = XInternAtom(d, "_NET_WM_STATE_FULLSCREEN", 0);
 
   if (sizeof(Atom) < 4)
     atom_bits = sizeof(Atom) * 8;
@@ -768,6 +774,31 @@
   XSendEvent(fl_display, window, 0, 0, &e);
 }
 
+
+/* 
+   Get window property value (32 bit format) 
+   Returns zero on success, -1 on error
+*/
+static int get_xwinprop(Window wnd, Atom prop, long max_length,
+                       unsigned long *nitems, unsigned char **data) {
+  Atom actual;
+  int format;
+  unsigned long bytes_after;
+  
+  if (Success != XGetWindowProperty(fl_display, wnd, prop, 0, max_length, 
+                                   False, AnyPropertyType, &actual, &format, 
+                                   nitems, &bytes_after, data)) {
+    return -1;
+  }
+
+  if (actual == None || format != 32) {
+    return -1;
+  }
+
+  return 0;
+}
+
+
 ////////////////////////////////////////////////////////////////
 // Code for copying to clipboard and DnD out of the program:
 
@@ -1393,6 +1424,31 @@
     in_a_window = true;
     break;
 
+  case PropertyNotify:
+    if (xevent.xproperty.atom == fl_NET_WM_STATE) {
+      int fullscreen_state = 0;
+      if (xevent.xproperty.state != PropertyDelete) {
+       unsigned long nitems;
+       unsigned int *words = 0;
+       if (0 == get_xwinprop(xid, fl_NET_WM_STATE, 64, &nitems, (unsigned char 
**)&words) ) { 
+         for (unsigned long item = 0; item < nitems; item++) {
+           if (words[item] == fl_NET_WM_STATE_FULLSCREEN) {
+             fullscreen_state = 1;
+           }
+         }
+       }
+      }
+      if (window->fullscreen_active() && !fullscreen_state) {
+       window->_clear_fullscreen();
+       event = FL_FULLSCREEN;
+      }
+      if (!window->fullscreen_active() && fullscreen_state) {
+       window->_set_fullscreen();
+       event = FL_FULLSCREEN;
+      }
+    }
+    break;
+
   case MotionNotify:
     set_event_xy();
 #  if CONSOLIDATE_MOTION
@@ -1532,6 +1588,80 @@
 
 ////////////////////////////////////////////////////////////////
 
+#define _NET_WM_STATE_REMOVE        0  /* remove/unset property */
+#define _NET_WM_STATE_ADD           1  /* add/set property */
+#define _NET_WM_STATE_TOGGLE        2  /* toggle property  */
+
+static void send_wm_state_event(Window wnd, int add, Atom prop) {
+  XEvent e;
+  e.xany.type = ClientMessage;
+  e.xany.window = wnd;
+  e.xclient.message_type = fl_NET_WM_STATE;
+  e.xclient.format = 32;
+  e.xclient.data.l[0] = add ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
+  e.xclient.data.l[1] = prop;
+  e.xclient.data.l[2] = 0;
+  e.xclient.data.l[3] = 0;
+  e.xclient.data.l[4] = 0;
+  XSendEvent(fl_display, RootWindow(fl_display, fl_screen),
+            0, SubstructureNotifyMask | SubstructureRedirectMask,
+            &e);
+}
+
+int ewmh_supported() {
+  static unsigned char result = -1;
+
+  if (result == -1) {
+    result = 0;
+    unsigned long nitems;
+    unsigned int *words = 0;
+    if (0 == get_xwinprop(XRootWindow(fl_display, fl_screen), 
fl_NET_SUPPORTING_WM_CHECK, 64,
+                         &nitems, (unsigned char **)&words) && nitems == 1) {
+      Window child = words[0];
+      if (0 == get_xwinprop(child, fl_NET_SUPPORTING_WM_CHECK, 64,
+                           &nitems, (unsigned char **)&words) && nitems == 1) {
+       result = (child == words[0]);
+      }
+    }
+  }
+
+  return result;
+}
+
+/* Change an existing window to fullscreen */
+void fullscreen_x(Fl_Window *w) {
+  int sx, sy, sw, sh;
+  Fl::screen_xywh(sx, sy, sw, sh, w->x(), w->y(), w->w(), w->h());
+  w->resize(sx, sy, sw, sh);
+  if (ewmh_supported()) {
+    send_wm_state_event(fl_xid(w), 1, fl_NET_WM_STATE_FULLSCREEN);
+  } else {
+    w->_set_fullscreen();
+    w->hide();
+    w->show();
+    XGrabKeyboard(fl_display, fl_xid(w), 1, GrabModeAsync, GrabModeAsync, 
fl_event_time);
+    Fl::handle(FL_FULLSCREEN, w);
+  }
+}
+
+
+void fullscreen_off_x(Fl_Window *w, int X, int Y, int W, int H) {
+  /* WM may deny fullscreen leave, but let's try the resize in any case */
+  w->resize(X,Y,W,H);
+  if (ewmh_supported()) {
+    send_wm_state_event(fl_xid(w), 0, fl_NET_WM_STATE_FULLSCREEN);
+  } else {
+    w->_clear_fullscreen();
+    Fl::grab(w);
+    Fl::grab(0);
+    w->hide();
+    w->show();
+    Fl::handle(FL_FULLSCREEN, w);
+  }
+}
+
+////////////////////////////////////////////////////////////////
+
 // A subclass of Fl_Window may call this to associate an X window it
 // creates with the Fl_Window:
 
@@ -1567,6 +1697,7 @@
 |KeyPressMask|KeyReleaseMask|KeymapStateMask|FocusChangeMask
 |ButtonPressMask|ButtonReleaseMask
 |EnterWindowMask|LeaveWindowMask
+|PropertyChangeMask
 |PointerMotionMask;
 
 void Fl_X::make_xid(Fl_Window* win, XVisualInfo *visual, Colormap colormap)
@@ -1638,6 +1769,16 @@
     attr.save_under = 1; mask |= CWSaveUnder;
     if (!win->border()) {attr.override_redirect = 1; mask |= 
CWOverrideRedirect;}
   }
+  // For the non-EWMH fullscreen case, we cannot use the code above,
+  // since we do not want save_under, do not want to turn off the
+  // border, and cannot grab without an existing window. Besides, 
+  // there is no clear_override(). 
+  if (win->flags() & Fl_Widget::FULLSCREEN && !ewmh_supported()) {
+    attr.override_redirect = 1;
+    mask |= CWOverrideRedirect;
+    Fl::screen_xywh(X, Y, W, H, X, Y, W, H);
+  }
+
   if (fl_background_pixel >= 0) {
     attr.background_pixel = fl_background_pixel;
     fl_background_pixel = -1;
@@ -1697,6 +1838,12 @@
           PropModeAppend, (unsigned char*) &net_wm_state_skip_taskbar, 1);
     }
 
+    // If asked for, create fullscreen
+    if (win->flags() & Fl_Widget::FULLSCREEN && ewmh_supported()) {
+      XChangeProperty (fl_display, xp->xid, fl_NET_WM_STATE, XA_ATOM, 32,
+                      PropModeAppend, (unsigned char*) 
&fl_NET_WM_STATE_FULLSCREEN, 1);
+    }
+
     // Make it receptive to DnD:
     long version = 4;
     XChangeProperty(fl_display, xp->xid, fl_XdndAware,
@@ -1734,6 +1881,12 @@
     Fl::e_number = old_event;
     win->redraw();
   }
+
+  // non-EWMH fullscreen case, need grab
+  if (win->flags() & Fl_Widget::FULLSCREEN && !ewmh_supported()) {
+    XGrabKeyboard(fl_display, xp->xid, 1, GrabModeAsync, GrabModeAsync, 
fl_event_time);
+  }
+
 }
 
 ////////////////////////////////////////////////////////////////
Index: src/glut_compatability.cxx
===================================================================
Index: src/Fl_cocoa.mm
===================================================================
--- src/Fl_cocoa.mm     (revision 8678)
+++ src/Fl_cocoa.mm     (arbetskopia)
@@ -613,6 +613,10 @@
 {
   containsGLsubwindow = contains;
 }
+- (BOOL)canBecomeKeyWindow
+{
+  return YES;
+}
 @end
 
 @interface FLApplication : NSObject
@@ -1978,7 +1982,29 @@
 
 @end
 
+void fullscreen_x(Fl_Window *w) {
+  w->_set_fullscreen();
+  /* On OS X, it is necessary to recreate the window. This is done
+     with hide+show. */
+  w->hide();
+  if (CGDisplayCapture( kCGDirectMainDisplay ) != kCGErrorSuccess) {
+    NSLog( @"Couldn't capture the main display!" );
+  }
+  w->show();
+  Fl::handle(FL_FULLSCREEN, w);
+}
 
+void fullscreen_off_x(Fl_Window *w, int X, int Y, int W, int H) {
+  w->_clear_fullscreen();
+  w->hide();
+  w->resize(X, Y, W, H);
+  if (CGDisplayRelease( kCGDirectMainDisplay ) != kCGErrorSuccess) {
+    NSLog( @"Couldn't release the main display!" );
+  }
+  w->show();
+  Fl::handle(FL_FULLSCREEN, w);
+}
+
 /*
  * go ahead, create that (sub)window
  */
@@ -2101,6 +2127,13 @@
     x->gc = 0;
          
     NSRect srect = [[NSScreen mainScreen] frame];
+    if (w->flags() & Fl_Widget::FULLSCREEN) {
+      int sx, sy, sw, sh;
+      Fl::screen_xywh(sx, sy, sw, sh, w->x(), w->y(), w->w(), w->h());
+      w->resize(sx, sy, sw, sh);
+      winstyle = NSBorderlessWindowMask;
+      winlevel = CGShieldingWindowLevel();
+    }
     NSRect crect;
     crect.origin.x = w->x(); 
     crect.origin.y = srect.size.height - (w->y() + w->h());
Index: FL/Enumerations.H
===================================================================
--- FL/Enumerations.H   (revision 8678)
+++ FL/Enumerations.H   (arbetskopia)
@@ -292,7 +292,12 @@
       If the widget returns 1, it will receive the data in the immediately 
       following FL_PASTE event.
    */
-  FL_DND_RELEASE       = 23
+  FL_DND_RELEASE       = 23,
+
+  /** The fullscreen state of the window has changed
+   */
+  FL_FULLSCREEN         = 24
+
 };
 
 /** \name When Conditions */
Index: FL/Fl.H
===================================================================
Index: FL/Fl_Widget.H
===================================================================
--- FL/Fl_Widget.H      (revision 8678)
+++ FL/Fl_Widget.H      (arbetskopia)
@@ -179,6 +179,7 @@
         NO_OVERLAY      = 1<<15,  ///< window not using a hardware overlay 
plane (Fl_Menu_Window)
         GROUP_RELATIVE  = 1<<16,  ///< position this widget relative to the 
parent group, not to the window
         COPIED_TOOLTIP  = 1<<17,  ///< the widget tooltip is internally 
copied, its destruction is handled by the widget
+        FULLSCREEN      = 1<<18,  ///< a fullscreen window (Fl_Window)
         // (space for more flags)
         USERFLAG3       = 1<<29,  ///< reserved for 3rd party extensions
         USERFLAG2       = 1<<30,  ///< reserved for 3rd party extensions
@@ -852,6 +853,9 @@
   static unsigned int label_shortcut(const char *t);
   /* Internal use only. */
   static int test_shortcut(const char*, const bool require_alt = false);
+  /* Internal use only. */
+  void _set_fullscreen() {flags_ |= FULLSCREEN;}
+  void _clear_fullscreen() {flags_ &= ~FULLSCREEN;}
 
   /** Checks if w is a child of this widget.
       \param[in] w potential child widget
Index: FL/names.h
===================================================================
--- FL/names.h  (revision 8678)
+++ FL/names.h  (arbetskopia)
@@ -75,6 +75,7 @@
   "FL_DND_DRAG",
   "FL_DND_LEAVE",
   "FL_DND_RELEASE",
+  "FL_FULLSCREEN"
 };
 
 /**
Index: FL/Fl_Window.H
===================================================================
--- FL/Fl_Window.H      (revision 8678)
+++ FL/Fl_Window.H      (arbetskopia)
@@ -69,6 +69,7 @@
   int minw, minh, maxw, maxh;
   int dw, dh, aspect;
   uchar size_range_set;
+  int no_fullscreen_x, no_fullscreen_y, no_fullscreen_w, no_fullscreen_h;
   // cursor stuff
   Fl_Cursor cursor_default;
   Fl_Color cursor_fg, cursor_bg;
@@ -384,14 +385,23 @@
   /**
     Makes the window completely fill the screen, without any window
     manager border visible.  You must use fullscreen_off() to undo
-    this. This may not work with all window managers.
+    this. Note: If the X window manager does not support 
+    Extended Window Manager Hints, the keyboard will be grabbed. 
   */
   void fullscreen();
   /**
+    Turns off any side effects of fullscreen()
+  */
+  void fullscreen_off();
+  /**
     Turns off any side effects of fullscreen() and does 
     resize(x,y,w,h).
   */
   void fullscreen_off(int,int,int,int);
+  /** 
+    Returns non zero if FULLSCREEN flag is set, 0 otherwise. 
+  */
+  unsigned int fullscreen_active() const { return flags() & FULLSCREEN; }
   /**
     Iconifies the window.  If you call this when shown() is false
     it will show() it as an icon.  If the window is already
Index: test/Makefile
===================================================================
Index: test/CMakeLists.txt
===================================================================
Index: test/fullscreen.cxx
===================================================================
--- test/fullscreen.cxx (revision 8678)
+++ test/fullscreen.cxx (arbetskopia)
@@ -60,6 +60,7 @@
 #include <FL/Fl.H>
 #include <FL/Fl_Single_Window.H>
 #include <FL/Fl_Hor_Slider.H>
+#include <FL/Fl_Input.H>
 #include <FL/Fl_Toggle_Light_Button.H>
 #include <FL/math.h>
 #include <stdio.h>
@@ -68,6 +69,30 @@
 #include <FL/gl.h>
 #include <FL/Fl_Gl_Window.H>
 
+
+class fullscreen_window : public Fl_Single_Window {
+
+  public:
+  fullscreen_window(int W, int H, const char *t=0);
+  int handle (int e);
+  Fl_Toggle_Light_Button *b3;
+
+};
+
+fullscreen_window::fullscreen_window(int W, int H, const char *t) : 
Fl_Single_Window(W, H, t) { 
+
+}
+
+int fullscreen_window::handle(int e) {
+  if (e == FL_FULLSCREEN) {
+    printf("Recieved FL_FULLSCREEN event\n");
+    b3->value(fullscreen_active());
+  }
+  if (Fl_Single_Window::handle(e)) return 1;
+  return 0;
+}
+
+
 class shape_window : public Fl_Gl_Window {
   void draw();
 public:
@@ -161,13 +186,14 @@
     py = w->y();
     pw = w->w();
     ph = w->h();
-#ifndef WIN32//necessary because fullscreen removes border
-       border_button->value(0);
-       border_button->do_callback();
+    w->fullscreen();
+    w->override();
+#ifndef WIN32 // update our border state in case border was turned off
+    border_button->value(w->border());
 #endif
-    w->fullscreen();
   } else {
-    w->fullscreen_off(px,py,pw,ph);
+    //w->fullscreen_off(px,py,pw,ph);
+    w->fullscreen_off();
   }
 }
 
@@ -177,7 +203,7 @@
   exit(0);
 }
 
-#define NUMB 5
+#define NUMB 6
 
 int twowindow = 0;
 int initfull = 0;
@@ -193,7 +219,7 @@
   if (Fl::args(argc,argv,i,arg) < argc)
     Fl::fatal("Options are:\n -2 = 2 windows\n -f = startup 
fullscreen\n%s",Fl::help);
 
-  Fl_Single_Window window(300,300+30*NUMB); window.end();
+  fullscreen_window window(300,300+30*NUMB); window.end();
 
   shape_window sw(10,10,window.w()-20,window.h()-30*NUMB-20);
 #if HAVE_GL
@@ -228,21 +254,24 @@
   b1.callback(double_cb,&sw);
   y+=30;
 
+  Fl_Input i1(50,y,window.w()-60,30, "Input");
+  y+=30;
+
   Fl_Toggle_Light_Button b2(50,y,window.w()-60,30,"Border");
   b2.callback(border_cb,w);
   b2.set();
   border_button = &b2;
   y+=30;
 
-  Fl_Toggle_Light_Button b3(50,y,window.w()-60,30,"FullScreen");
-  b3.callback(fullscreen_cb,w);
+  window.b3 = new Fl_Toggle_Light_Button(50,y,window.w()-60,30,"FullScreen");
+  window.b3->callback(fullscreen_cb,w);
   y+=30;
 
   Fl_Button eb(50,y,window.w()-60,30,"Exit");
   eb.callback(exit_cb);
   y+=30;
 
-  if (initfull) {b3.set(); b3.do_callback();}
+  if (initfull) {window.b3->set(); window.b3->do_callback();}
 
   window.end();
   window.show(argc,argv);
Index: documentation/src/enumerations.dox
===================================================================
--- documentation/src/enumerations.dox  (revision 8678)
+++ documentation/src/enumerations.dox  (arbetskopia)
@@ -57,6 +57,7 @@
 \li FL_DND_LEAVE - The mouse pointer left a widget still dragging
     data. 
 \li FL_DND_RELEASE - Dragged data is about to be dropped. 
+\li FL_FULLSCREEN - The fullscreen state of the window has changed.
 
 
 \section enumerations_when Callback "When" Conditions
Index: documentation/src/events.dox
===================================================================
--- documentation/src/events.dox        (revision 8678)
+++ documentation/src/events.dox        (arbetskopia)
@@ -300,7 +300,14 @@
 the widget. If the widget returns 1, it will receive the data in
 the immediately following \p FL_PASTE event.
 
+\subsection events_fl_fullscreen FL_FULLSCREEN
 
+The application window has been changed from normal to fullscreen, or
+from fullscreen to normal. If you are using a X window manager which
+supports Extended Window Manager Hints, this event will not be
+delivered until the change has actually happened. 
+
+
 \section events_event_xxx Fl::event_*() methods
 
 FLTK keeps the information about the most recent event in
_______________________________________________
fltk-bugs mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk-bugs

Reply via email to