From 105c6eb2116ab5db0157b272a22243bba1ae50ef Mon Sep 17 00:00:00 2001 From: "Owen W. Taylor" Date: Thu, 20 Aug 2015 13:58:07 +0200 Subject: Fix crash when struts change during grab operation Since meta_workspace_invalidate_work_area() frees the edges workspace->screen_edges and workspace->monitor_edges, we must clean up our cached edge resistance data when the invalidate_work_area() is called on the active workspace, or when the workspace changes. Make the computation of the edge resistance data lazy so that it will be recomputed the next time we try to access it. meta_display_compute_resistance_and_snapping_edges() is made private to edge-resistance.c Invaliding the data when active workspace changes also will improve correctness for edge resistance when the current workspace changes during a grab operation. (Even with this fix we still don't try to handle window positions changing during a grab operation; that can't cause a crash since, unlike screen and monitor edges, the window edges are freshly allocated, it will just cause slight oddness in that corner case.) Root cause tracked down due to much effort by Jon Nettleton. https://bugzilla.gnome.org/show_bug.cgi?id=608800 --- src/core/edge-resistance.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'src/core/edge-resistance.c') diff --git a/src/core/edge-resistance.c b/src/core/edge-resistance.c index 51e77d54..aa4fcb6a 100644 --- a/src/core/edge-resistance.c +++ b/src/core/edge-resistance.c @@ -63,6 +63,8 @@ struct MetaEdgeResistanceData ResistanceDataForAnEdge bottom_data; }; +static void compute_resistance_and_snapping_edges (MetaDisplay *display); + /* !WARNING!: this function can return invalid indices (namely, either -1 or * edges->len); this is by design, but you need to remember this. */ @@ -550,7 +552,9 @@ apply_edge_resistance_to_each_side (MetaDisplay *display, gboolean modified; int new_left, new_right, new_top, new_bottom; - g_assert (display->grab_edge_resistance_data != NULL); + if (display->grab_edge_resistance_data == NULL) + compute_resistance_and_snapping_edges (display); + edge_data = display->grab_edge_resistance_data; if (auto_snap) @@ -671,7 +675,8 @@ meta_display_cleanup_edges (MetaDisplay *display) MetaEdgeResistanceData *edge_data = display->grab_edge_resistance_data; GHashTable *edges_to_be_freed; - g_assert (edge_data != NULL); + if (edge_data == NULL) /* Not currently cached */ + return; /* We first need to clean out any window edges */ edges_to_be_freed = g_hash_table_new_full (g_direct_hash, g_direct_equal, @@ -938,8 +943,8 @@ initialize_grab_edge_resistance_data (MetaDisplay *display) edge_data->bottom_data.keyboard_buildup = 0; } -void -meta_display_compute_resistance_and_snapping_edges (MetaDisplay *display) +static void +compute_resistance_and_snapping_edges (MetaDisplay *display) { GList *stacked_windows; GList *cur_window_iter; @@ -952,6 +957,11 @@ meta_display_compute_resistance_and_snapping_edges (MetaDisplay *display) */ GSList *rem_windows, *rem_win_stacking; + g_assert (display->grab_window != NULL); + meta_topic (META_DEBUG_WINDOW_OPS, + "Computing edges to resist-movement or snap-to for %s.\n", + display->grab_window->desc); + /* * 1st: Get the list of relevant windows, from bottom to top */ -- cgit v1.2.1