diff options
| -rw-r--r-- | FL/Fl_Widget.H | 2 | ||||
| -rw-r--r-- | FL/Fl_Window.H | 8 | ||||
| -rw-r--r-- | src/Fl_Window.cxx | 30 | ||||
| -rw-r--r-- | src/Fl_Window_Driver.H | 8 | ||||
| -rw-r--r-- | src/Fl_Window_Driver.cxx | 28 | ||||
| -rw-r--r-- | src/Fl_cocoa.mm | 14 | ||||
| -rw-r--r-- | src/Fl_win32.cxx | 1 | ||||
| -rw-r--r-- | src/Fl_x.cxx | 44 | ||||
| -rw-r--r-- | src/drivers/Cocoa/Fl_Cocoa_Window_Driver.H | 2 | ||||
| -rw-r--r-- | src/drivers/Wayland/Fl_Wayland_Window_Driver.H | 2 | ||||
| -rw-r--r-- | src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx | 14 | ||||
| -rw-r--r-- | src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H | 3 | ||||
| -rw-r--r-- | src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx | 9 | ||||
| -rw-r--r-- | src/drivers/X11/Fl_X11_Window_Driver.H | 2 | ||||
| -rw-r--r-- | test/fullscreen.cxx | 37 |
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); |
