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
This commit is contained in:
parent
8cd98f5236
commit
08ce2e07d3
@ -3,7 +3,7 @@
|
||||
//
|
||||
// Enumerations 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. Distribution and use rights are outlined in
|
||||
// the file "COPYING" which should have been included with this file. If this
|
||||
@ -293,7 +293,10 @@ enum Fl_Event { // events
|
||||
/** The screen configuration (number, positions) was changed.
|
||||
Use Fl::add_handler() to be notified of this event.
|
||||
*/
|
||||
FL_SCREEN_CONFIGURATION_CHANGED = 24
|
||||
FL_SCREEN_CONFIGURATION_CHANGED = 24,
|
||||
/** The fullscreen state of the window has changed
|
||||
*/
|
||||
FL_FULLSCREEN = 25
|
||||
};
|
||||
|
||||
/** \name When Conditions */
|
||||
|
@ -3,7 +3,7 @@
|
||||
//
|
||||
// Widget 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. Distribution and use rights are outlined in
|
||||
// the file "COPYING" which should have been included with this file. If this
|
||||
@ -170,6 +170,7 @@ protected:
|
||||
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
|
||||
@ -843,6 +844,9 @@ public:
|
||||
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
|
||||
|
@ -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. Distribution and use rights are outlined in
|
||||
// the file "COPYING" which should have been included with this file. If this
|
||||
@ -49,6 +49,10 @@ class Fl_X;
|
||||
class FL_EXPORT Fl_Window : public Fl_Group {
|
||||
|
||||
static char *default_xclass_;
|
||||
#if FLTK_ABI_VERSION < 10302
|
||||
static // when these members are static, ABI compatibility with 1.3.0 is respected
|
||||
#endif
|
||||
int no_fullscreen_x, no_fullscreen_y, no_fullscreen_w, no_fullscreen_h;
|
||||
|
||||
friend class Fl_X;
|
||||
Fl_X *i; // points at the system-specific stuff
|
||||
@ -65,6 +69,8 @@ class FL_EXPORT Fl_Window : public Fl_Group {
|
||||
Fl_Color cursor_fg, cursor_bg;
|
||||
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
|
||||
Fl_Window(const Fl_Window&);
|
||||
@ -375,14 +381,26 @@ public:
|
||||
/**
|
||||
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
|
||||
|
@ -67,6 +67,7 @@ const char * const fl_eventnames[] =
|
||||
"FL_DND_LEAVE",
|
||||
"FL_DND_RELEASE",
|
||||
"FL_SCREEN_CONFIGURATION_CHANGED",
|
||||
"FL_FULLSCREEN"
|
||||
};
|
||||
|
||||
/**
|
||||
|
1
FL/x.H
1
FL/x.H
@ -160,6 +160,7 @@ public:
|
||||
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()
|
||||
|
@ -27,7 +27,7 @@ The FLTK version number is stored in a number of compile-time constants:
|
||||
|
||||
\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 @@ following events are currently defined:
|
||||
\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
|
||||
|
@ -300,6 +300,20 @@ The user has released the mouse button dropping data into
|
||||
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
|
||||
|
||||
|
@ -781,6 +781,8 @@ static handler_link *handlers = 0;
|
||||
- \ref FL_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 FL_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
|
||||
|
@ -50,6 +50,12 @@ void Fl_Window::_Fl_Window() {
|
||||
resizable(0);
|
||||
size_range_set = 0;
|
||||
minw = maxw = minh = maxh = 0;
|
||||
#if FLTK_ABI_VERSION >= 10302
|
||||
no_fullscreen_x = 0;
|
||||
no_fullscreen_y = 0;
|
||||
no_fullscreen_w = w();
|
||||
no_fullscreen_h = h();
|
||||
#endif
|
||||
callback((Fl_Callback*)default_callback);
|
||||
}
|
||||
|
||||
|
@ -31,6 +31,13 @@
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#if FLTK_ABI_VERSION < 10302
|
||||
int Fl_Window::no_fullscreen_x = 0;
|
||||
int Fl_Window::no_fullscreen_y = 0;
|
||||
int Fl_Window::no_fullscreen_w = 0;
|
||||
int Fl_Window::no_fullscreen_h = 0;
|
||||
#endif
|
||||
|
||||
void Fl_Window::border(int b) {
|
||||
if (b) {
|
||||
if (border()) return;
|
||||
@ -51,39 +58,44 @@ void Fl_Window::border(int b) {
|
||||
#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 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();
|
||||
no_fullscreen_x = x();
|
||||
no_fullscreen_y = y();
|
||||
no_fullscreen_w = w();
|
||||
no_fullscreen_h = h();
|
||||
if (shown() && !(flags() & Fl_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,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(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$".
|
||||
//
|
||||
|
@ -931,6 +931,10 @@ void fl_open_callback(void (*cb)(const char *)) {
|
||||
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();
|
||||
}
|
||||
@ -939,6 +943,9 @@ void fl_open_callback(void (*cb)(const char *)) {
|
||||
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();
|
||||
}
|
||||
@ -1914,6 +1921,22 @@ static void q_set_window_title(NSWindow *nsw, const char * name, const char *mi
|
||||
|
||||
@end
|
||||
|
||||
void Fl_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();
|
||||
Fl::handle(FL_FULLSCREEN, this);
|
||||
}
|
||||
|
||||
void Fl_Window::fullscreen_off_x(int X, int Y, int W, int H) {
|
||||
_clear_fullscreen();
|
||||
hide();
|
||||
resize(X, Y, W, H);
|
||||
show();
|
||||
Fl::handle(FL_FULLSCREEN, this);
|
||||
}
|
||||
|
||||
/*
|
||||
* go ahead, create that (sub)window
|
||||
@ -2030,6 +2053,13 @@ void Fl_X::make(Fl_Window* w)
|
||||
x->gc = 0;
|
||||
|
||||
NSRect crect;
|
||||
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;
|
||||
}
|
||||
crect.origin.x = w->x();
|
||||
crect.origin.y = main_screen_height - (w->y() + w->h());
|
||||
crect.size.width=w->w();
|
||||
|
@ -42,6 +42,15 @@ extern void *fl_capture;
|
||||
#endif
|
||||
|
||||
void Fl::grab(Fl_Window* win) {
|
||||
#if USE_X11
|
||||
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;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (win) {
|
||||
if (!grab_) {
|
||||
#ifdef WIN32
|
||||
@ -51,8 +60,9 @@ void Fl::grab(Fl_Window* win) {
|
||||
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,
|
||||
@ -62,7 +72,7 @@ void Fl::grab(Fl_Window* win) {
|
||||
0,
|
||||
fl_event_time);
|
||||
XGrabKeyboard(fl_display,
|
||||
fl_xid(first_window()),
|
||||
xid,
|
||||
1,
|
||||
GrabModeAsync,
|
||||
GrabModeAsync,
|
||||
@ -78,7 +88,10 @@ void Fl::grab(Fl_Window* win) {
|
||||
#elif defined(__APPLE__)
|
||||
fl_capture = 0;
|
||||
#else
|
||||
// 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:
|
||||
|
@ -1315,6 +1315,11 @@ int Fl_X::fake_X_wm(const Fl_Window* w,int &X,int &Y, int &bt,int &bx, int &by)
|
||||
X+=xoff;
|
||||
Y+=yoff;
|
||||
|
||||
if (w->flags() & Fl_Widget::FULLSCREEN) {
|
||||
X = Y = 0;
|
||||
bx = by = bt = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1365,6 +1370,58 @@ void Fl_Window::resize(int X,int Y,int W,int H) {
|
||||
}
|
||||
}
|
||||
|
||||
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 Fl_Window::fullscreen_x() {
|
||||
_set_fullscreen();
|
||||
make_fullscreen(this, fl_xid(this), x(), y(), w(), h());
|
||||
Fl::handle(FL_FULLSCREEN, this);
|
||||
}
|
||||
|
||||
void Fl_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);
|
||||
Fl::handle(FL_FULLSCREEN, this);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
@ -1494,18 +1551,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;
|
||||
}
|
||||
@ -1561,6 +1626,18 @@ Fl_X* Fl_X::make(Fl_Window* w) {
|
||||
);
|
||||
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;
|
||||
|
||||
@ -1576,7 +1653,7 @@ Fl_X* Fl_X::make(Fl_Window* w) {
|
||||
// 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();
|
||||
|
148
src/Fl_x.cxx
148
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <FL/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;
|
||||
@ -142,47 +143,61 @@ static void screen_init() {
|
||||
num_screens = count;
|
||||
}
|
||||
|
||||
#elif HAVE_XINERAMA
|
||||
# include <X11/extensions/Xinerama.h>
|
||||
#else
|
||||
|
||||
// Screen data...
|
||||
static XineramaScreenInfo *screens;
|
||||
static float dpi[16][2];
|
||||
#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];
|
||||
|
||||
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;
|
||||
}
|
||||
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 { // ! XineramaIsActive()
|
||||
num_screens = 1;
|
||||
int mm = DisplayWidthMM(fl_display, fl_screen);
|
||||
dpi[0][0] = mm ? Fl::w()*25.4f/mm : 0.0f;
|
||||
mm = DisplayHeightMM(fl_display, fl_screen);
|
||||
dpi[0][1] = mm ? Fl::h()*25.4f/mm : dpi[0][0];
|
||||
}
|
||||
}
|
||||
#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 ? Fl::w()*25.4f/mm : 0.0f;
|
||||
mm = DisplayHeightMM(fl_display, fl_screen);
|
||||
dpi[1] = mm ? Fl::h()*25.4f/mm : dpi[0];
|
||||
}
|
||||
|
||||
#endif // WIN32
|
||||
|
||||
#ifndef FL_DOXYGEN
|
||||
@ -297,20 +312,11 @@ void Fl::screen_xywh(int &X, int &Y, int &W, int &H, int n) {
|
||||
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
|
||||
}
|
||||
@ -372,16 +378,11 @@ void Fl::screen_dpi(float &h, float &v, int n)
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -54,8 +54,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
|
||||
@ -118,6 +121,27 @@ void shape_window::draw() {
|
||||
|
||||
#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("Received 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());
|
||||
@ -155,13 +179,14 @@ void fullscreen_cb(Fl_Widget *o, void *p) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -171,7 +196,7 @@ void exit_cb(Fl_Widget *, void *) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
#define NUMB 5
|
||||
#define NUMB 6
|
||||
|
||||
int twowindow = 0;
|
||||
int initfull = 0;
|
||||
@ -187,9 +212,10 @@ int main(int argc, char **argv) {
|
||||
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
|
||||
sw.mode(FL_RGB);
|
||||
#endif
|
||||
@ -222,21 +248,24 @@ int main(int argc, char **argv) {
|
||||
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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user