Author: manolo
Date: 2012-03-25 10:33:46 -0700 (Sun, 25 Mar 2012)
New Revision: 9301
Log:
Fix STR#2641: true fullscreen windows that cover all their screen including
menu bar, task bar, dock.
Modified:
branches/branch-3.0/documentation/src/enumerations.dox
branches/branch-3.0/documentation/src/events.dox
branches/branch-3.0/include/FL/Enumerations.H
branches/branch-3.0/include/FL/Fl_Widget.H
branches/branch-3.0/include/FL/Fl_Window.H
branches/branch-3.0/include/FL/names.h
branches/branch-3.0/include/FL/x.H
branches/branch-3.0/include/fltk3/Widget.h
branches/branch-3.0/include/fltk3/Window.h
branches/branch-3.0/include/fltk3/enumerations.h
branches/branch-3.0/include/fltk3/names.h
branches/branch-3.0/include/fltk3/x.h
branches/branch-3.0/src/fltk3/Window.cxx
branches/branch-3.0/src/fltk3/Window_fullscreen.cxx
branches/branch-3.0/src/fltk3/cocoa.mm
branches/branch-3.0/src/fltk3/grab.cxx
branches/branch-3.0/src/fltk3/run.cxx
branches/branch-3.0/src/fltk3/screen_xywh.cxx
branches/branch-3.0/src/fltk3/win32.cxx
branches/branch-3.0/src/fltk3/x11.cxx
branches/branch-3.0/test/fullscreen.cxx
Modified: branches/branch-3.0/documentation/src/enumerations.dox
===================================================================
--- branches/branch-3.0/documentation/src/enumerations.dox 2012-03-23
20:36:00 UTC (rev 9300)
+++ branches/branch-3.0/documentation/src/enumerations.dox 2012-03-25
17:33:46 UTC (rev 9301)
@@ -27,7 +27,7 @@
\section enumerations_events Events
-Events are identified by an \p Fl_Event enumeration value. The
+Events are identified by an \ref Fl_Event enumeration value. The
following events are currently defined:
\li FL_NO_EVENT - No event (or an event fltk does not
@@ -57,6 +57,8 @@
\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_SCREEN_CONFIGURATION_CHANGED - The screen configuration (number,
positions) was changed.
+\li FL_FULLSCREEN - The fullscreen state of the window has changed.
\section enumerations_when Callback "When" Conditions
Modified: branches/branch-3.0/documentation/src/events.dox
===================================================================
--- branches/branch-3.0/documentation/src/events.dox 2012-03-23 20:36:00 UTC
(rev 9300)
+++ branches/branch-3.0/documentation/src/events.dox 2012-03-25 17:33:46 UTC
(rev 9301)
@@ -300,7 +300,20 @@
the widget. If the widget returns 1, it will receive the data in
the immediately following \p FL_PASTE event.
+\section events_fl_misc Other events
+\subsection events_fl_screen_config FL_SCREEN_CONFIGURATION_CHANGED
+Sent whenever the screen configuration changes (a screen is added/removed,
+a screen resolution is changed, screens are moved).
+Use Fl::add_handler() to be notified of this 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
Modified: branches/branch-3.0/include/FL/Enumerations.H
===================================================================
--- branches/branch-3.0/include/FL/Enumerations.H 2012-03-23 20:36:00 UTC
(rev 9300)
+++ branches/branch-3.0/include/FL/Enumerations.H 2012-03-25 17:33:46 UTC
(rev 9301)
@@ -95,7 +95,9 @@
FL_DND_ENTER = 20,
FL_DND_DRAG = 21,
FL_DND_LEAVE = 22,
- FL_DND_RELEASE = 23
+ FL_DND_RELEASE = 23,
+ FL_SCREEN_CONFIGURATION_CHANGED = 24,
+ FL_FULLSCREEN = 25
} Fl_Event;
namespace fltk3 {
Modified: branches/branch-3.0/include/FL/Fl_Widget.H
===================================================================
--- branches/branch-3.0/include/FL/Fl_Widget.H 2012-03-23 20:36:00 UTC (rev
9300)
+++ branches/branch-3.0/include/FL/Fl_Widget.H 2012-03-25 17:33:46 UTC (rev
9301)
@@ -134,6 +134,7 @@
NO_OVERLAY = 1<<15,
GROUP_RELATIVE = 1<<16,
COPIED_TOOLTIP = 1<<17,
+ FULLSCREEN = 1<<18,
USERFLAG3 = 1<<29,
USERFLAG2 = 1<<30,
USERFLAG1 = 1<<31
@@ -507,6 +508,13 @@
return ((fltk3::Widget_I*)_p)->test_shortcut();
}
+ void _set_fullscreen() {
+ ((fltk3::Widget_I*)_p)->_set_fullscreen();
+ }
+ void _clear_fullscreen() {
+ ((fltk3::Widget_I*)_p)->_clear_fullscreen();
+ }
+
static unsigned int label_shortcut(const char *t) {
return fltk3::Widget_I::label_shortcut(t);
}
Modified: branches/branch-3.0/include/FL/Fl_Window.H
===================================================================
--- branches/branch-3.0/include/FL/Fl_Window.H 2012-03-23 20:36:00 UTC (rev
9300)
+++ branches/branch-3.0/include/FL/Fl_Window.H 2012-03-25 17:33:46 UTC (rev
9301)
@@ -206,10 +206,28 @@
((fltk3::Window*)_p)->show(argc, argv);
}
+ void fullscreen_x() {
+ ((fltk3::Window*)_p)->fullscreen_x();
+ }
+
+ void fullscreen_off_x() {
+ ((fltk3::Window*)_p)->fullscreen_off_x();
+ }
+
+ void fullscreen_off_x(int X, int Y, int W, int H);
+
void fullscreen() {
((fltk3::Window*)_p)->fullscreen();
}
+ void fullscreen_off() {
+ ((fltk3::Window*)_p)->fullscreen_off();
+ }
+
+ unsigned int fullscreen_active() {
+ return ((fltk3::Window*)_p)->fullscreen_active();
+ }
+
void fullscreen_off(int x, int y, int w, int h) {
((fltk3::Window*)_p)->fullscreen_off(x, y, w, h);
}
Modified: branches/branch-3.0/include/FL/names.h
===================================================================
--- branches/branch-3.0/include/FL/names.h 2012-03-23 20:36:00 UTC (rev
9300)
+++ branches/branch-3.0/include/FL/names.h 2012-03-25 17:33:46 UTC (rev
9301)
@@ -76,6 +76,8 @@
"FL_DND_DRAG",
"FL_DND_LEAVE",
"FL_DND_RELEASE",
+ "FL_SCREEN_CONFIGURATION_CHANGED",
+ "FL_FULLSCREEN"
};
/**
Modified: branches/branch-3.0/include/FL/x.H
===================================================================
--- branches/branch-3.0/include/FL/x.H 2012-03-23 20:36:00 UTC (rev 9300)
+++ branches/branch-3.0/include/FL/x.H 2012-03-25 17:33:46 UTC (rev 9301)
@@ -115,6 +115,7 @@
void flush() {w->flush();}
static void x(Fl_Window* wi, int X) {wi->x(X);}
static void y(Fl_Window* wi, int Y) {wi->y(Y);}
+ static int ewmh_supported();
};
extern FL_EXPORT char fl_override_redirect; // hack into Fl_X::make_xid()
Modified: branches/branch-3.0/include/fltk3/Widget.h
===================================================================
--- branches/branch-3.0/include/fltk3/Widget.h 2012-03-23 20:36:00 UTC (rev
9300)
+++ branches/branch-3.0/include/fltk3/Widget.h 2012-03-25 17:33:46 UTC (rev
9301)
@@ -365,6 +365,7 @@
NO_OVERLAY = 1<<15, ///< window not using a hardware overlay plane
(fltk3::MenuWindow)
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
@@ -879,6 +880,8 @@
/* Internal use only. */
int test_shortcut();
+ void _set_fullscreen() {flags_ |= FULLSCREEN;}
+ void _clear_fullscreen() {flags_ &= ~FULLSCREEN;}
/* Internal use only. */
static unsigned int label_shortcut(const char *t);
/* Internal use only. */
Modified: branches/branch-3.0/include/fltk3/Window.h
===================================================================
--- branches/branch-3.0/include/fltk3/Window.h 2012-03-23 20:36:00 UTC (rev
9300)
+++ branches/branch-3.0/include/fltk3/Window.h 2012-03-25 17:33:46 UTC (rev
9301)
@@ -3,7 +3,7 @@
//
// Window header file for the Fast Light Tool Kit (FLTK).
//
-// Copyright 1998-2010 by Bill Spitzak and others.
+// Copyright 1998-2012 by Bill Spitzak and others.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
@@ -78,9 +78,13 @@
// cursor stuff
fltk3::Cursor cursor_default;
fltk3::Color cursor_fg, cursor_bg;
+ // fullscreen stuff
+ int no_fullscreen_x, no_fullscreen_y, no_fullscreen_w, no_fullscreen_h;
void size_range_();
void _Fl_Window(); // constructor innards
-
+ void fullscreen_x(); // platform-specific part of sending a window to full
screen
+ void fullscreen_off_x(int X, int Y, int W, int H);// platform-specific
part of leaving full screen
+
// unimplemented copy ctor and assignment operator
Window(const Window&);
Window& operator=(const Window&);
@@ -397,14 +401,21 @@
/**
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
Modified: branches/branch-3.0/include/fltk3/enumerations.h
===================================================================
--- branches/branch-3.0/include/fltk3/enumerations.h 2012-03-23 20:36:00 UTC
(rev 9300)
+++ branches/branch-3.0/include/fltk3/enumerations.h 2012-03-25 17:33:46 UTC
(rev 9301)
@@ -298,7 +298,9 @@
/** The screen configuration (number, positions) was changed.
Use fltk3::add_handler() to be notified of this event.
*/
- SCREEN_CONFIGURATION_CHANGED = 24
+ SCREEN_CONFIGURATION_CHANGED = 24,
+ /** The fullscreen state of the window has changed */
+ FULLSCREEN = 25
};
Modified: branches/branch-3.0/include/fltk3/names.h
===================================================================
--- branches/branch-3.0/include/fltk3/names.h 2012-03-23 20:36:00 UTC (rev
9300)
+++ branches/branch-3.0/include/fltk3/names.h 2012-03-25 17:33:46 UTC (rev
9301)
@@ -76,6 +76,7 @@
"fltk3::DND_LEAVE",
"fltk3::DND_RELEASE",
"fltk3::SCREEN_CONFIGURATION_CHANGED",
+ "fltk3::FULLSCREEN"
};
/**
Modified: branches/branch-3.0/include/fltk3/x.h
===================================================================
--- branches/branch-3.0/include/fltk3/x.h 2012-03-23 20:36:00 UTC (rev
9300)
+++ branches/branch-3.0/include/fltk3/x.h 2012-03-25 17:33:46 UTC (rev
9301)
@@ -179,6 +179,7 @@
void flush() {w->flush();}
static void x(fltk3::Window* wi, int X) {wi->x(X);}
static void y(fltk3::Window* wi, int Y) {wi->y(Y);}
+ static int ewmh_supported();
};
extern FLTK3_EXPORT char fl_override_redirect; // hack into Fl_X::make_xid()
Modified: branches/branch-3.0/src/fltk3/Window.cxx
===================================================================
--- branches/branch-3.0/src/fltk3/Window.cxx 2012-03-23 20:36:00 UTC (rev
9300)
+++ branches/branch-3.0/src/fltk3/Window.cxx 2012-03-25 17:33:46 UTC (rev
9301)
@@ -60,6 +60,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((fltk3::Callback*)default_callback);
}
Modified: branches/branch-3.0/src/fltk3/Window_fullscreen.cxx
===================================================================
--- branches/branch-3.0/src/fltk3/Window_fullscreen.cxx 2012-03-23 20:36:00 UTC
(rev 9300)
+++ branches/branch-3.0/src/fltk3/Window_fullscreen.cxx 2012-03-25 17:33:46 UTC
(rev 9301)
@@ -60,39 +60,43 @@
#endif
}
+/* 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 fltk3::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;
- fltk3::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 (fltk3::x()>=sx && fltk3::y()>=sy && fltk3::x()+fltk3::w()<=sx+sw &&
fltk3::y()+fltk3::h()<=sy+sh) {
- sx = fltk3::x(); sy = fltk3::y();
- sw = fltk3::w(); sh = fltk3::h();
+ no_fullscreen_x = x();
+ no_fullscreen_y = y();
+ no_fullscreen_w = w();
+ no_fullscreen_h = h();
+ if (shown() && !(flags() & fltk3::Widget::FULLSCREEN)) {
+ fullscreen_x();
+ } 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,fltk3::w(),fltk3::h());
-#endif
}
void fltk3::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() & fltk3::Widget::FULLSCREEN)) {
+ fullscreen_off_x(X, Y, W, H);
+ } else {
+ clear_flag(FULLSCREEN);
+ }
+ no_fullscreen_x = no_fullscreen_y = no_fullscreen_w = no_fullscreen_h = 0;
}
+void fltk3::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$".
//
Modified: branches/branch-3.0/src/fltk3/cocoa.mm
===================================================================
--- branches/branch-3.0/src/fltk3/cocoa.mm 2012-03-23 20:36:00 UTC (rev
9300)
+++ branches/branch-3.0/src/fltk3/cocoa.mm 2012-03-25 17:33:46 UTC (rev
9301)
@@ -926,6 +926,10 @@
fl_lock_function();
FLWindow *nsw = (FLWindow*)[notif object];
fltk3::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];
fltk3::handle( fltk3::UNFOCUS, window);
fl_unlock_function();
}
@@ -934,6 +938,9 @@
fl_lock_function();
FLWindow *nsw = (FLWindow*)[notif object];
fltk3::Window *w = [nsw getFl_Window];
+ /* Restore previous fullscreen level */
+ if (w->fullscreen_active())
+ [nsw setLevel:NSStatusWindowLevel];
if ( w->border() || (!w->modal() && !w->tooltip_window()) ) fltk3::handle(
fltk3::FOCUS, w);
fl_unlock_function();
}
@@ -1909,7 +1916,23 @@
@end
+void fltk3::Window::fullscreen_x() {
+ _set_fullscreen();
+ /* On OS X < 10.6, it is necessary to recreate the window. This is done
+ with hide+show. */
+ hide();
+ show();
+ fltk3::handle(fltk3::FULLSCREEN, this);
+}
+void fltk3::Window::fullscreen_off_x(int X, int Y, int W, int H) {
+ _clear_fullscreen();
+ hide();
+ resize(X, Y, W, H);
+ show();
+ fltk3::handle(fltk3::FULLSCREEN, this);
+}
+
/*
* go ahead, create that (sub)window
*/
@@ -2025,6 +2048,13 @@
x->gc = 0;
NSRect crect;
+ if (w->flags() & fltk3::Widget::FULLSCREEN) {
+ int sx, sy, sw, sh;
+ fltk3::screen_xywh(sx, sy, sw, sh, w->x(), w->y(), w->w(), w->h());
+ w->resize(sx, sy, sw, sh);
+ winstyle = NSBorderlessWindowMask;
+ winlevel = NSStatusWindowLevel;
+ }
crect.origin.x = w->x();
crect.origin.y = main_screen_height - (w->y() + w->h());
crect.size.width=w->w();
Modified: branches/branch-3.0/src/fltk3/grab.cxx
===================================================================
--- branches/branch-3.0/src/fltk3/grab.cxx 2012-03-23 20:36:00 UTC (rev
9300)
+++ branches/branch-3.0/src/fltk3/grab.cxx 2012-03-25 17:33:46 UTC (rev
9301)
@@ -3,7 +3,7 @@
//
// Grab/release code for the Fast Light Tool Kit (FLTK).
//
-// Copyright 1998-2010 by Bill Spitzak and others.
+// Copyright 1998-2012 by Bill Spitzak and others.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
@@ -51,6 +51,15 @@
#endif
void fltk3::grab(fltk3::Window* win) {
+#if USE_X11
+ fltk3::Window *fullscreen_win = NULL;
+ for (fltk3::Window *W = fltk3::first_window(); W; W = fltk3::next_window(W))
{
+ if (W->fullscreen_active()) {
+ fullscreen_win = W;
+ break;
+ }
+ }
+#endif
if (win) {
if (!grab_) {
#ifdef WIN32
@@ -60,8 +69,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,
@@ -71,7 +81,7 @@
0,
fl_event_time);
XGrabKeyboard(fl_display,
- fl_xid(first_window()),
+ xid,
1,
GrabModeAsync,
GrabModeAsync,
@@ -87,7 +97,10 @@
#elif defined(__APPLE__)
fl_capture = 0;
#else
- XUngrabKeyboard(fl_display, fl_event_time);
+ // We must keep the grab in the non-EWMH fullscreen case
+ if (!fullscreen_win || Fl_X::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:
Modified: branches/branch-3.0/src/fltk3/run.cxx
===================================================================
--- branches/branch-3.0/src/fltk3/run.cxx 2012-03-23 20:36:00 UTC (rev
9300)
+++ branches/branch-3.0/src/fltk3/run.cxx 2012-03-25 17:33:46 UTC (rev
9301)
@@ -787,9 +787,13 @@
them returns non-zero then the event is ignored. Events that cause
this to be called are:
- - fltk3::SHORTCUT events that are not recognized by any widget.
+ - \ref fltk3::SHORTCUT events that are not recognized by any widget.
This lets you provide global shortcut keys.
- - fltk3::SCREEN_CONFIGURATION_CHANGED events.
+ - \ref fltk3::SCREEN_CONFIGURATION_CHANGED events.
+ Under X11, this event requires the libXrandr.so shared library to be
+ loadable at run-time and the X server to implement the RandR extension.
+ - \ref fltk3::FULLSCREEN events sent to a window that enters of leaves
+ fullscreen mode.
- System events that FLTK does not recognize. See fl_xevent.
- \e Some other events when the widget FLTK selected returns
zero from its handle() method. Exactly which ones may change
Modified: branches/branch-3.0/src/fltk3/screen_xywh.cxx
===================================================================
--- branches/branch-3.0/src/fltk3/screen_xywh.cxx 2012-03-23 20:36:00 UTC
(rev 9300)
+++ branches/branch-3.0/src/fltk3/screen_xywh.cxx 2012-03-25 17:33:46 UTC
(rev 9301)
@@ -3,7 +3,7 @@
//
// Screen/monitor bounding box API for the Fast Light Tool Kit (FLTK).
//
-// Copyright 1998-2010 by Bill Spitzak and others.
+// Copyright 1998-2012 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@@ -21,6 +21,7 @@
#include <fltk3/x.h>
#include <config.h>
+#define MAX_SCREENS 16
// Number of screens returned by multi monitor aware API; -1 before init
static int num_screens = -1;
@@ -138,47 +139,61 @@
num_screens = count;
}
-#elif HAVE_XINERAMA
+#else
+
+#if HAVE_XINERAMA
# include <X11/extensions/Xinerama.h>
+#endif
+typedef struct {
+ short x_org;
+ short y_org;
+ short width;
+ short height;
+} FLScreenInfo;
+static FLScreenInfo screens[MAX_SCREENS];
+static float dpi[MAX_SCREENS][2];
-// Screen data...
-static XineramaScreenInfo *screens;
-static float dpi[16][2];
-
static void screen_init() {
if (!fl_display) fl_open_display();
-
+ // FIXME: Rewrite using RandR instead
+#if HAVE_XINERAMA
if (XineramaIsActive(fl_display)) {
- screens = XineramaQueryScreens(fl_display, &num_screens);
- int i;
- // Xlib and Xinerama may disagree on the screen count. Sigh...
- // Use the minimum of the reported counts.
- // Use the previous screen's info for non-existent ones.
- int sc = ScreenCount(fl_display); // Xlib screen count
- for (i=0; i<num_screens; i++) {
- int mm = (i < sc) ? DisplayWidthMM(fl_display, i) : 0;
- dpi[i][0] = mm ? screens[i].width*25.4f/mm : (i > 0) ? dpi[i-1][0] :
0.0f;
- mm = (i < sc) ? DisplayHeightMM(fl_display, i) : 0;
- dpi[i][1] = mm ? screens[i].height*25.4f/mm : (i > 0) ? dpi[i-1][1] :
0.0f;
+ XineramaScreenInfo *xsi = XineramaQueryScreens(fl_display, &num_screens);
+ if (num_screens > MAX_SCREENS) num_screens = MAX_SCREENS;
+
+ /* There's no way to use different DPI for different Xinerama screens. */
+ for (int i=0; i<num_screens; i++) {
+ screens[i].x_org = xsi[i].x_org;
+ screens[i].y_org = xsi[i].y_org;
+ screens[i].width = xsi[i].width;
+ screens[i].height = xsi[i].height;
+
+ int mm = DisplayWidthMM(fl_display, fl_screen);
+ dpi[i][0] = mm ? screens[i].width*25.4f/mm : 0.0f;
+ mm = DisplayHeightMM(fl_display, fl_screen);
+ dpi[i][1] = mm ? screens[i].height*25.4f/mm : 0.0f;
}
- } else { // ! XineramaIsActive()
- num_screens = 1;
- int mm = DisplayWidthMM(fl_display, fl_screen);
- dpi[0][0] = mm ? fltk3::w()*25.4f/mm : 0.0f;
- mm = DisplayHeightMM(fl_display, fl_screen);
- dpi[0][1] = mm ? fltk3::h()*25.4f/mm : dpi[0][0];
+ if (xsi) XFree(xsi);
+ } else
+#endif
+ { // ! XineramaIsActive()
+ num_screens = ScreenCount(fl_display);
+ if (num_screens > MAX_SCREENS) num_screens = MAX_SCREENS;
+
+ for (int i=0; i<num_screens; i++) {
+ screens[i].x_org = 0;
+ screens[i].y_org = 0;
+ screens[i].width = DisplayWidth(fl_display, i);
+ screens[i].height = DisplayHeight(fl_display, i);
+
+ int mm = DisplayWidthMM(fl_display, i);
+ dpi[i][0] = mm ? DisplayWidth(fl_display, i)*25.4f/mm : 0.0f;
+ mm = DisplayHeightMM(fl_display, i);
+ dpi[i][1] = mm ? DisplayHeight(fl_display, i)*25.4f/mm : 0.0f;
+ }
}
}
-#else
-static float dpi[2];
-static void screen_init() {
- num_screens = 1;
- if (!fl_display) fl_open_display();
- int mm = DisplayWidthMM(fl_display, fl_screen);
- dpi[0] = mm ? fltk3::w()*25.4f/mm : 0.0f;
- mm = DisplayHeightMM(fl_display, fl_screen);
- dpi[1] = mm ? fltk3::h()*25.4f/mm : dpi[0];
-}
+
#endif // WIN32
#ifndef FLTK3_DOXYGEN
@@ -292,20 +307,11 @@
W = screens[n].width;
H = screens[n].height;
#else
-#if HAVE_XINERAMA
- if (num_screens > 0 && screens) {
+ if (num_screens > 0) {
X = screens[n].x_org;
Y = screens[n].y_org;
W = screens[n].width;
H = screens[n].height;
- } else
-#endif // HAVE_XINERAMA
- {
- /* Fallback if something is broken (or no Xinerama)... */
- X = 0;
- Y = 0;
- W = DisplayWidth(fl_display, fl_screen);
- H = DisplayHeight(fl_display, fl_screen);
}
#endif // WIN32
}
@@ -367,16 +373,11 @@
h = dpi_h[n];
v = dpi_v[n];
}
-#elif HAVE_XINERAMA
+#else
if (n >= 0 && n < num_screens) {
h = dpi[n][0];
v = dpi[n][1];
}
-#else
- if (n >= 0 && n < num_screens) {
- h = dpi[0];
- v = dpi[1];
- }
#endif // WIN32
}
Modified: branches/branch-3.0/src/fltk3/win32.cxx
===================================================================
--- branches/branch-3.0/src/fltk3/win32.cxx 2012-03-23 20:36:00 UTC (rev
9300)
+++ branches/branch-3.0/src/fltk3/win32.cxx 2012-03-25 17:33:46 UTC (rev
9301)
@@ -1325,6 +1325,11 @@
X+=xoff;
Y+=yoff;
+ if (w->flags() & fltk3::Widget::FULLSCREEN) {
+ X = Y = 0;
+ bx = by = bt = 0;
+ }
+
return ret;
}
@@ -1375,6 +1380,57 @@
}
}
+static void make_fullscreen(fltk3::Window *w, Window xid, int X, int Y, int W,
int H) {
+ int sx, sy, sw, sh;
+ fltk3::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 fltk3::Window::fullscreen_x() {
+ _set_fullscreen();
+ make_fullscreen(this, fl_xid(this), x(), y(), w(), h());
+ fltk3::handle(fltk3::FULLSCREEN, this);
+}
+
+void fltk3::Window::fullscreen_off_x(int X, int Y, int W, int H) {
+ _clear_fullscreen();
+ DWORD style = GetWindowLong(fl_xid(this), 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(this);
+ Fl_X::i(this)->xid = NULL;
+ int wx, wy, bt, bx, by;
+ switch (Fl_X::fake_X_wm(this, wx, wy, bt, bx, by)) {
+ case 0:
+ break;
+ case 1:
+ style |= WS_CAPTION;
+ break;
+ case 2:
+ if (border()) {
+ style |= WS_THICKFRAME | WS_CAPTION;
+ }
+ break;
+ }
+ Fl_X::i(this)->xid = xid;
+ // Adjust for decorations (but not if that puts the decorations
+ // outside the screen)
+ if ((X != x()) || (Y != y())) {
+ X -= bx;
+ Y -= by+bt;
+ }
+ W += bx*2;
+ H += by*2+bt;
+ SetWindowLong(fl_xid(this), GWL_STYLE, style);
+ SetWindowPos(fl_xid(this), 0, X, Y, W, H,
+ SWP_NOACTIVATE | SWP_NOZORDER |
SWP_FRAMECHANGED);
+ fltk3::handle(fltk3::FULLSCREEN, this);
+}
+
////////////////////////////////////////////////////////////////
/*
@@ -1504,18 +1560,26 @@
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;
- break;
+ 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;
}
@@ -1571,6 +1635,18 @@
);
if (lab) free(lab);
+ if (w->flags() & fltk3::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;
@@ -1586,7 +1662,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 :
- (fltk3::grab() || (style & WS_POPUP)) ? SW_SHOWNOACTIVATE :
SW_SHOWNORMAL);
+ (fltk3::grab() || (styleEx & WS_EX_TOOLWINDOW)) ?
SW_SHOWNOACTIVATE : SW_SHOWNORMAL);
// Register all windows for potential drag'n'drop operations
fl_OleInitialize();
Modified: branches/branch-3.0/src/fltk3/x11.cxx
===================================================================
--- branches/branch-3.0/src/fltk3/x11.cxx 2012-03-23 20:36:00 UTC (rev
9300)
+++ branches/branch-3.0/src/fltk3/x11.cxx 2012-03-25 17:33:46 UTC (rev
9301)
@@ -3,7 +3,7 @@
//
// X specific code for the Fast Light Tool Kit (FLTK).
//
-// Copyright 1998-2011 by Bill Spitzak and others.
+// Copyright 1998-2012 by Bill Spitzak and others.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
@@ -336,6 +336,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,
@@ -633,7 +636,10 @@
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;
@@ -794,6 +800,29 @@
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:
@@ -1490,6 +1519,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 = fltk3::FULLSCREEN;
+ }
+ if (!window->fullscreen_active() && fullscreen_state) {
+ window->_set_fullscreen();
+ event = fltk3::FULLSCREEN;
+ }
+ }
+ break;
+
case MotionNotify:
set_event_xy();
# if CONSOLIDATE_MOTION
@@ -1629,6 +1683,74 @@
////////////////////////////////////////////////////////////////
+#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 fltk3::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);
+ fltk3::handle(fltk3::FULLSCREEN, this);
+ }
+}
+
+void fltk3::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();
+ fltk3::handle(fltk3::FULLSCREEN, this);
+ }
+}
+
+////////////////////////////////////////////////////////////////
+
// A subclass of fltk3::Window may call this to associate an X window it
// creates with the fltk3::Window:
@@ -1664,6 +1786,7 @@
|KeyPressMask|KeyReleaseMask|KeymapStateMask|FocusChangeMask
|ButtonPressMask|ButtonReleaseMask
|EnterWindowMask|LeaveWindowMask
+|PropertyChangeMask
|PointerMotionMask;
void Fl_X::make_xid(fltk3::Window* win, XVisualInfo *visual, Colormap colormap)
@@ -1735,6 +1858,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() & fltk3::Widget::FULLSCREEN && !Fl_X::ewmh_supported()) {
+ attr.override_redirect = 1;
+ mask |= CWOverrideRedirect;
+ fltk3::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;
@@ -1795,6 +1928,12 @@
PropModeAppend, (unsigned char*) &net_wm_state_skip_taskbar, 1);
}
+ // If asked for, create fullscreen
+ if (win->flags() & fltk3::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,
@@ -1832,6 +1971,11 @@
fltk3::e_number = old_event;
win->redraw();
}
+ // non-EWMH fullscreen case, need grab
+ if (win->flags() & fltk3::Widget::FULLSCREEN && !Fl_X::ewmh_supported()) {
+ XGrabKeyboard(fl_display, xp->xid, 1, GrabModeAsync, GrabModeAsync,
fl_event_time);
+ }
+
}
////////////////////////////////////////////////////////////////
Modified: branches/branch-3.0/test/fullscreen.cxx
===================================================================
--- branches/branch-3.0/test/fullscreen.cxx 2012-03-23 20:36:00 UTC (rev
9300)
+++ branches/branch-3.0/test/fullscreen.cxx 2012-03-25 17:33:46 UTC (rev
9301)
@@ -34,7 +34,7 @@
// can avoid this by making the fltk3::GLWindow a child of a normal
// window.
//
-// Copyright 1998-2010 by Bill Spitzak and others.
+// Copyright 1998-2012 by Bill Spitzak and others.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
@@ -60,8 +60,10 @@
#include <fltk3/run.h>
#include <fltk3/SingleWindow.h>
#include <fltk3/HorSlider.h>
+#include <fltk3/Input.h>
#include <fltk3/LightButton.h>
#include <fltk3/math.h>
+#include <fltk3/ask.h>
#include <stdio.h>
#if HAVE_GL
@@ -124,6 +126,26 @@
#endif
+class fullscreen_window : public fltk3::SingleWindow {
+ public:
+ fullscreen_window(int W, int H, const char *t=0);
+ int handle (int e);
+ fltk3::LightButton *b3;
+
+};
+
+fullscreen_window::fullscreen_window(int W, int H, const char *t) :
fltk3::SingleWindow(W, H, t) {
+}
+
+int fullscreen_window::handle(int e) {
+ if (e == fltk3::FULLSCREEN) {
+ printf("Received fltk3::FULLSCREEN event\n");
+ b3->value(fullscreen_active());
+ }
+ if (fltk3::SingleWindow::handle(e)) return 1;
+ return 0;
+}
+
void sides_cb(fltk3::Widget *o, void *p) {
shape_window *sw = (shape_window *)p;
sw->sides = int(((fltk3::Slider *)o)->value());
@@ -161,13 +183,13 @@
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();
}
}
@@ -177,7 +199,7 @@
exit(0);
}
-#define NUMB 5
+#define NUMB 6
int twowindow = 0;
int initfull = 0;
@@ -193,9 +215,10 @@
if (fltk3::args(argc,argv,i,arg) < argc)
fltk3::fatal("Options are:\n -2 = 2 windows\n -f = startup
fullscreen\n%s",fltk3::help);
- fltk3::SingleWindow 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
sw.mode(fltk3::RGB);
#endif
@@ -227,22 +250,26 @@
fltk3::LightButton b1(50,y,window.w()-60,30,"Double Buffered");
b1.callback(double_cb,&sw);
y+=30;
+
+ fltk3::Input i1(50,y,window.w()-60,30, "Input");
+ y+=30;
+
fltk3::LightButton b2(50,y,window.w()-60,30,"Border");
b2.callback(border_cb,w);
b2.set();
border_button = &b2;
y+=30;
- fltk3::LightButton b3(50,y,window.w()-60,30,"FullScreen");
- b3.callback(fullscreen_cb,w);
+ window.b3 = new fltk3::LightButton(50,y,window.w()-60,30,"FullScreen");
+ window.b3->callback(fullscreen_cb,w);
y+=30;
fltk3::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-commit mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk-commit