Merge branch 'restack-gtk4' into 'master'

GDK W32: Ensure correct stacking of popup windows (GTK4)

See merge request GNOME/gtk!902
This commit is contained in:
Matthias Clasen 2019-06-01 19:47:32 +00:00
commit 29252eac6a

View File

@ -1646,6 +1646,27 @@ should_window_be_always_on_top (GdkSurface *window)
return FALSE;
}
static void
restack_children (GdkSurface *window)
{
GList *popup;
for (popup = window->children; popup; popup = popup->next)
{
GdkSurface *child = GDK_SURFACE (popup->data);
/* Windows doesn't have a function to put window A *above* window B.
* Instead we put window A immediately *below* window B,
* then put window B immediately below window A.
* SWP_NOSENDCHANGING prevents our own handler from triggering.
*/
SetWindowPos (GDK_SURFACE_HWND (child), GDK_SURFACE_HWND (window), 0, 0, 0, 0,
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING);
g_print ("Put popup %p (%p) above %p (%p)\n", child, GDK_SURFACE_HWND (child), window, GDK_SURFACE_HWND (window));
SetWindowPos (GDK_SURFACE_HWND (window), GDK_SURFACE_HWND (child), 0, 0, 0, 0,
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER);
}
}
static void
ensure_stacking_on_unminimize (MSG *msg)
{
@ -1687,7 +1708,7 @@ ensure_stacking_on_unminimize (MSG *msg)
if (lowest_transient != NULL)
{
GDK_NOTE (EVENTS,
g_print (" restacking %p above %p",
g_print (" restacking %p below %p",
msg->hwnd, lowest_transient));
SetWindowPos (msg->hwnd, lowest_transient, 0, 0, 0, 0,
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER);
@ -1770,8 +1791,20 @@ ensure_stacking_on_activate_app (MSG *msg,
impl->type_hint == GDK_SURFACE_TYPE_HINT_DIALOG ||
impl->transient_owner != NULL)
{
GdkSurface *child = window;
GdkSurface *owner = impl->transient_owner;
SetWindowPos (msg->hwnd, HWND_TOP, 0, 0, 0, 0,
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER);
/* Bing the whole hierarchy of transients back up */
while (owner != NULL)
{
SetWindowPos (GDK_SURFACE_HWND (owner), GDK_SURFACE_HWND (child), 0, 0, 0, 0,
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER);
restack_children (owner);
child = owner;
owner = GDK_WIN32_SURFACE (owner)->transient_owner;
}
return;
}
@ -1810,7 +1843,7 @@ ensure_stacking_on_activate_app (MSG *msg,
((window_ontop && rover_ontop) || (!window_ontop && !rover_ontop)))
{
GDK_NOTE (EVENTS,
g_print (" restacking %p above %p",
g_print (" restacking %p below %p",
msg->hwnd, rover));
SetWindowPos (msg->hwnd, rover, 0, 0, 0, 0,
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER);
@ -3090,7 +3123,11 @@ gdk_event_translate (MSG *msg,
transient-type windows. */
if (!(old_state & GDK_SURFACE_STATE_ICONIFIED) &&
(new_state & GDK_SURFACE_STATE_ICONIFIED))
ensure_stacking_on_unminimize (msg);
{
ensure_stacking_on_unminimize (msg);
restack_children (window);
}
}
/* Show, New size or position => configure event */
@ -3430,7 +3467,8 @@ gdk_event_translate (MSG *msg,
(LOWORD (msg->wParam) == WA_INACTIVE ? "INACTIVE" : "???"))),
HIWORD (msg->wParam) ? " minimized" : "",
(HWND) msg->lParam));
if (window->surface_type == GDK_SURFACE_POPUP)
if (window->surface_type == GDK_SURFACE_POPUP ||
window->surface_type == GDK_SURFACE_TEMP)
{
/* Popups cannot be activated or de-activated -
* they only support keyboard focus, which GTK
@ -3453,6 +3491,23 @@ gdk_event_translate (MSG *msg,
break;
}
if (LOWORD (msg->wParam) == WA_INACTIVE && msg->lParam != 0)
{
GdkSurface *other_surface = gdk_win32_handle_table_lookup ((HWND) msg->lParam);
if (other_surface != NULL &&
(other_surface->surface_type == GDK_SURFACE_POPUP ||
other_surface->surface_type == GDK_SURFACE_TEMP))
{
/* We're being deactivated in favour of some popup or temp window.
* Since only toplevels can have visual focus, pretend that
* nothing happened.
*/
*ret_valp = 0;
return_val = TRUE;
break;
}
}
if (LOWORD (msg->wParam) == WA_INACTIVE)
gdk_synthesize_surface_state (window, GDK_SURFACE_STATE_FOCUSED, 0);
else
@ -3472,7 +3527,10 @@ gdk_event_translate (MSG *msg,
msg->wParam ? "YES" : "NO",
(gint64) msg->lParam));
if (msg->wParam && GDK_SURFACE_IS_MAPPED (window))
ensure_stacking_on_activate_app (msg, window);
{
ensure_stacking_on_activate_app (msg, window);
restack_children (window);
}
break;
case WM_NCHITTEST:
/* TODO: pass all messages to DwmDefWindowProc() first! */