From 204cf63805a17df71a3b7b22c3a113e641ba52a7 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Fri, 3 Aug 2001 04:20:27 +0000 Subject: [PATCH] push error trap around configure of withdrawn window, fixes a crash caused 2001-08-03 Havoc Pennington * src/display.c (event_callback): push error trap around configure of withdrawn window, fixes a crash caused by rapidly creating/destroying a window. * src/window.c (recalc_window_features): don't allow shading undecorated windows. * src/wm-tester/main.c: add a program to torture window managers. --- ChangeLog | 17 ++++ README | 24 ++++-- configure.in | 3 +- src/Makefile.am | 2 + src/display.c | 2 + src/run-metacity.sh | 10 ++- src/window.c | 17 +++- src/wm-tester/Makefile.am | 9 +++ src/wm-tester/main.c | 158 ++++++++++++++++++++++++++++++++++++++ 9 files changed, 233 insertions(+), 9 deletions(-) create mode 100644 src/wm-tester/Makefile.am create mode 100644 src/wm-tester/main.c diff --git a/ChangeLog b/ChangeLog index e69de29bb..709156e90 100644 --- a/ChangeLog +++ b/ChangeLog @@ -0,0 +1,17 @@ +2001-08-03 Havoc Pennington + + * src/display.c (event_callback): push error trap around configure + of withdrawn window, fixes a crash caused by rapidly + creating/destroying a window. + + * src/window.c (recalc_window_features): don't allow shading + undecorated windows. + + * src/wm-tester/main.c: add a program to torture window managers. + +2001-08-01 Havoc Pennington + + * src/window.c (recalc_window_features): if a window isn't + resizeable, turn off maximize function. If min size is equal to + max size, turn off resize function. + diff --git a/README b/README index c248cca37..004e48c50 100644 --- a/README +++ b/README @@ -177,12 +177,6 @@ METACITY BUGS, NON-FEATURES, AND CAVEATS - There are probably other ICCCM-compliance issues. - - I know there's at least one race condition involving rapidly - created and destroyed windows that will crash Metacity. I think a - small test app that did a lot of rapid show/hide on a GtkWindow, - in combination with the METACITY_SYNC environment variable and - Metacity in a debugger, would turn this up quickly. - - Window placement is always cascade for now; I want to implement "first fit, falling back to cascade if no fit." (Configurable placement algorithms are stupid though, don't @@ -246,6 +240,24 @@ METACITY BUGS, NON-FEATURES, AND CAVEATS xstuff.c:xstuff_is_compliant_wm() in the panel to get started on how the panel deals with this.) + - If you have "put panel below other windows" turned on + in panel Global Preferences, Miscellaneous tab, you need to change + this to "Put panel on top of other windows." That's because + Metacity uses semantic categories, not the legacy layer system + in the GNOME spec. It treats things in the legacy "dock" layer + as semantic type dock, but if you have the panel set to be + in another layer, Metacity will think it's a normal window. + + You can diagnose this problem because Metacity will put panels in + the wrong place, and Alt+rightclick will let you perform operations + like minimize/maximize, and Alt+leftclick will let you move the panel. + If Metacity has detected that the panel is a panel, then none of + this will be enabled. + + I put a patch in the CVS version of the panel to fix this by + setting the new non-legacy type hint, but a panel with that + patch hasn't been released yet. + FAQ === diff --git a/configure.in b/configure.in index a2dc9807a..c129b3437 100644 --- a/configure.in +++ b/configure.in @@ -2,7 +2,7 @@ AC_INIT(src/display.c) AM_CONFIG_HEADER(config.h) -AM_INIT_AUTOMAKE(metacity, 2.3.1) +AM_INIT_AUTOMAKE(metacity, 2.3.2) GETTEXT_PACKAGE=metacity AC_SUBST(GETTEXT_PACKAGE) @@ -71,6 +71,7 @@ AC_SUBST(HOST_ALIAS) AC_OUTPUT([ Makefile src/Makefile +src/wm-tester/Makefile ]) diff --git a/src/Makefile.am b/src/Makefile.am index 5043c9818..dbd3e1634 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,4 +1,6 @@ +SUBDIRS=wm-tester + INCLUDES=@METACITY_CFLAGS@ -DMETACITY_LIBEXECDIR=\"$(libexecdir)\" -DHOST_ALIAS=\"@HOST_ALIAS@\" metacity_SOURCES= \ diff --git a/src/display.c b/src/display.c index df75a624b..bf3cef5ed 100644 --- a/src/display.c +++ b/src/display.c @@ -825,8 +825,10 @@ event_callback (XEvent *event, meta_verbose ("Configuring withdrawn window to %d,%d %dx%d border %d (some values may not be in mask)\n", xwc.x, xwc.y, xwc.width, xwc.height, xwc.border_width); + meta_error_trap_push (display); XConfigureWindow (display->xdisplay, event->xconfigurerequest.window, xwcm, &xwc); + meta_error_trap_pop (display); } else { diff --git a/src/run-metacity.sh b/src/run-metacity.sh index 0919c9423..db1be58d1 100755 --- a/src/run-metacity.sh +++ b/src/run-metacity.sh @@ -18,10 +18,18 @@ if test -z "$SM_CLIENTS"; then SM_CLIENTS=0 fi +if test -n "$EVIL_TEST"; then + TEST_CLIENT='./wm-tester/wm-tester --evil' +fi + if test -z "$ONLY_WM"; then Xnest -ac :1 -scrns $SCREENS -geometry 640x480 -bw 15 & usleep 500000 + if test -n "$TEST_CLIENT"; then + DISPLAY=:1 $TEST_CLIENT & + fi + if test $CLIENTS != 0; then for I in `seq 1 $CLIENTS`; do DISPLAY=:1 xterm -geometry 25x15 & @@ -40,5 +48,5 @@ if test -z "$ONLY_WM"; then fi if test -z "$ONLY_SETUP"; then - METACITY_DISPLAY=:1 exec unst libtool --mode=execute $DEBUG ./metacity $OPTIONS + METACITY_DEBUG_BUTTON_GRABS=1 METACITY_DISPLAY=:1 exec unst libtool --mode=execute $DEBUG ./metacity $OPTIONS fi diff --git a/src/window.c b/src/window.c index 243f4201c..e13bbd40d 100644 --- a/src/window.c +++ b/src/window.c @@ -2491,6 +2491,8 @@ update_size_hints (MetaWindow *window) window->size_hints.flags |= PWinGravity; } + recalc_window_features (window); + return meta_error_trap_pop (window->display); } @@ -2552,7 +2554,7 @@ update_title (MetaWindow *window) &err); if (err != NULL) { - meta_warning ("WM_NAME property for %s contained stuff we are too dumb to figure out: %s\n", window->desc, err->message); + meta_warning ("WM_NAME property for %s contained stuff window manager is too dumb to figure out: %s\n", window->desc, err->message); g_error_free (err); } @@ -3441,6 +3443,19 @@ recalc_window_features (MetaWindow *window) window->has_maximize_func = FALSE; } + /* If min_size == max_size, then don't allow resize */ + if (window->size_hints.min_width == window->size_hints.max_width && + window->size_hints.min_height == window->size_hints.max_height) + window->has_resize_func = FALSE; + + /* don't allow maximize if we can't resize */ + if (!window->has_resize_func) + window->has_maximize_func = FALSE; + + /* no shading if not decorated */ + if (!window->decorated) + window->has_shade_func = FALSE; + /* FIXME perhaps should ensure if we don't have a shade func, * we aren't shaded, etc. */ diff --git a/src/wm-tester/Makefile.am b/src/wm-tester/Makefile.am new file mode 100644 index 000000000..dc82c646e --- /dev/null +++ b/src/wm-tester/Makefile.am @@ -0,0 +1,9 @@ + +INCLUDES=@METACITY_CFLAGS@ + +wm_tester_SOURCES= \ + main.c + +bin_PROGRAMS=wm-tester + +wm_tester_LDADD= @METACITY_LIBS@ diff --git a/src/wm-tester/main.c b/src/wm-tester/main.c new file mode 100644 index 000000000..9a2da68fe --- /dev/null +++ b/src/wm-tester/main.c @@ -0,0 +1,158 @@ +/* WM tester main() */ + +/* + * Copyright (C) 2001 Havoc Pennington + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include + +#include +#include +#include +#include +#include + +static void set_up_the_evil (void); + +static void +usage (void) +{ + g_print ("wm-tester [--evil]\n"); + exit (0); +} + +int +main (int argc, char **argv) +{ + int i; + gboolean do_evil; + + gtk_init (&argc, &argv); + + do_evil = FALSE; + + i = 1; + while (i < argc) + { + const char *arg = argv[i]; + + if (strcmp (arg, "--help") == 0 || + strcmp (arg, "-h") == 0 || + strcmp (arg, "-?") == 0) + usage (); + else if (strcmp (arg, "--evil") == 0) + do_evil = TRUE; + else + usage (); + + ++i; + } + + /* Be sure some option was provided */ + if (! (do_evil)) + return 1; + + if (do_evil) + set_up_the_evil (); + + gtk_main (); + + return 0; +} + +static GSList *evil_windows = NULL; + +static gint +evil_timeout (gpointer data) +{ + int i; + int n_windows; + int len; + int create_count; + int destroy_count; + + len = g_slist_length (evil_windows); + + if (len > 35) + { + create_count = 2; + destroy_count = 5; + } + else + { + create_count = 5; + destroy_count = 5; + } + + /* Create some windows */ + n_windows = g_random_int_range (0, create_count); + + i = 0; + while (i < n_windows) + { + GtkWidget *w; + GtkWidget *c; + + w = gtk_window_new (GTK_WINDOW_TOPLEVEL); + c = gtk_button_new_with_label ("Evil Window!"); + gtk_container_add (GTK_CONTAINER (w), c); + + gtk_widget_set_uposition (w, + g_random_int_range (0, + gdk_screen_width ()), + g_random_int_range (0, + gdk_screen_height ())); + + gtk_widget_show_all (w); + + evil_windows = g_slist_prepend (evil_windows, w); + + ++i; + } + + /* Destroy some windows */ + if (len > destroy_count) + { + n_windows = g_random_int_range (0, destroy_count); + i = 0; + while (i < n_windows) + { + GtkWidget *w; + + w = g_slist_nth_data (evil_windows, + g_random_int_range (0, len)); + if (w) + { + --len; + evil_windows = g_slist_remove (evil_windows, w); + gtk_widget_destroy (w); + } + + ++i; + } + } + + return TRUE; +} + +static void +set_up_the_evil (void) +{ + g_timeout_add (40, evil_timeout, NULL); +} +