]> Pileus Git - ~andy/gtk/commitdiff
win32: Add custom placements for some window types
authorAlexander Larsson <alexl@redhat.com>
Thu, 27 Oct 2011 14:09:42 +0000 (16:09 +0200)
committerAlexander Larsson <alexl@redhat.com>
Thu, 10 Nov 2011 16:41:06 +0000 (17:41 +0100)
Windows with transients: center on parent
Splash screens: center on monitor
Also properly ignores initial moves of unmapped
windows that are not override redirect or HINT_POS

Fixes bugs #324254 and #612359

gdk/win32/gdkwindow-win32.c
gdk/win32/gdkwindow-win32.h

index 2b3317860fca2e75115de8340f7645537ebdebdb..35ec5a6545bfce6bdfe6a4d65d8f64c516251e5c 100644 (file)
@@ -442,6 +442,7 @@ _gdk_win32_display_create_window_impl (GdkDisplay    *display,
   GdkWindowImplWin32 *impl;
   const gchar *title;
   wchar_t *wtitle;
+  gboolean override_redirect;
   gint window_width, window_height;
   gint offset_x = 0, offset_y = 0;
   gint x, y;
@@ -469,8 +470,12 @@ _gdk_win32_display_create_window_impl (GdkDisplay    *display,
       g_assert (attributes->y == window->y);
       remaining_mask &= ~GDK_WA_Y;
     }
+  override_redirect = FALSE;
   if ((attributes_mask & GDK_WA_NOREDIR) != 0)
-    remaining_mask &= ~GDK_WA_NOREDIR;
+    {
+      override_redirect = !!attributes->override_redirect;
+      remaining_mask &= ~GDK_WA_NOREDIR;
+    }
 
   if ((remaining_mask & ~(GDK_WA_WMCLASS|GDK_WA_VISUAL|GDK_WA_CURSOR|GDK_WA_TITLE|GDK_WA_TYPE_HINT)) != 0)
     g_warning ("_gdk_window_impl_new: uexpected attribute 0x%X",
@@ -486,6 +491,7 @@ _gdk_win32_display_create_window_impl (GdkDisplay    *display,
     g_assert (gdk_screen_get_system_visual (screen) == attributes->visual);
 
   impl->extension_events_selected = FALSE;
+  impl->override_redirect = override_redirect;
 
   /* wclass is not any longer set always, but if is ... */
   if ((attributes_mask & GDK_WA_WMCLASS) == GDK_WA_WMCLASS)
@@ -623,6 +629,9 @@ _gdk_win32_display_create_window_impl (GdkDisplay    *display,
 # endif
 
     }
+  GetWindowRect (GDK_WINDOW_HWND (window), &rect);
+  impl->initial_x = rect.left;
+  impl->initial_y = rect.top;
 
   g_object_ref (window);
   gdk_win32_handle_table_insert (&GDK_WINDOW_HWND (window), window);
@@ -898,6 +907,7 @@ show_window_internal (GdkWindow *window,
                       gboolean   already_mapped,
                      gboolean   deiconify)
 {
+  GdkWindowImplWin32 *window_impl;
   HWND old_active_window;
   gboolean focus_on_map = FALSE;
   DWORD exstyle;
@@ -960,6 +970,76 @@ show_window_internal (GdkWindow *window,
       return;
     }
 
+  /* For initial map of "normal" windows we want to emulate WM window
+   * positioning behaviour, which means: 
+   * + Use user specified position if GDK_HINT_POS or GDK_HINT_USER_POS
+   * otherwise:
+   * + default to the initial CW_USEDEFAULT placement,
+   *   no matter if the user moved the window before showing it.
+   * + Certain window types and hints have more elaborate positioning
+   *   schemes.
+   */
+  window_impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
+  if (!already_mapped &&
+      GDK_WINDOW_TYPE (window) == GDK_WINDOW_TOPLEVEL &&
+      (window_impl->hint_flags & (GDK_HINT_POS | GDK_HINT_USER_POS)) == 0 &&
+      !window_impl->override_redirect)
+    {
+      gboolean center = FALSE;
+      RECT window_rect, center_on_rect;
+      int x, y;
+
+      x = window_impl->initial_x;
+      y = window_impl->initial_y;
+
+      if (window_impl->type_hint == GDK_WINDOW_TYPE_HINT_SPLASHSCREEN)
+       {
+         HMONITOR monitor;
+         MONITORINFO mi;
+
+         monitor = MonitorFromWindow (GDK_WINDOW_HWND (window), MONITOR_DEFAULTTONEAREST);
+         mi.cbSize = sizeof (mi);
+         if (monitor && GetMonitorInfo (monitor, &mi))
+           center_on_rect = mi.rcMonitor;
+         else
+           {
+             center_on_rect.left = 0;
+             center_on_rect.right = 0;
+             center_on_rect.right = GetSystemMetrics (SM_CXSCREEN);
+             center_on_rect.bottom = GetSystemMetrics (SM_CYSCREEN);
+           }
+         center = TRUE;
+       }
+      else if (window_impl->transient_owner != NULL &&
+              GDK_WINDOW_IS_MAPPED (window_impl->transient_owner))
+       {
+         GdkWindow *owner = window_impl->transient_owner;
+         /* Center on transient parent */
+         center_on_rect.left = owner->x;
+         center_on_rect.top = owner->y;
+         center_on_rect.right = center_on_rect.left + owner->width;
+         center_on_rect.bottom = center_on_rect.top + owner->height;
+         _gdk_win32_adjust_client_rect (GDK_WINDOW (owner), &center_on_rect);
+         center = TRUE;
+       }
+
+      if (center)
+       {
+         window_rect.left = 0;
+         window_rect.top = 0;
+         window_rect.right = window->width;
+         window_rect.bottom = window->height;
+         _gdk_win32_adjust_client_rect (window, &window_rect);
+
+         x = center_on_rect.left + ((center_on_rect.right - center_on_rect.left) - (window_rect.right - window_rect.left)) / 2;
+         y = center_on_rect.top + ((center_on_rect.bottom - center_on_rect.top) - (window_rect.bottom - window_rect.top)) / 2;
+       }
+
+      API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), NULL,
+                              x, y, 0, 0,
+                              SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER));
+    }
+
   if (window->state & GDK_WINDOW_STATE_FULLSCREEN)
     {
       gdk_window_fullscreen (window);
@@ -2068,9 +2148,13 @@ static void
 gdk_win32_window_set_override_redirect (GdkWindow *window,
                                  gboolean   override_redirect)
 {
+  GdkWindowImplWin32 *window_impl;
+
   g_return_if_fail (GDK_IS_WINDOW (window));
 
-  g_warning ("gdk_window_set_override_redirect not implemented");
+  window_impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
+
+  window_impl->override_redirect = !!override_redirect;
 }
 
 static void
index 648ae116d0bf0513673732d130eefd66d7e96486..c393814ec0c16f09d0fad2419be29c35bca7e8b2 100644 (file)
@@ -76,8 +76,12 @@ struct _GdkWindowImplWin32
   gint       num_transients;
   gboolean   changing_state;
 
+  gint initial_x;
+  gint initial_y;
+
   guint no_bg : 1;
   guint inhibit_configure : 1;
+  guint override_redirect : 1;
 
   cairo_surface_t *cairo_surface;
   HDC              hdc;