summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>2023-11-04 11:30:45 +0100
committerManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>2023-11-05 19:42:55 +0100
commit0ae927a00e9ecd45a45edf004e939ab2e5ce4813 (patch)
treed2d585d0d6088494b23529fc43dde9a7cdf330b3
parenta31409f7bbe7db51f63c79b16358d64ae6e2d4bb (diff)
Add Fl_Window::maximize() and Fl_Window::un_maximize()
-rw-r--r--FL/Fl_Widget.H2
-rw-r--r--FL/Fl_Window.H8
-rw-r--r--src/Fl_Window.cxx30
-rw-r--r--src/Fl_Window_Driver.H8
-rw-r--r--src/Fl_Window_Driver.cxx28
-rw-r--r--src/Fl_cocoa.mm14
-rw-r--r--src/Fl_win32.cxx1
-rw-r--r--src/Fl_x.cxx44
-rw-r--r--src/drivers/Cocoa/Fl_Cocoa_Window_Driver.H2
-rw-r--r--src/drivers/Wayland/Fl_Wayland_Window_Driver.H2
-rw-r--r--src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx14
-rw-r--r--src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H3
-rw-r--r--src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx9
-rw-r--r--src/drivers/X11/Fl_X11_Window_Driver.H2
-rw-r--r--test/fullscreen.cxx37
15 files changed, 200 insertions, 4 deletions
diff --git a/FL/Fl_Widget.H b/FL/Fl_Widget.H
index 3036ea582..55282857a 100644
--- a/FL/Fl_Widget.H
+++ b/FL/Fl_Widget.H
@@ -180,7 +180,7 @@ protected:
IMAGE_BOUND = 1<<21, ///< binding the image to the widget will transfer ownership, so that the widget will delete the image when it is no longer needed
DEIMAGE_BOUND = 1<<22, ///< bind the inactive image to the widget, so the widget deletes the image when it is no longer needed
AUTO_DELETE_USER_DATA = 1<<23, ///< automatically call `delete` on the user_data pointer when destroying this widget; if set, user_data must point to a class derived from the class Fl_Callback_User_Data
-
+ MAXIMIZED = 1<<24, ///< a maximized Fl_Window
// Note to devs: add new FLTK core flags above this line (up to 1<<28).
// Three more flags, reserved for user code
diff --git a/FL/Fl_Window.H b/FL/Fl_Window.H
index 18ff8b201..f0d2f5bb0 100644
--- a/FL/Fl_Window.H
+++ b/FL/Fl_Window.H
@@ -92,6 +92,8 @@ private:
Fl_Window(const Fl_Window&);
Fl_Window& operator=(const Fl_Window&);
+ void is_maximized_(bool b);
+
protected:
/** Stores the last window that was made current. See current() const */
@@ -508,6 +510,12 @@ public:
\see void Fl_Window::fullscreen()
*/
void fullscreen_screens(int top, int bottom, int left, int right);
+
+ void maximize();
+ void un_maximize();
+ /** Returns whether the window is currently maximized */
+ unsigned int maximize_active() const { return flags() & MAXIMIZED; }
+public:
/**
Iconifies the window. If you call this when shown() is false
it will show() it as an icon. If the window is already
diff --git a/src/Fl_Window.cxx b/src/Fl_Window.cxx
index f2d527485..18c01151b 100644
--- a/src/Fl_Window.cxx
+++ b/src/Fl_Window.cxx
@@ -922,3 +922,33 @@ bool Fl_Window::is_a_rescale() {return Fl_Window_Driver::is_a_rescale_;}
\li other platforms: 0.
*/
fl_uintptr_t Fl_Window::os_id() { return pWindowDriver->os_id();}
+
+/**
+ Maximizes a top-level window to its current screen.
+
+ This function is effective only with a show()'n, resizable, top-level window.
+ Bordered and borderless windows can be used.
+ \see Fl_Window::un_maximize(), Fl_Window::maximize_active()
+ */
+void Fl_Window::maximize() {
+ if (!shown() || parent() || !resizable() || maximize_active()) return;
+ set_flag(MAXIMIZED);
+ if (border()) pWindowDriver->maximize();
+ else pWindowDriver->Fl_Window_Driver::maximize();
+}
+
+/**
+ Returns a previously maximized top-level window to its previous size.
+ \see Fl_Window::maximize()
+*/
+void Fl_Window::un_maximize() {
+ if (!shown() || parent() || !resizable() || !maximize_active()) return;
+ clear_flag(MAXIMIZED);
+ if (border()) pWindowDriver->un_maximize();
+ else pWindowDriver->Fl_Window_Driver::un_maximize();
+}
+
+void Fl_Window::is_maximized_(bool b) {
+ if (b) set_flag(MAXIMIZED);
+ else clear_flag(MAXIMIZED);
+}
diff --git a/src/Fl_Window_Driver.H b/src/Fl_Window_Driver.H
index 9d7588d9d..983dfd023 100644
--- a/src/Fl_Window_Driver.H
+++ b/src/Fl_Window_Driver.H
@@ -105,6 +105,10 @@ public:
int fullscreen_screen_bottom();
int fullscreen_screen_left();
int fullscreen_screen_right();
+ int* no_fullscreen_x() { return &pWindow->no_fullscreen_x; }
+ int* no_fullscreen_y() { return &pWindow->no_fullscreen_y; }
+ int* no_fullscreen_w() { return &pWindow->no_fullscreen_w; }
+ int* no_fullscreen_h() { return &pWindow->no_fullscreen_h; }
int force_position();
void force_position(int c);
void x(int X);
@@ -154,6 +158,10 @@ public:
virtual void unmap() {}
virtual void fullscreen_on() {}
virtual void fullscreen_off(int /*X*/, int /*Y*/, int /*W*/, int /*H*/) {}
+ virtual void maximize();
+ virtual void un_maximize();
+ virtual bool maximize_needs_hide() { return false; }
+ void is_maximized(bool b) { pWindow->is_maximized_(b); }
virtual void use_border();
virtual void size_range();
virtual void iconize() {}
diff --git a/src/Fl_Window_Driver.cxx b/src/Fl_Window_Driver.cxx
index 25d2554c6..085c9f61e 100644
--- a/src/Fl_Window_Driver.cxx
+++ b/src/Fl_Window_Driver.cxx
@@ -286,6 +286,34 @@ Fl_Window *Fl_Window_Driver::find(fl_uintptr_t xid) {
return 0;
}
+
+void Fl_Window_Driver::maximize() {
+ *no_fullscreen_x() = x();
+ *no_fullscreen_y() = y();
+ *no_fullscreen_w() = w();
+ *no_fullscreen_h() = h();
+ int X,Y,W,H;
+ Fl::screen_work_area(X, Y, W, H, screen_num());
+ int width = decorated_w();
+ int height = decorated_h();
+ int dw = (width - w());
+ int dh = (height - h() - dw);
+ bool need_hide_show = maximize_needs_hide();
+ if (need_hide_show) hide(); // pb may occur in subwindow without this
+ resize(X + dw/2, Y + dh + dw/2, W - dw, H - dh - dw);
+ if (need_hide_show) show();
+}
+
+
+void Fl_Window_Driver::un_maximize() {
+ resize(*no_fullscreen_x(), *no_fullscreen_y(),
+ *no_fullscreen_w(), *no_fullscreen_h());
+ *no_fullscreen_x() = 0;
+ *no_fullscreen_y() = 0;
+ *no_fullscreen_w() = 0;
+ *no_fullscreen_h() = 0;
+}
+
/**
\}
\endcond
diff --git a/src/Fl_cocoa.mm b/src/Fl_cocoa.mm
index 2331a9ff6..7f3eb9117 100644
--- a/src/Fl_cocoa.mm
+++ b/src/Fl_cocoa.mm
@@ -1351,6 +1351,9 @@ static FLWindowDelegate *flwindowdelegate_instance = nil;
window->redraw();
}
#endif
+ if (!window->parent()) {
+ Fl_Cocoa_Window_Driver::driver(window)->is_maximized([nsw isZoomed]);
+ }
fl_unlock_function();
}
- (void)windowDidResignKey:(NSNotification *)notif
@@ -3236,6 +3239,17 @@ void Fl_Cocoa_Window_Driver::fullscreen_on() {
Fl::handle(FL_FULLSCREEN, pWindow);
}
+
+void Fl_Cocoa_Window_Driver::maximize() {
+ [fl_xid(pWindow) performZoom:nil];
+}
+
+
+void Fl_Cocoa_Window_Driver::un_maximize() {
+ [fl_xid(pWindow) performZoom:nil];
+}
+
+
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
static NSUInteger calc_win_style(Fl_Window *win) {
NSUInteger winstyle;
diff --git a/src/Fl_win32.cxx b/src/Fl_win32.cxx
index 0895ca417..809fd0479 100644
--- a/src/Fl_win32.cxx
+++ b/src/Fl_win32.cxx
@@ -1572,6 +1572,7 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar
case WM_SIZE:
if (!window->parent()) {
+ Fl_Window_Driver::driver(window)->is_maximized(wParam == SIZE_MAXIMIZED);
if (wParam == SIZE_MINIMIZED || wParam == SIZE_MAXHIDE) {
Fl::handle(FL_HIDE, window);
} else {
diff --git a/src/Fl_x.cxx b/src/Fl_x.cxx
index 27d4d8b01..642650c5d 100644
--- a/src/Fl_x.cxx
+++ b/src/Fl_x.cxx
@@ -200,6 +200,8 @@ static Atom fl_NET_WM_ICON_NAME; // utf8 aware window icon name
static Atom fl_NET_SUPPORTING_WM_CHECK;
static Atom fl_NET_WM_STATE;
static Atom fl_NET_WM_STATE_FULLSCREEN;
+static Atom fl_NET_WM_STATE_MAXIMIZED_VERT;
+static Atom fl_NET_WM_STATE_MAXIMIZED_HORZ;
static Atom fl_NET_WM_FULLSCREEN_MONITORS;
Atom fl_NET_WORKAREA;
static Atom fl_NET_WM_ICON;
@@ -590,6 +592,8 @@ void open_display_i(Display* d) {
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);
+ fl_NET_WM_STATE_MAXIMIZED_VERT = XInternAtom(d, "_NET_WM_STATE_MAXIMIZED_VERT", 0);
+ fl_NET_WM_STATE_MAXIMIZED_HORZ = XInternAtom(d, "_NET_WM_STATE_MAXIMIZED_HORZ", 0);
fl_NET_WM_FULLSCREEN_MONITORS = XInternAtom(d, "_NET_WM_FULLSCREEN_MONITORS", 0);
fl_NET_WORKAREA = XInternAtom(d, "_NET_WORKAREA", 0);
fl_NET_WM_ICON = XInternAtom(d, "_NET_WM_ICON", 0);
@@ -1947,6 +1951,7 @@ int fl_handle(const XEvent& thisevent)
case PropertyNotify:
if (xevent.xproperty.atom == fl_NET_WM_STATE) {
int fullscreen_state = 0;
+ int maximize_state = 0;
if (xevent.xproperty.state != PropertyDelete) {
unsigned long nitems;
unsigned long *words = 0;
@@ -1955,10 +1960,14 @@ int fl_handle(const XEvent& thisevent)
if (words[item] == fl_NET_WM_STATE_FULLSCREEN) {
fullscreen_state = 1;
}
+ if (words[item] == fl_NET_WM_STATE_MAXIMIZED_HORZ) {
+ maximize_state = 1;
+ }
}
}
if ( words ) { XFree(words); words = 0; }
}
+ Fl_Window_Driver::driver(window)->is_maximized(maximize_state);
if (window->fullscreen_active() && !fullscreen_state) {
window->_clear_fullscreen();
event = FL_FULLSCREEN;
@@ -2318,6 +2327,41 @@ void Fl_X11_Window_Driver::fullscreen_off(int X, int Y, int W, int H) {
}
}
+
+void Fl_X11_Window_Driver::maximize() {
+ if (Fl_X11_Screen_Driver::ewmh_supported()) {
+ send_wm_event(fl_xid(pWindow), fl_NET_WM_STATE, _NET_WM_STATE_ADD,
+ fl_NET_WM_STATE_MAXIMIZED_VERT, fl_NET_WM_STATE_MAXIMIZED_HORZ);
+ } else {
+ *no_fullscreen_x() = x();
+ *no_fullscreen_y() = y();
+ *no_fullscreen_w() = w();
+ *no_fullscreen_h() = h();
+ int X,Y,W,H;
+ Fl::screen_work_area(X, Y, W, H, screen_num());
+ int width, height;
+ decorated_win_size(width, height);
+ int dw = (width - w());
+ int dh = (height - h() - dw);
+ resize(X + dw/2, Y + dh + dw/2, W - dw, H - dh - dw);
+ }
+}
+
+void Fl_X11_Window_Driver::un_maximize() {
+ if (Fl_X11_Screen_Driver::ewmh_supported()) {
+ send_wm_event(fl_xid(pWindow), fl_NET_WM_STATE, _NET_WM_STATE_REMOVE,
+ fl_NET_WM_STATE_MAXIMIZED_VERT, fl_NET_WM_STATE_MAXIMIZED_HORZ);
+ } else {
+ resize(*no_fullscreen_x(), *no_fullscreen_y(),
+ *no_fullscreen_w(), *no_fullscreen_h());
+ *no_fullscreen_x() = 0;
+ *no_fullscreen_y() = 0;
+ *no_fullscreen_w() = 0;
+ *no_fullscreen_h() = 0;
+ }
+}
+
+
////////////////////////////////////////////////////////////////
// A subclass of Fl_Window may call this to associate an X window it
diff --git a/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.H b/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.H
index 163d2e486..3c47c49c9 100644
--- a/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.H
+++ b/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.H
@@ -130,6 +130,8 @@ public:
void unmap() FL_OVERRIDE;
void fullscreen_on() FL_OVERRIDE;
void fullscreen_off(int X, int Y, int W, int H) FL_OVERRIDE;
+ void maximize() FL_OVERRIDE;
+ void un_maximize() FL_OVERRIDE;
void use_border() FL_OVERRIDE;
void size_range() FL_OVERRIDE;
void iconize() FL_OVERRIDE;
diff --git a/src/drivers/Wayland/Fl_Wayland_Window_Driver.H b/src/drivers/Wayland/Fl_Wayland_Window_Driver.H
index b758b658e..b8c7ff9fd 100644
--- a/src/drivers/Wayland/Fl_Wayland_Window_Driver.H
+++ b/src/drivers/Wayland/Fl_Wayland_Window_Driver.H
@@ -114,6 +114,8 @@ public:
void unmap() FL_OVERRIDE;
void fullscreen_on() FL_OVERRIDE;
void fullscreen_off(int X, int Y, int W, int H) FL_OVERRIDE;
+ void maximize() FL_OVERRIDE;
+ void un_maximize() FL_OVERRIDE;
void use_border() FL_OVERRIDE;
void size_range() FL_OVERRIDE;
void iconize() FL_OVERRIDE;
diff --git a/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx b/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx
index 6afc9588f..1c04bf575 100644
--- a/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx
+++ b/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx
@@ -941,6 +941,8 @@ static void handle_configure(struct libdecor_frame *frame,
}
}
+ if (window->fl_win->border())
+ driver->is_maximized(window_state & LIBDECOR_WINDOW_STATE_MAXIMIZED);
if (window_state & LIBDECOR_WINDOW_STATE_MAXIMIZED) state = libdecor_state_new(width,
height);
else state = libdecor_state_new(int(ceil(width/f)*f), int(ceil(height/f)*f));
@@ -2135,3 +2137,15 @@ Fl_Wayland_Plugin *Fl_Wayland_Window_Driver::gl_plugin() {
}
return plugin;
}
+
+
+void Fl_Wayland_Window_Driver::maximize() {
+ struct wld_window *xid = (struct wld_window *)Fl_X::flx(pWindow)->xid;
+ if (xid->kind == DECORATED) libdecor_frame_set_maximized(xid->frame);
+}
+
+
+void Fl_Wayland_Window_Driver::un_maximize() {
+ struct wld_window *xid = (struct wld_window *)Fl_X::flx(pWindow)->xid;
+ if (xid->kind == DECORATED) libdecor_frame_unset_maximized(xid->frame);
+}
diff --git a/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H b/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H
index 4bde200a0..974f9060d 100644
--- a/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H
+++ b/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H
@@ -101,6 +101,9 @@ public:
void unmap() FL_OVERRIDE;
void fullscreen_on() FL_OVERRIDE;
void fullscreen_off(int X, int Y, int W, int H) FL_OVERRIDE;
+ void maximize() FL_OVERRIDE;
+ void un_maximize() FL_OVERRIDE;
+ virtual bool maximize_needs_hide() FL_OVERRIDE { return true; }
void iconize() FL_OVERRIDE;
void decoration_sizes(int *top, int *left, int *right, int *bottom) FL_OVERRIDE;
// --- window cursor stuff
diff --git a/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx b/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx
index 063d24552..e2c0de1d7 100644
--- a/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx
+++ b/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx
@@ -616,6 +616,15 @@ void Fl_WinAPI_Window_Driver::fullscreen_off(int X, int Y, int W, int H) {
}
+void Fl_WinAPI_Window_Driver::maximize() {
+ ShowWindow(fl_xid(pWindow), SW_SHOWMAXIMIZED);
+}
+
+void Fl_WinAPI_Window_Driver::un_maximize() {
+ ShowWindow(fl_xid(pWindow), SW_SHOWNORMAL);
+}
+
+
void Fl_WinAPI_Window_Driver::iconize() {
ShowWindow(fl_xid(pWindow), SW_SHOWMINNOACTIVE);
}
diff --git a/src/drivers/X11/Fl_X11_Window_Driver.H b/src/drivers/X11/Fl_X11_Window_Driver.H
index 57602360d..06c2d89e3 100644
--- a/src/drivers/X11/Fl_X11_Window_Driver.H
+++ b/src/drivers/X11/Fl_X11_Window_Driver.H
@@ -113,6 +113,8 @@ public:
void unmap() FL_OVERRIDE;
void fullscreen_on() FL_OVERRIDE;
void fullscreen_off(int X, int Y, int W, int H) FL_OVERRIDE;
+ void maximize() FL_OVERRIDE;
+ void un_maximize() FL_OVERRIDE;
void use_border() FL_OVERRIDE;
void size_range() FL_OVERRIDE;
void iconize() FL_OVERRIDE;
diff --git a/test/fullscreen.cxx b/test/fullscreen.cxx
index 23de9e76d..9d0d776b2 100644
--- a/test/fullscreen.cxx
+++ b/test/fullscreen.cxx
@@ -1,7 +1,6 @@
//
-
//
-// Copyright 1998-2010 by Bill Spitzak and others.
+// Copyright 1998-2023 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
@@ -124,6 +123,8 @@ class fullscreen_window : public Fl_Single_Window {
public:
fullscreen_window(int W, int H, const char *t=0);
int handle (int e) FL_OVERRIDE;
+ void resize(int x, int y, int w, int h) FL_OVERRIDE;
+ Fl_Toggle_Light_Button *b3_maxi;
Fl_Toggle_Light_Button *b3;
Fl_Toggle_Light_Button *b4;
};
@@ -132,6 +133,19 @@ fullscreen_window::fullscreen_window(int W, int H, const char *t) : Fl_Single_Wi
}
+void after_resize(void *data) {
+ Fl::remove_check(after_resize, data);
+ fullscreen_window *win = (fullscreen_window*)data;
+ if (win->maximize_active()) win->b3_maxi->set();
+ else win->b3_maxi->clear();
+ win->b3_maxi->redraw();
+}
+
+void fullscreen_window::resize(int x, int y, int w, int h) {
+ Fl_Single_Window::resize(x,y,w,h);
+ Fl::add_check(after_resize, this);
+};
+
int fullscreen_window::handle(int e) {
if (e == FL_FULLSCREEN) {
// fprintf(stderr, "Received FL_FULLSCREEN event\n");
@@ -163,6 +177,19 @@ void border_cb(Fl_Widget *o, void *p) {
w->border(d);
}
+
+void maximize_cb(Fl_Widget *o, void *p) {
+ Fl_Window *w = (Fl_Window *)p;
+ if (w->maximize_active()) {
+ w->un_maximize();
+ //((Fl_Button*)o)->set();
+ } else {
+ w->maximize();
+ //((Fl_Button*)o)->clear();
+ }
+}
+
+
Fl_Button *border_button;
void fullscreen_cb(Fl_Widget *o, void *p) {
Fl_Window *w = (Fl_Window *)p;
@@ -250,7 +277,7 @@ void exit_cb(Fl_Widget *, void *) {
exit(0);
}
-#define NUMB 8
+#define NUMB 9
int twowindow = 0;
int initfull = 0;
@@ -315,6 +342,10 @@ int main(int argc, char **argv) {
window.b3 = new Fl_Toggle_Light_Button(50,y,window.w()-60,30,"FullScreen");
window.b3->callback(fullscreen_cb,w);
y+=30;
+
+ window.b3_maxi = new Fl_Toggle_Light_Button(50,y,window.w()-60,30,"Maximize");
+ window.b3_maxi->callback(maximize_cb,w);
+ y+=30;
window.b4 = new Fl_Toggle_Light_Button(50,y,window.w()-60,30,"All Screens");
window.b4->callback(allscreens_cb,w);