diff options
| author | Manolo Gouy <Manolo> | 2016-03-23 07:08:17 +0000 |
|---|---|---|
| committer | Manolo Gouy <Manolo> | 2016-03-23 07:08:17 +0000 |
| commit | 270b437500552cba0d082363f9124456f16a1fda (patch) | |
| tree | ac7245b95a138a5f64c6e6b8318632fd4dc45075 | |
| parent | bf7e4de688fc1f0e3008049a41c07543a7da0752 (diff) | |
Rewrite Fl_Window::hide() under the driver model.
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3-porting@11402 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
| -rw-r--r-- | FL/Fl_Window_Driver.H | 2 | ||||
| -rw-r--r-- | src/Fl.cxx | 141 | ||||
| -rw-r--r-- | src/Fl_Window.cxx | 4 | ||||
| -rw-r--r-- | src/Fl_Window_Driver.cxx | 40 | ||||
| -rw-r--r-- | src/drivers/Cocoa/Fl_Cocoa_Window_Driver.H | 1 | ||||
| -rw-r--r-- | src/drivers/Cocoa/Fl_Cocoa_Window_Driver.cxx | 16 | ||||
| -rw-r--r-- | src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H | 1 | ||||
| -rw-r--r-- | src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx | 76 | ||||
| -rw-r--r-- | src/drivers/X11/Fl_X11_Window_Driver.H | 1 | ||||
| -rw-r--r-- | src/drivers/X11/Fl_X11_Window_Driver.cxx | 14 | ||||
| -rw-r--r-- | src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H | 3 | ||||
| -rw-r--r-- | src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx | 2 |
12 files changed, 159 insertions, 142 deletions
diff --git a/FL/Fl_Window_Driver.H b/FL/Fl_Window_Driver.H index d625294d5..f386e04f4 100644 --- a/FL/Fl_Window_Driver.H +++ b/FL/Fl_Window_Driver.H @@ -83,6 +83,8 @@ public: virtual void show(); virtual void show_menu(); virtual void resize(int X,int Y,int W,int H) {} + virtual void hide() {} + int hide_common(); // --- window shape stuff void shape_pixmap_(Fl_Image* pixmap); // TODO: check diff --git a/src/Fl.cxx b/src/Fl.cxx index 5e725cfcc..11d0c62ce 100644 --- a/src/Fl.cxx +++ b/src/Fl.cxx @@ -1450,147 +1450,6 @@ int Fl::handle_(int e, Fl_Window* window) return send_handlers(e); } -//////////////////////////////////////////////////////////////// -// hide() destroys the X window, it does not do unmap! - -#if defined(WIN32) -extern void fl_clipboard_notify_retarget(HWND wnd); -extern void fl_update_clipboard(void); -#elif USE_XFT -extern void fl_destroy_xft_draw(Window); -#endif - -void Fl_Window::hide() { -#ifdef WIN32 // platform fix - // STR#3079: if there remains a window and a non-modal window, and the window is deleted, - // the app remains running without any apparent window. - // Bug mechanism: hiding an owner window unmaps the owned (non-modal) window(s) - // but does not delete it(them) in FLTK. - // Fix for it: - // when hiding a window, build list of windows it owns, and do hide/show on them. - int count = 0; - Fl_Window *win, **doit = NULL; - for (win = Fl::first_window(); win && i; win = Fl::next_window(win)) { - if (win->non_modal() && GetWindow(fl_xid(win), GW_OWNER) == i->xid) { - count++; - } - } - if (count) { - doit = new Fl_Window*[count]; - count = 0; - for (win = Fl::first_window(); win && i; win = Fl::next_window(win)) { - if (win->non_modal() && GetWindow(fl_xid(win), GW_OWNER) == i->xid) { - doit[count++] = win; - } - } - } -#endif - clear_visible(); - - if (!shown()) return; - - // remove from the list of windows: - Fl_X* ip = i; - Fl_X** pp = &Fl_X::first; - for (; *pp != ip; pp = &(*pp)->next) if (!*pp) return; - *pp = ip->next; -#ifdef __APPLE__ // platform fix - // MacOS X manages a single pointer per application. Make sure that hiding - // a toplevel window will not leave us with some random pointer shape, or - // worst case, an invisible pointer - if (!parent()) cursor(FL_CURSOR_DEFAULT); -#endif - i = 0; - - // recursively remove any subwindows: - for (Fl_X *wi = Fl_X::first; wi;) { - Fl_Window* W = wi->w; - if (W->window() == this) { - W->hide(); - W->set_visible(); - wi = Fl_X::first; - } else wi = wi->next; - } - - if (this == Fl::modal_) { // we are closing the modal window, find next one: - Fl_Window* W; - for (W = Fl::first_window(); W; W = Fl::next_window(W)) - if (W->modal()) break; - Fl::modal_ = W; - } - - // Make sure no events are sent to this window: - fl_throw_focus(this); - handle(FL_HIDE); - -#if defined(WIN32) - // make sure any custom icons get freed - icons(NULL, 0); - // this little trick keeps the current clipboard alive, even if we are about - // to destroy the window that owns the selection. - if (GetClipboardOwner()==ip->xid) - fl_update_clipboard(); - // Make sure we unlink this window from the clipboard chain - fl_clipboard_notify_retarget(ip->xid); - // Send a message to myself so that I'll get out of the event loop... - PostMessage(ip->xid, WM_APP, 0, 0); - if (ip->private_dc) fl_release_dc(ip->xid, ip->private_dc); - if (ip->xid == fl_window && fl_graphics_driver->gc()) { - fl_release_dc(fl_window, (HDC)fl_graphics_driver->gc()); - fl_window = (HWND)-1; - fl_graphics_driver->gc(0); -# ifdef FLTK_USE_CAIRO - if (Fl::cairo_autolink_context()) Fl::cairo_make_current((Fl_Window*) 0); -# endif - } -#elif defined(__APPLE_QUARTZ__) // PORTME: Fl_Window_Driver - platform window unmapping - Fl_X::q_release_context(ip); - if ( ip->xid == fl_window ) - fl_window = 0; -#endif - - if (ip->region) XDestroyRegion(ip->region); - -#if defined(USE_X11) -# if USE_XFT - fl_destroy_xft_draw(ip->xid); -# endif - // this test makes sure ip->xid has not been destroyed already - if (ip->xid) XDestroyWindow(fl_display, ip->xid); -#elif defined(WIN32) - // this little trickery seems to avoid the popup window stacking problem - HWND p = GetForegroundWindow(); - if (p==GetParent(ip->xid)) { - ShowWindow(ip->xid, SW_HIDE); - ShowWindow(p, SW_SHOWNA); - } - XDestroyWindow(fl_display, ip->xid); - // end of fix for STR#3079 - if (count) { - int ii; - for (ii = 0; ii < count; ii++) doit[ii]->hide(); - for (ii = 0; ii < count; ii++) { - if (ii != 0) doit[0]->show(); // Fix for STR#3165 - doit[ii]->show(); - } - delete[] doit; - } -#elif defined(__APPLE_QUARTZ__) // PORTME: Fl_Window_Driver - platform window unmapping - ip->destroy(); -#elif defined(FL_PORTING) -# pragma message "FL_PORTING: code to destroy a window on screen" -#else -# error unsupported platform -#endif - -#ifdef WIN32 - // Try to stop the annoying "raise another program" behavior - if (non_modal() && Fl::first_window() && Fl::first_window()->shown()) - Fl::first_window()->show(); -#endif - delete ip; -} - // FL_SHOW and FL_HIDE are called whenever the visibility of this widget // or any parent changes. We must correctly map/unmap the system's window. diff --git a/src/Fl_Window.cxx b/src/Fl_Window.cxx index 35c6c1945..df6f97259 100644 --- a/src/Fl_Window.cxx +++ b/src/Fl_Window.cxx @@ -510,6 +510,10 @@ void Fl_Window::resize(int X,int Y,int W,int H) { pWindowDriver->resize(X, Y, W, H); } +void Fl_Window::hide() { + pWindowDriver->hide(); +} + // // End of "$Id$". // diff --git a/src/Fl_Window_Driver.cxx b/src/Fl_Window_Driver.cxx index 40cc7c668..f9dc31c79 100644 --- a/src/Fl_Window_Driver.cxx +++ b/src/Fl_Window_Driver.cxx @@ -21,7 +21,9 @@ #include <config.h> #include <FL/Fl_Window_Driver.H> #include <FL/fl_draw.H> +#include <FL/Fl.H> +extern void fl_throw_focus(Fl_Widget *o); Fl_Window_Driver::Fl_Window_Driver(Fl_Window *win) : pWindow(win) @@ -151,6 +153,44 @@ void Fl_Window_Driver::capture_titlebar_and_borders(Fl_Shared_Image*& top, Fl_Sh top = left = bottom = right = NULL; } + +// This function is available for use by platform-specific, Fl_Window_Driver-derived classes +int Fl_Window_Driver::hide_common() { + pWindow->clear_visible(); + + if (!pWindow->shown()) return 1; + + // remove from the list of windows: + Fl_X* ip = Fl_X::i(pWindow); + Fl_X** pp = &Fl_X::first; + for (; *pp != ip; pp = &(*pp)->next) if (!*pp) return 1; + *pp = ip->next; + + pWindow->i = 0; + + // recursively remove any subwindows: + for (Fl_X *wi = Fl_X::first; wi;) { + Fl_Window* W = wi->w; + if (W->window() == pWindow) { + W->hide(); + W->set_visible(); + wi = Fl_X::first; + } else wi = wi->next; + } + + if (pWindow == Fl::modal_) { // we are closing the modal window, find next one: + Fl_Window* W; + for (W = Fl::first_window(); W; W = Fl::next_window(W)) + if (W->modal()) break; + Fl::modal_ = W; + } + + // Make sure no events are sent to this window: + fl_throw_focus(pWindow); + pWindow->handle(FL_HIDE); + return 0; +} + // // End of "$Id$". // diff --git a/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.H b/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.H index 46428962b..bd5a0e79e 100644 --- a/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.H +++ b/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.H @@ -77,6 +77,7 @@ public: virtual void label(const char *name, const char *mininame); virtual void show(); virtual void resize(int X,int Y,int W,int H); + virtual void hide(); virtual void shape(const Fl_Image* img); // that one is implemented in Fl_Cocoa.mm because it uses Objective-c diff --git a/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.cxx b/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.cxx index 127a84d6d..5d97ac91d 100644 --- a/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.cxx +++ b/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.cxx @@ -223,6 +223,22 @@ void Fl_Cocoa_Window_Driver::shape(const Fl_Image* img) { #endif } + +void Fl_Cocoa_Window_Driver::hide() { + Fl_X* ip = Fl_X::i(pWindow); + // MacOS X manages a single pointer per application. Make sure that hiding + // a toplevel window will not leave us with some random pointer shape, or + // worst case, an invisible pointer + if (ip && !pWindow->parent()) pWindow->cursor(FL_CURSOR_DEFAULT); + if ( hide_common() ) return; + Fl_X::q_release_context(ip); + if ( ip->xid == fl_window ) + fl_window = 0; + if (ip->region) XDestroyRegion(ip->region); + ip->destroy(); + delete ip; +} + // // End of "$Id$". // diff --git a/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H b/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H index 5a2053af8..4d7d8b490 100644 --- a/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H +++ b/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H @@ -82,6 +82,7 @@ public: virtual void show(); virtual void label(const char *name,const char *iname); virtual void resize(int X,int Y,int W,int H); + virtual void hide(); virtual void shape(const Fl_Image* img); virtual void icons(const Fl_RGB_Image *icons[], int count); diff --git a/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx b/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx index 976fbd606..70c254216 100644 --- a/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx +++ b/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx @@ -445,6 +445,82 @@ void Fl_WinAPI_Window_Driver::label(const char *name,const char *iname) { } } + +extern void fl_clipboard_notify_retarget(HWND wnd); +extern void fl_update_clipboard(void); + +void Fl_WinAPI_Window_Driver::hide() { + Fl_X* ip = Fl_X::i(pWindow); + // STR#3079: if there remains a window and a non-modal window, and the window is deleted, + // the app remains running without any apparent window. + // Bug mechanism: hiding an owner window unmaps the owned (non-modal) window(s) + // but does not delete it(them) in FLTK. + // Fix for it: + // when hiding a window, build list of windows it owns, and do hide/show on them. + int count = 0; + Fl_Window *win, **doit = NULL; + for (win = Fl::first_window(); win && ip; win = Fl::next_window(win)) { + if (win->non_modal() && GetWindow(fl_xid(win), GW_OWNER) == ip->xid) { + count++; + } + } + if (count) { + doit = new Fl_Window*[count]; + count = 0; + for (win = Fl::first_window(); win && ip; win = Fl::next_window(win)) { + if (win->non_modal() && GetWindow(fl_xid(win), GW_OWNER) == ip->xid) { + doit[count++] = win; + } + } + } + + if (hide_common()) return; + + // make sure any custom icons get freed + icons(NULL, 0); + // this little trick keeps the current clipboard alive, even if we are about + // to destroy the window that owns the selection. + if (GetClipboardOwner()==ip->xid) + fl_update_clipboard(); + // Make sure we unlink this window from the clipboard chain + fl_clipboard_notify_retarget(ip->xid); + // Send a message to myself so that I'll get out of the event loop... + PostMessage(ip->xid, WM_APP, 0, 0); + if (ip->private_dc) fl_release_dc(ip->xid, ip->private_dc); + if (ip->xid == fl_window && fl_graphics_driver->gc()) { + fl_release_dc(fl_window, (HDC)fl_graphics_driver->gc()); + fl_window = (HWND)-1; + fl_graphics_driver->gc(0); +# ifdef FLTK_USE_CAIRO + if (Fl::cairo_autolink_context()) Fl::cairo_make_current((Fl_Window*) 0); +# endif + } + + if (ip->region) XDestroyRegion(ip->region); + + // this little trickery seems to avoid the popup window stacking problem + HWND p = GetForegroundWindow(); + if (p==GetParent(ip->xid)) { + ShowWindow(ip->xid, SW_HIDE); + ShowWindow(p, SW_SHOWNA); + } + XDestroyWindow(fl_display, ip->xid); + // end of fix for STR#3079 + if (count) { + int ii; + for (ii = 0; ii < count; ii++) doit[ii]->hide(); + for (ii = 0; ii < count; ii++) { + if (ii != 0) doit[0]->show(); // Fix for STR#3165 + doit[ii]->show(); + } + delete[] doit; + } + // Try to stop the annoying "raise another program" behavior + if (pWindow->non_modal() && Fl::first_window() && Fl::first_window()->shown()) + Fl::first_window()->show(); + delete ip; +} + // // End of "$Id$". // diff --git a/src/drivers/X11/Fl_X11_Window_Driver.H b/src/drivers/X11/Fl_X11_Window_Driver.H index 89f8ca457..967b7d0fa 100644 --- a/src/drivers/X11/Fl_X11_Window_Driver.H +++ b/src/drivers/X11/Fl_X11_Window_Driver.H @@ -91,6 +91,7 @@ public: virtual void resize(int X,int Y,int W,int H); virtual void label(const char *name, const char *mininame); virtual void destroy_double_buffer(); + virtual void hide(); virtual void shape(const Fl_Image* img); virtual void icons(const Fl_RGB_Image *icons[], int count); diff --git a/src/drivers/X11/Fl_X11_Window_Driver.cxx b/src/drivers/X11/Fl_X11_Window_Driver.cxx index 0458c2b4f..4f04dba7f 100644 --- a/src/drivers/X11/Fl_X11_Window_Driver.cxx +++ b/src/drivers/X11/Fl_X11_Window_Driver.cxx @@ -19,6 +19,7 @@ #include "../../config_lib.h" #include "Fl_X11_Window_Driver.H" +#include "Fl_Xlib_Graphics_Driver.H" #include <FL/Fl_Shared_Image.H> #include <FL/Fl_Overlay_Window.H> @@ -461,6 +462,19 @@ void Fl_X11_Window_Driver::show_menu() pWindow->Fl_Window::show(); } + +void Fl_X11_Window_Driver::hide() { + Fl_X* ip = Fl_X::i(pWindow); + if (hide_common()) return; + if (ip->region) XDestroyRegion(ip->region); +# if USE_XFT + Fl_Xlib_Graphics_Driver::destroy_xft_draw(ip->xid); +# endif + // this test makes sure ip->xid has not been destroyed already + if (ip->xid) XDestroyWindow(fl_display, ip->xid); + delete ip; +} + // // End of "$Id$". // diff --git a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H index ef225092d..d9f0d7135 100644 --- a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H +++ b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H @@ -44,6 +44,9 @@ public: virtual void *gc() { return gc_; } virtual void gc(void *value); char can_do_alpha_blending(); +#if USE_XFT + static void destroy_xft_draw(Window id); +#endif // --- bitmap stuff Fl_Bitmask create_bitmask(int w, int h, const uchar *array); diff --git a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx index ea2cacbda..c419b4fd6 100644 --- a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx +++ b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx @@ -958,7 +958,7 @@ static XftDraw* draw_overlay; static Window draw_overlay_window; #endif -void fl_destroy_xft_draw(Window id) { +void Fl_Xlib_Graphics_Driver::destroy_xft_draw(Window id) { if (id == draw_window) XftDrawChange(draw_, draw_window = fl_message_window); #if USE_OVERLAY |
