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.4-feature
Attached file "fltk-1.3.x-fullscreen.patch"...
Link: http://www.fltk.org/str.php?L2641
Version: 1.4-feature
diff -bur fltk-1.3.x-r8732.org/documentation/src/enumerations.dox
fltk-1.3.x-r8732/documentation/src/enumerations.dox
--- fltk-1.3.x-r8732.org/documentation/src/enumerations.dox 2011-05-11
17:49:30.000000000 +0200
+++ fltk-1.3.x-r8732/documentation/src/enumerations.dox 2011-05-26
10:15:39.258959203 +0200
@@ -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
diff -bur fltk-1.3.x-r8732.org/documentation/src/events.dox
fltk-1.3.x-r8732/documentation/src/events.dox
--- fltk-1.3.x-r8732.org/documentation/src/events.dox 2011-05-11
17:49:30.000000000 +0200
+++ fltk-1.3.x-r8732/documentation/src/events.dox 2011-05-26
10:15:39.259959029 +0200
@@ -300,6 +300,13 @@
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
diff -bur fltk-1.3.x-r8732.org/FL/Enumerations.H
fltk-1.3.x-r8732/FL/Enumerations.H
--- fltk-1.3.x-r8732.org/FL/Enumerations.H 2011-05-21 23:55:59.000000000
+0200
+++ fltk-1.3.x-r8732/FL/Enumerations.H 2011-05-26 10:15:39.256959549 +0200
@@ -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 */
diff -bur fltk-1.3.x-r8732.org/FL/Fl_Widget.H fltk-1.3.x-r8732/FL/Fl_Widget.H
--- fltk-1.3.x-r8732.org/FL/Fl_Widget.H 2011-05-26 10:15:26.146232604 +0200
+++ fltk-1.3.x-r8732/FL/Fl_Widget.H 2011-05-26 10:15:53.701455256 +0200
@@ -180,6 +180,7 @@
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
SIMPLE_KEYBOARD = 1<<18, ///< the widget wants simple, consistent
keypresses and not advanced input (like character composition and CJK input)
+ FULLSCREEN = 1<<19, ///< 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
@@ -882,6 +883,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
Endast i fltk-1.3.x-r8732/FL: Fl_Widget.H.orig
diff -bur fltk-1.3.x-r8732.org/FL/Fl_Window.H fltk-1.3.x-r8732/FL/Fl_Window.H
--- fltk-1.3.x-r8732.org/FL/Fl_Window.H 2011-04-15 23:38:05.000000000 +0200
+++ fltk-1.3.x-r8732/FL/Fl_Window.H 2011-05-26 10:15:39.258959203 +0200
@@ -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,15 +385,27 @@
/**
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 On some platforms, this can result in the keyboard being
+ grabbed. The window may also be recreated, meaning hide() and
+ show() will be called.
*/
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
iconified this does nothing.
diff -bur fltk-1.3.x-r8732.org/FL/names.h fltk-1.3.x-r8732/FL/names.h
--- fltk-1.3.x-r8732.org/FL/names.h 2010-11-28 22:06:39.000000000 +0100
+++ fltk-1.3.x-r8732/FL/names.h 2011-05-26 10:15:39.257959376 +0200
@@ -75,6 +75,7 @@
"FL_DND_DRAG",
"FL_DND_LEAVE",
"FL_DND_RELEASE",
+ "FL_FULLSCREEN"
};
/**
diff -bur fltk-1.3.x-r8732.org/src/Fl_cocoa.mm fltk-1.3.x-r8732/src/Fl_cocoa.mm
--- fltk-1.3.x-r8732.org/src/Fl_cocoa.mm 2011-05-26 10:15:26.168228790
+0200
+++ fltk-1.3.x-r8732/src/Fl_cocoa.mm 2011-05-26 10:15:39.255959723 +0200
@@ -649,6 +649,10 @@
{
containsGLsubwindow = contains;
}
+- (BOOL)canBecomeKeyWindow
+{
+ return YES;
+}
@end
@interface FLApplication : NSObject
@@ -1087,6 +1091,10 @@
fl_lock_function();
FLWindow *nsw = (FLWindow*)[notif object];
Fl_Window *window = [nsw getFl_Window];
+ /* Fullscreen windows obscure all other windows so we need to return
+ to a "normal" level when the user switches to another window */
+ if (window->fullscreen_active())
+ [nsw setLevel:NSNormalWindowLevel];
Fl::handle( FL_UNFOCUS, window);
fl_unlock_function();
}
@@ -1095,6 +1103,9 @@
fl_lock_function();
FLWindow *nsw = (FLWindow*)[notif object];
Fl_Window *w = [nsw getFl_Window];
+ /* Restore previous fullscreen level */
+ if (w->fullscreen_active())
+ [nsw setLevel:NSStatusWindowLevel];
if ( w->border() || (!w->modal() && !w->tooltip_window()) ) Fl::handle(
FL_FOCUS, w);
fl_unlock_function();
}
@@ -2087,6 +2098,22 @@
@end
+void fullscreen_x(Fl_Window *w) {
+ w->_set_fullscreen();
+ /* On OS X < 10.6, it is necessary to recreate the window. This is done
+ with hide+show. */
+ w->hide();
+ 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);
+ w->show();
+ Fl::handle(FL_FULLSCREEN, w);
+}
/*
* go ahead, create that (sub)window
@@ -2210,6 +2237,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 = NSStatusWindowLevel;
+ }
NSRect crect;
crect.origin.x = w->x();
crect.origin.y = srect.size.height - (w->y() + w->h());
Endast i fltk-1.3.x-r8732/src: Fl_cocoa.mm.orig
diff -bur fltk-1.3.x-r8732.org/src/Fl_grab.cxx fltk-1.3.x-r8732/src/Fl_grab.cxx
--- fltk-1.3.x-r8732.org/src/Fl_grab.cxx 2011-05-26 10:15:26.147232431
+0200
+++ fltk-1.3.x-r8732/src/Fl_grab.cxx 2011-05-26 10:15:39.250960589 +0200
@@ -51,7 +51,19 @@
extern void *fl_capture;
#endif
+#if !(defined(WIN32) || defined(__APPLE__))
+extern int ewmh_supported(); // from Fl_x.cxx
+#endif
+
void Fl::grab(Fl_Window* win) {
+ Fl_Window *fullscreen_win = NULL;
+ for (Fl_Window *W = Fl::first_window(); W; W = Fl::next_window(W)) {
+ if (W->fullscreen_active()) {
+ fullscreen_win = W;
+ break;
+ }
+ }
+
if (win) {
if (!grab_) {
#ifdef WIN32
@@ -61,8 +73,9 @@
fl_capture = Fl_X::i(first_window())->xid;
Fl_X::i(first_window())->set_key_window();
#else
+ Window xid = fullscreen_win ? fl_xid(fullscreen_win) :
fl_xid(first_window());
XGrabPointer(fl_display,
- fl_xid(first_window()),
+ xid,
1,
ButtonPressMask|ButtonReleaseMask|
ButtonMotionMask|PointerMotionMask,
@@ -72,7 +85,7 @@
0,
fl_event_time);
XGrabKeyboard(fl_display,
- fl_xid(first_window()),
+ xid,
1,
GrabModeAsync,
GrabModeAsync,
@@ -89,7 +102,10 @@
#elif defined(__APPLE__)
fl_capture = 0;
#else
+ // We must keep the grab in the non-EWMH fullscreen case
+ if (!fullscreen_win || ewmh_supported()) {
XUngrabKeyboard(fl_display, fl_event_time);
+ }
XUngrabPointer(fl_display, fl_event_time);
// this flush is done in case the picked menu item goes into
// an infinite loop, so we don't leave the X server locked up:
Endast i fltk-1.3.x-r8732/src: Fl_grab.cxx.orig
diff -bur fltk-1.3.x-r8732.org/src/Fl_win32.cxx
fltk-1.3.x-r8732/src/Fl_win32.cxx
--- fltk-1.3.x-r8732.org/src/Fl_win32.cxx 2011-05-26 10:15:26.165229310
+0200
+++ fltk-1.3.x-r8732/src/Fl_win32.cxx 2011-05-26 10:15:39.252960243 +0200
@@ -1490,6 +1490,11 @@
X+=xoff;
Y+=yoff;
+ if (w->flags() & Fl_Widget::FULLSCREEN) {
+ X = Y = 0;
+ bx = by = bt = 0;
+ }
+
return ret;
}
@@ -1540,6 +1545,58 @@
}
}
+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);
+ DWORD flags = GetWindowLong(xid, GWL_STYLE);
+ flags = flags & ~(WS_THICKFRAME|WS_CAPTION);
+ SetWindowLong(xid, GWL_STYLE, flags);
+ // SWP_NOSENDCHANGING is so that we can override size limits
+ SetWindowPos(xid, HWND_TOP, sx, sy, sw, sh, SWP_NOSENDCHANGING |
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();
+ DWORD style = GetWindowLong(fl_xid(w), GWL_STYLE);
+ // Remove the xid temporarily so that Fl_X::fake_X_wm() behaves like it
+ // does in Fl_X::make().
+ HWND xid = fl_xid(w);
+ Fl_X::i(w)->xid = NULL;
+ 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;
+ }
+ Fl_X::i(w)->xid = xid;
+ // Adjust for decorations (but not if that puts the decorations
+ // outside the screen)
+ if ((X != w->x()) || (Y != w->y())) {
+ X -= bx;
+ Y -= by+bt;
+ }
+ W += bx*2;
+ H += by*2+bt;
+ SetWindowLong(fl_xid(w), GWL_STYLE, style);
+ SetWindowPos(fl_xid(w), 0, X, Y, W, H,
+ SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED);
+ Fl::handle(FL_FULLSCREEN, w);
+}
+
+
////////////////////////////////////////////////////////////////
/*
@@ -1669,18 +1726,26 @@ Fl_X* Fl_X::make(Fl_Window* w) {
int xwm = xp , ywm = yp , bt, bx, by;
switch (fake_X_wm(w, xwm, ywm, bt, bx, by)) {
// No border (used for menus)
- case 0: style |= WS_POPUP;
- styleEx |= WS_EX_TOOLWINDOW;
+ case 0:
+ style |= WS_POPUP;
+ styleEx |= WS_EX_TOOLWINDOW;
break;
// Thin border and title bar
- case 1: style |= WS_DLGFRAME | WS_CAPTION; break;
+ case 1:
+ style |= WS_DLGFRAME | WS_CAPTION;
+ if (!w->modal())
+ style |= WS_SYSMENU | WS_MINIMIZEBOX;
+ break;
// Thick, resizable border and title bar, with maximize button
- case 2: style |= WS_THICKFRAME | WS_MAXIMIZEBOX | WS_CAPTION ; break;
+ case 2:
+ style |= WS_THICKFRAME | WS_SYSMENU | WS_MAXIMIZEBOX | WS_CAPTION;
+ if (!w->modal())
+ style |= WS_MINIMIZEBOX;
+ break;
}
if (by+bt) {
- if (!w->modal()) style |= WS_SYSMENU | WS_MINIMIZEBOX;
wp += 2*bx;
hp += 2*by+bt;
}
@@ -1736,6 +1801,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;
@@ -1753,7 +1830,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();
Endast i fltk-1.3.x-r8732/src: Fl_win32.cxx.orig
diff -bur fltk-1.3.x-r8732.org/src/Fl_Window.cxx
fltk-1.3.x-r8732/src/Fl_Window.cxx
--- fltk-1.3.x-r8732.org/src/Fl_Window.cxx 2011-02-25 09:44:47.000000000
+0100
+++ fltk-1.3.x-r8732/src/Fl_Window.cxx 2011-05-26 10:15:39.250960589 +0200
@@ -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);
}
diff -bur fltk-1.3.x-r8732.org/src/Fl_Window_fullscreen.cxx
fltk-1.3.x-r8732/src/Fl_Window_fullscreen.cxx
--- fltk-1.3.x-r8732.org/src/Fl_Window_fullscreen.cxx 2011-03-12
22:36:21.000000000 +0100
+++ fltk-1.3.x-r8732/src/Fl_Window_fullscreen.cxx 2011-05-26
10:15:39.249960763 +0200
@@ -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: Fl_Window_fullscreen.cxx 8515 2011-03-12 21:36:21Z manolo $".
//
Endast i fltk-1.3.x-r8732/src: Fl_Window_fullscreen.cxx.orig
diff -bur fltk-1.3.x-r8732.org/src/Fl_x.cxx fltk-1.3.x-r8732/src/Fl_x.cxx
--- fltk-1.3.x-r8732.org/src/Fl_x.cxx 2011-05-26 10:15:26.159230350 +0200
+++ fltk-1.3.x-r8732/src/Fl_x.cxx 2011-05-26 10:15:39.253960069 +0200
@@ -338,6 +338,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,
@@ -711,6 +714,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;
@@ -862,6 +868,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 long **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, (unsigned
char**)data)) {
+ return -1;
+ }
+
+ if (actual == None || format != 32) {
+ return -1;
+ }
+
+ return 0;
+}
+
+
////////////////////////////////////////////////////////////////
// Code for copying to clipboard and DnD out of the program:
@@ -1631,6 +1662,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 long *words = 0;
+ if (0 == get_xwinprop(xid, fl_NET_WM_STATE, 64, &nitems, &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
@@ -1789,6 +1845,75 @@
////////////////////////////////////////////////////////////////
+#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 int result = -1;
+
+ if (result == -1) {
+ result = 0;
+ unsigned long nitems;
+ unsigned long *words = 0;
+ if (0 == get_xwinprop(XRootWindow(fl_display, fl_screen),
fl_NET_SUPPORTING_WM_CHECK, 64,
+ &nitems, &words) && nitems == 1) {
+ Window child = words[0];
+ if (0 == get_xwinprop(child, fl_NET_SUPPORTING_WM_CHECK, 64,
+ &nitems, &words) && nitems == 1) {
+ result = (child == words[0]);
+ }
+ }
+ }
+
+ return result;
+}
+
+/* Change an existing window to fullscreen */
+void fullscreen_x(Fl_Window *w) {
+ if (ewmh_supported()) {
+ send_wm_state_event(fl_xid(w), 1, fl_NET_WM_STATE_FULLSCREEN);
+ } else {
+ w->_set_fullscreen();
+ w->hide();
+ w->show();
+ /* We want to grab the window, not a widget, so we cannot use Fl::grab */
+ 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) {
+ if (ewmh_supported()) {
+ send_wm_state_event(fl_xid(w), 0, fl_NET_WM_STATE_FULLSCREEN);
+ } else {
+ w->_clear_fullscreen();
+ /* The grab will be lost when the window is destroyed */
+ w->hide();
+ w->resize(X,Y,W,H);
+ 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:
@@ -1824,6 +1949,7 @@
|KeyPressMask|KeyReleaseMask|KeymapStateMask|FocusChangeMask
|ButtonPressMask|ButtonReleaseMask
|EnterWindowMask|LeaveWindowMask
+|PropertyChangeMask
|PointerMotionMask;
void Fl_X::make_xid(Fl_Window* win, XVisualInfo *visual, Colormap colormap)
@@ -1895,6 +2021,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;
@@ -1954,6 +2090,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,
@@ -2001,6 +2143,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);
+ }
+
}
////////////////////////////////////////////////////////////////
Endast i fltk-1.3.x-r8732/src: Fl_x.cxx.orig
diff -bur fltk-1.3.x-r8732.org/test/fullscreen.cxx
fltk-1.3.x-r8732/test/fullscreen.cxx
--- fltk-1.3.x-r8732.org/test/fullscreen.cxx 2010-12-15 13:11:16.000000000
+0100
+++ fltk-1.3.x-r8732/test/fullscreen.cxx 2011-05-26 10:15:39.258959203
+0200
@@ -60,8 +60,11 @@
#include <FL/Fl.H>
#include <FL/Fl_Single_Window.H>
#include <FL/Fl_Hor_Slider.H>
+#include <FL/Fl_Input.H>
+#include <FL/Fl_Menu_Button.H>
#include <FL/Fl_Toggle_Light_Button.H>
#include <FL/math.h>
+#include <FL/fl_ask.H>
#include <stdio.h>
#if HAVE_GL
@@ -124,6 +127,28 @@
#endif
+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;
+}
+
void sides_cb(Fl_Widget *o, void *p) {
shape_window *sw = (shape_window *)p;
sw->sides = int(((Fl_Slider *)o)->value());
@@ -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();
-#endif
w->fullscreen();
+ w->override();
+#ifndef WIN32 // update our border state in case border was turned off
+ border_button->value(w->border());
+#endif
} 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);
_______________________________________________
fltk-dev mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk-dev