gdk/win32/gdkevents-win32.c Force non-modal transient dialogs to iconify
008-02-05 Cody Russell <cody@jhu.edu> * gdk/win32/gdkevents-win32.c * gdk/win32/gdkwindow-win32.[ch]: Force non-modal transient dialogs to iconify with their parents on Win32. Maintain a list of transient children, and whenever a window is hidden or restored we now do the same thing to all connected transient windows above and below the current window in the chain. See comment under WM_ACTIVATE for the reasons why. (#164537, #371036, #405178) svn path=/branches/gtk-2-10/; revision=19467
This commit is contained in:
committed by
Cody Russell
parent
fab2d2fd64
commit
5183f13feb
10
ChangeLog
10
ChangeLog
@@ -1,3 +1,13 @@
|
||||
2008-02-05 Cody Russell <cody@jhu.edu>
|
||||
|
||||
* gdk/win32/gdkevents-win32.c
|
||||
* gdk/win32/gdkwindow-win32.[ch]: Force non-modal transient dialogs
|
||||
to iconify with their parents on Win32. Maintain a list of transient
|
||||
children, and whenever a window is hidden or restored we now do the
|
||||
same thing to all connected transient windows above and below the
|
||||
current window in the chain. See comment under WM_ACTIVATE for the
|
||||
reasons why. (#164537, #371036, #405178)
|
||||
|
||||
2008-01-16 Matthias Clasen <mclasen@redhat.com>
|
||||
|
||||
Merge from trunk:
|
||||
|
||||
@@ -1335,6 +1335,37 @@ apply_filters (GdkWindow *window,
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
show_window_recurse (GdkWindow *window, gboolean hide_window)
|
||||
{
|
||||
GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
|
||||
GSList *children = impl->transient_children;
|
||||
GdkWindow *child = NULL;
|
||||
|
||||
if (!impl->changing_state)
|
||||
{
|
||||
impl->changing_state = TRUE;
|
||||
|
||||
if (children != NULL)
|
||||
{
|
||||
while (children != NULL)
|
||||
{
|
||||
child = children->data;
|
||||
show_window_recurse (child, hide_window);
|
||||
|
||||
children = g_slist_next (children);
|
||||
}
|
||||
}
|
||||
|
||||
if (!hide_window)
|
||||
ShowWindow (GDK_WINDOW_HWND (window), SW_RESTORE);
|
||||
else
|
||||
ShowWindow (GDK_WINDOW_HWND (window), SW_MINIMIZE);
|
||||
|
||||
impl->changing_state = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_window_is_ancestor (GdkWindow *ancestor,
|
||||
GdkWindow *window)
|
||||
@@ -2896,16 +2927,18 @@ gdk_event_translate (MSG *msg,
|
||||
{
|
||||
SetForegroundWindow (GDK_WINDOW_HWND (impl->transient_owner));
|
||||
}
|
||||
|
||||
if (p_grab_window == window)
|
||||
{
|
||||
gdk_pointer_ungrab (msg->time);
|
||||
}
|
||||
|
||||
if (k_grab_window == window)
|
||||
{
|
||||
gdk_keyboard_ungrab (msg->time);
|
||||
}
|
||||
}
|
||||
|
||||
if (event->any.type == GDK_UNMAP &&
|
||||
p_grab_window == window)
|
||||
gdk_pointer_ungrab (msg->time);
|
||||
|
||||
if (event->any.type == GDK_UNMAP &&
|
||||
k_grab_window == window)
|
||||
gdk_keyboard_ungrab (msg->time);
|
||||
|
||||
return_val = TRUE;
|
||||
break;
|
||||
|
||||
@@ -3402,6 +3435,49 @@ gdk_event_translate (MSG *msg,
|
||||
|
||||
#ifdef HAVE_WINTAB
|
||||
case WM_ACTIVATE:
|
||||
;
|
||||
|
||||
/*
|
||||
* On Windows, transient windows will not have their own taskbar entries.
|
||||
* Because of this, we must hide and restore groups of transients in both
|
||||
* directions. That is, all transient children must be hidden or restored
|
||||
* with this window, but if this window's transient owner also has a
|
||||
* transient owner then this window's transient owner must be hidden/restored
|
||||
* with this one. And etc, up the chain until we hit an ancestor that has no
|
||||
* transient owner.
|
||||
*
|
||||
* It would be a good idea if applications don't chain transient windows
|
||||
* together. There's a limit to how much evil GTK can try to shield you
|
||||
* from.
|
||||
*/
|
||||
GdkWindow *tmp_window = NULL;
|
||||
GdkWindowImplWin32 *tmp_impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
|
||||
|
||||
while (tmp_impl->transient_owner != NULL)
|
||||
{
|
||||
tmp_window = tmp_impl->transient_owner;
|
||||
tmp_impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (tmp_window)->impl);
|
||||
}
|
||||
|
||||
if (tmp_window == NULL)
|
||||
tmp_window = window;
|
||||
|
||||
if (LOWORD (msg->wParam) == WA_INACTIVE && HIWORD (msg->wParam))
|
||||
{
|
||||
if (!tmp_impl->changing_state)
|
||||
{
|
||||
show_window_recurse (tmp_window, TRUE);
|
||||
}
|
||||
}
|
||||
else if (LOWORD (msg->wParam) == WA_ACTIVE && HIWORD (msg->wParam))
|
||||
{
|
||||
if (!tmp_impl->changing_state)
|
||||
{
|
||||
show_window_recurse (tmp_window, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Bring any tablet contexts to the top of the overlap order when
|
||||
* one of our windows is activated.
|
||||
* NOTE: It doesn't seem to work well if it is done in WM_ACTIVATEAPP
|
||||
|
||||
@@ -157,6 +157,9 @@ gdk_window_impl_win32_init (GdkWindowImplWin32 *impl)
|
||||
impl->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
|
||||
impl->extension_events_selected = FALSE;
|
||||
impl->transient_owner = NULL;
|
||||
impl->transient_children = NULL;
|
||||
impl->num_transients = 0;
|
||||
impl->changing_state = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -871,6 +874,7 @@ _gdk_windowing_window_destroy (GdkWindow *window,
|
||||
{
|
||||
GdkWindowObject *private = (GdkWindowObject *)window;
|
||||
GdkWindowImplWin32 *window_impl = GDK_WINDOW_IMPL_WIN32 (private->impl);
|
||||
GSList *tmp;
|
||||
|
||||
g_return_if_fail (GDK_IS_WINDOW (window));
|
||||
|
||||
@@ -880,6 +884,19 @@ _gdk_windowing_window_destroy (GdkWindow *window,
|
||||
if (private->extension_events != 0)
|
||||
_gdk_input_window_destroy (window);
|
||||
|
||||
/* Remove all our transient children */
|
||||
tmp = window_impl->transient_children;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
GdkWindow *child = tmp->data;
|
||||
GdkWindowImplWin32 *child_impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (child)->impl);
|
||||
|
||||
child_impl->transient_owner = NULL;
|
||||
tmp = g_slist_next (tmp);
|
||||
}
|
||||
g_slist_free (window_impl->transient_children);
|
||||
window_impl->transient_children = NULL;
|
||||
|
||||
/* Remove ourself from our transient owner */
|
||||
if (window_impl->transient_owner != NULL)
|
||||
{
|
||||
@@ -1977,6 +1994,8 @@ gdk_window_set_transient_for (GdkWindow *window,
|
||||
{
|
||||
HWND window_id, parent_id;
|
||||
GdkWindowImplWin32 *window_impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
|
||||
GdkWindowImplWin32 *parent_impl = NULL;
|
||||
GSList *item;
|
||||
|
||||
g_return_if_fail (GDK_IS_WINDOW (window));
|
||||
|
||||
@@ -1999,7 +2018,32 @@ gdk_window_set_transient_for (GdkWindow *window,
|
||||
return;
|
||||
}
|
||||
|
||||
window_impl->transient_owner = parent;
|
||||
if (parent == NULL)
|
||||
{
|
||||
GdkWindowImplWin32 *trans_impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window_impl->transient_owner)->impl);
|
||||
if (trans_impl->transient_children != NULL)
|
||||
{
|
||||
item = g_slist_find (trans_impl->transient_children, window);
|
||||
item->data = NULL;
|
||||
trans_impl->transient_children = g_slist_delete_link (trans_impl->transient_children, item);
|
||||
trans_impl->num_transients--;
|
||||
|
||||
if (!trans_impl->num_transients)
|
||||
{
|
||||
trans_impl->transient_children = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
window_impl->transient_owner = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
parent_impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (parent)->impl);
|
||||
|
||||
parent_impl->transient_children = g_slist_append (parent_impl->transient_children, window);
|
||||
parent_impl->num_transients++;
|
||||
window_impl->transient_owner = parent;
|
||||
}
|
||||
|
||||
/* This changes the *owner* of the window, despite the misleading
|
||||
* name. (Owner and parent are unrelated concepts.) At least that's
|
||||
@@ -2964,7 +3008,7 @@ QueryTree (HWND hwnd,
|
||||
gint *nchildren)
|
||||
{
|
||||
guint i, n;
|
||||
HWND child;
|
||||
HWND child = NULL;
|
||||
|
||||
n = 0;
|
||||
do {
|
||||
@@ -3448,7 +3492,7 @@ gdk_window_set_modal_hint (GdkWindow *window,
|
||||
|
||||
private->modal_hint = modal;
|
||||
|
||||
#if 0
|
||||
#if 1
|
||||
/* Not sure about this one.. -- Cody */
|
||||
if (GDK_WINDOW_IS_MAPPED (window))
|
||||
API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window),
|
||||
@@ -3467,6 +3511,9 @@ gdk_window_set_skip_taskbar_hint (GdkWindow *window,
|
||||
|
||||
g_return_if_fail (GDK_IS_WINDOW (window));
|
||||
|
||||
// ### TODO: Need to figure out what to do here.
|
||||
return;
|
||||
|
||||
GDK_NOTE (MISC, g_print ("gdk_window_set_skip_taskbar_hint: %p: %s\n",
|
||||
GDK_WINDOW_HWND (window),
|
||||
skips_taskbar ? "TRUE" : "FALSE"));
|
||||
|
||||
@@ -88,6 +88,9 @@ struct _GdkWindowImplWin32
|
||||
gboolean extension_events_selected;
|
||||
|
||||
GdkWindow *transient_owner;
|
||||
GSList *transient_children;
|
||||
gint num_transients;
|
||||
gboolean changing_state;
|
||||
};
|
||||
|
||||
struct _GdkWindowImplWin32Class
|
||||
|
||||
Reference in New Issue
Block a user