Blob Blame History Raw
From 443608282901a16565ef01e70d3fb1f66beb14f5 Mon Sep 17 00:00:00 2001
From: "Owen W. Taylor" <otaylor@fishsoup.net>
Date: Tue, 8 Jul 2014 21:35:47 -0400
Subject: [PATCH 4/4] Leave windows in place on a crash respawn

When Mutter is restarted and cleans up the window positions
cleanly, we need to add gravity adjustments. We can detect
this easily.

 - Windows started before the window manager (should add
   add gravity adjustments)
 - Replacing a different window manager (should add gravity
   adjustments)
 - A crash (no adjustments needed)

In GNOME the first two cases shouldn't happen in normal
usage, so assume the third case (though that *shouldn't*
happen in normal usage either.)
---
 src/core/display.c        |  4 ++--
 src/core/screen.c         |  2 +-
 src/core/window-private.h |  3 ++-
 src/core/window.c         | 33 ++++++++++++++++++++++++++-------
 4 files changed, 31 insertions(+), 11 deletions(-)

diff --git a/src/core/display.c b/src/core/display.c
index 9ed0f6e..90888c5 100644
--- a/src/core/display.c
+++ b/src/core/display.c
@@ -2613,14 +2613,14 @@ event_callback (XEvent   *event,
               && meta_display_screen_for_root (display, event->xmap.event))
             {
               window = meta_window_new (display, event->xmap.window,
-                                        FALSE);
+                                        FALSE, FALSE);
             }
           break;
         case MapRequest:
           if (window == NULL)
             {
               window = meta_window_new (display, event->xmaprequest.window,
-                                        FALSE);
+                                        FALSE, FALSE);
             }
           /* if frame was receiver it's some malicious send event or something */
           else if (!frame_was_receiver && window)        
diff --git a/src/core/screen.c b/src/core/screen.c
index 6db3ea3..6d8d018 100644
--- a/src/core/screen.c
+++ b/src/core/screen.c
@@ -1093,7 +1093,7 @@ meta_screen_manage_all_windows (MetaScreen *screen)
       WindowInfo *info = list->data;
 
       meta_window_new_with_attrs (screen->display, info->xwindow, TRUE,
-                                  META_COMP_EFFECT_NONE,
+                                  TRUE,
                                   &info->attrs);
     }
   meta_stack_thaw (screen->stack);
diff --git a/src/core/window-private.h b/src/core/window-private.h
index e9f935f..cc77861 100644
--- a/src/core/window-private.h
+++ b/src/core/window-private.h
@@ -481,11 +481,12 @@ struct _MetaWindowClass
 
 MetaWindow* meta_window_new                (MetaDisplay *display,
                                             Window       xwindow,
+                                            gboolean     managing_screen,
                                             gboolean     must_be_viewable);
 MetaWindow* meta_window_new_with_attrs     (MetaDisplay       *display,
                                             Window             xwindow,
+                                            gboolean           managing_screen,
                                             gboolean           must_be_viewable,
-                                            MetaCompEffect     effect,
                                             XWindowAttributes *attrs);
 void        meta_window_unmanage           (MetaWindow  *window,
                                             guint32      timestamp);
diff --git a/src/core/window.c b/src/core/window.c
index 8d221e3..8a290f3 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -40,6 +40,7 @@
 #include "keybindings-private.h"
 #include "ui.h"
 #include "place.h"
+#include <meta/main.h>
 #include "session.h"
 #include <meta/prefs.h>
 #include "resizepopup.h"
@@ -659,6 +660,7 @@ maybe_leave_show_desktop_mode (MetaWindow *window)
 MetaWindow*
 meta_window_new (MetaDisplay *display,
                  Window       xwindow,
+                 gboolean     managing_screen,
                  gboolean     must_be_viewable)
 {
   XWindowAttributes attrs;
@@ -682,8 +684,8 @@ meta_window_new (MetaDisplay *display,
           return NULL;
        }
       window = meta_window_new_with_attrs (display, xwindow,
+                                           managing_screen,
                                            must_be_viewable,
-                                           META_COMP_EFFECT_CREATE,
                                            &attrs);
    }
   else
@@ -815,8 +817,8 @@ meta_window_should_attach_to_parent (MetaWindow *window)
 MetaWindow*
 meta_window_new_with_attrs (MetaDisplay       *display,
                             Window             xwindow,
+                            gboolean           managing_screen,
                             gboolean           must_be_viewable,
-                            MetaCompEffect     effect,
                             XWindowAttributes *attrs)
 {
   MetaWindow *window;
@@ -827,6 +829,8 @@ meta_window_new_with_attrs (MetaDisplay       *display,
   MetaMoveResizeFlags flags;
   gboolean has_shape;
   MetaScreen *screen;
+  MetaCompEffect effect =
+    managing_screen ? META_COMP_EFFECT_NONE : META_COMP_EFFECT_CREATE;
 
   g_assert (attrs != NULL);
 
@@ -1425,12 +1429,27 @@ meta_window_new_with_attrs (MetaDisplay       *display,
   else
     window->layer = META_LAYER_OVERRIDE_REDIRECT; /* otherwise set by MetaStack */
 
-  /* Put our state back where it should be,
-   * passing TRUE for is_configure_request, ICCCM says
-   * initial map is handled same as configure request
-   */
   flags =
-    META_IS_CONFIGURE_REQUEST | META_IS_MOVE_ACTION | META_IS_RESIZE_ACTION | META_IS_INITIAL_RESIZE;
+    META_IS_MOVE_ACTION | META_IS_RESIZE_ACTION | META_IS_INITIAL_RESIZE;
+
+  /* ICCCM says initial map is handled same as configure request. When
+   * we are initially managing the screen, we distinguish two cases:
+   *
+   *  Restart: in this case, we put the windows back to the unframed
+   *   position before exiting, so we need to give them gravity
+   *   adjustments.
+   *  Something else: (perhaps a crash) if we didn't exit cleanly, then
+   *   windows will be reparented by the X server so that the client
+   *   origin stays the same, and no frame adjustment is needed.
+   *
+   * We don't have any way to distinguish replacing a different window
+   * manager from respawning on crash, so when we replace a different
+   * window manager, windows will shift onscreen, but this is expected
+   * to only happen in development.
+   */
+  if (!managing_screen || meta_is_restart())
+    flags |= META_IS_CONFIGURE_REQUEST;
+
   if (!window->override_redirect)
     meta_window_move_resize_internal (window,
                                       flags,
-- 
1.9.3