diff options
| author | Manolo Gouy <Manolo> | 2012-03-23 16:47:53 +0000 |
|---|---|---|
| committer | Manolo Gouy <Manolo> | 2012-03-23 16:47:53 +0000 |
| commit | 08ce2e07d379d6b9925208b5da9323f948b634db (patch) | |
| tree | cff1ab07cf0952cec8c1cf874ba9bcc7b241a041 /src/Fl_x.cxx | |
| parent | 8cd98f5236618f8ab9d576e709308b43246bc7ac (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.cxx | 148 |
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); + } + } //////////////////////////////////////////////////////////////// |
