summaryrefslogtreecommitdiff
path: root/src/Fl_x.cxx
diff options
context:
space:
mode:
authorManolo Gouy <Manolo>2012-03-23 16:47:53 +0000
committerManolo Gouy <Manolo>2012-03-23 16:47:53 +0000
commit08ce2e07d379d6b9925208b5da9323f948b634db (patch)
treecff1ab07cf0952cec8c1cf874ba9bcc7b241a041 /src/Fl_x.cxx
parent8cd98f5236618f8ab9d576e709308b43246bc7ac (diff)
Fix STR#2641: true fullscreen windows that cover all their screen including menu bar, task bar, dock.
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@9299 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'src/Fl_x.cxx')
-rw-r--r--src/Fl_x.cxx148
1 files changed, 148 insertions, 0 deletions
diff --git a/src/Fl_x.cxx b/src/Fl_x.cxx
index 3ee226173..330d363ec 100644
--- a/src/Fl_x.cxx
+++ b/src/Fl_x.cxx
@@ -325,6 +325,9 @@ Atom fl_XaUtf8String;
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,
@@ -623,6 +626,9 @@ void fl_open_display(Display* d) {
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;
@@ -784,6 +790,31 @@ void fl_sendClientMessage(Window window, Atom message,
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:
@@ -1480,6 +1511,31 @@ int fl_handle(const XEvent& thisevent)
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
@@ -1619,6 +1675,75 @@ void Fl_Window::resize(int X,int Y,int W,int H) {
////////////////////////////////////////////////////////////////
+#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 Fl_X::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 Fl_Window::fullscreen_x() {
+ if (Fl_X::ewmh_supported()) {
+ send_wm_state_event(fl_xid(this), 1, fl_NET_WM_STATE_FULLSCREEN);
+ } else {
+ _set_fullscreen();
+ hide();
+ show();
+ /* We want to grab the window, not a widget, so we cannot use Fl::grab */
+ XGrabKeyboard(fl_display, fl_xid(this), 1, GrabModeAsync, GrabModeAsync, fl_event_time);
+ Fl::handle(FL_FULLSCREEN, this);
+ }
+}
+
+void Fl_Window::fullscreen_off_x(int X, int Y, int W, int H) {
+ if (Fl_X::ewmh_supported()) {
+ send_wm_state_event(fl_xid(this), 0, fl_NET_WM_STATE_FULLSCREEN);
+ } else {
+ _clear_fullscreen();
+ /* The grab will be lost when the window is destroyed */
+ hide();
+ resize(X,Y,W,H);
+ show();
+ Fl::handle(FL_FULLSCREEN, this);
+ }
+}
+
+////////////////////////////////////////////////////////////////
+
// A subclass of Fl_Window may call this to associate an X window it
// creates with the Fl_Window:
@@ -1654,6 +1779,7 @@ ExposureMask|StructureNotifyMask
|KeyPressMask|KeyReleaseMask|KeymapStateMask|FocusChangeMask
|ButtonPressMask|ButtonReleaseMask
|EnterWindowMask|LeaveWindowMask
+|PropertyChangeMask
|PointerMotionMask;
void Fl_X::make_xid(Fl_Window* win, XVisualInfo *visual, Colormap colormap)
@@ -1725,6 +1851,16 @@ void Fl_X::make_xid(Fl_Window* win, XVisualInfo *visual, Colormap colormap)
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 && !Fl_X::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;
@@ -1785,6 +1921,12 @@ void Fl_X::make_xid(Fl_Window* win, XVisualInfo *visual, Colormap colormap)
PropModeAppend, (unsigned char*) &net_wm_state_skip_taskbar, 1);
}
+ // If asked for, create fullscreen
+ if (win->flags() & Fl_Widget::FULLSCREEN && Fl_X::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,
@@ -1822,6 +1964,12 @@ void Fl_X::make_xid(Fl_Window* win, XVisualInfo *visual, Colormap colormap)
Fl::e_number = old_event;
win->redraw();
}
+
+ // non-EWMH fullscreen case, need grab
+ if (win->flags() & Fl_Widget::FULLSCREEN && !Fl_X::ewmh_supported()) {
+ XGrabKeyboard(fl_display, xp->xid, 1, GrabModeAsync, GrabModeAsync, fl_event_time);
+ }
+
}
////////////////////////////////////////////////////////////////