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
This commit is contained in:
parent
bf7e4de688
commit
270b437500
@ -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
|
||||
|
141
src/Fl.cxx
141
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.
|
||||
|
@ -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$".
|
||||
//
|
||||
|
@ -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$".
|
||||
//
|
||||
|
@ -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
|
||||
|
@ -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$".
|
||||
//
|
||||
|
@ -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);
|
||||
|
@ -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$".
|
||||
//
|
||||
|
@ -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);
|
||||
|
@ -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$".
|
||||
//
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user