diff --git a/ChangeLog b/ChangeLog index 947b6ef18..d4be81b46 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,28 @@ +2002-04-30 Havoc Pennington + + * src/window.c (recalc_window_features): don't try to decorate + toolbars. + + * src/tools/metacity-window-demo.c: add menu and toolbar tests + + * src/place.c (meta_window_place): only dialogs should be centered + over parent, not anything with transient for set. + + * src/window.c (meta_window_configure_request): become more + fascist about window positioning if workarounds are disabled, and + less fascist if they are enabled. + + * src/metacity.schemas: add a "disable_workarounds" option. Kind + of crack-smoking. But we just can't get all applications + fixed. And I need no-workarounds mode to monitor which apps are + broken and what needs fixing in specs. + + * src/window.c (meta_window_configure_request): always allow + windows to resize themselves + + * src/keybindings.c (reload_modmap): don't filter out Mode_switch, + apparently some people bind window manager shortcuts to that. + 2002-04-30 Havoc Pennington * src/window.c (constrain_position): oops, fix diff --git a/src/keybindings.c b/src/keybindings.c index 7181e971d..5dd2de42d 100644 --- a/src/keybindings.c +++ b/src/keybindings.c @@ -269,19 +269,13 @@ reload_modmap (MetaDisplay *display) while (j < display->keysyms_per_keycode) { - if (syms[j] == XK_Mode_switch) + if (syms[j] == XK_Num_Lock) { - /* This modifier swaps groups */ - /* Mod1Mask is 1 << 3 for example, i.e. the * fourth modifier, i / keyspermod is the modifier * index */ - display->mode_switch_mask |= (1 << ( i / modmap->max_keypermod)); - } - else if (syms[j] == XK_Num_Lock) - { display->num_lock_mask |= (1 << ( i / modmap->max_keypermod)); } else if (syms[j] == XK_Scroll_Lock) diff --git a/src/metacity.schemas b/src/metacity.schemas index e77241801..9b0a5be43 100644 --- a/src/metacity.schemas +++ b/src/metacity.schemas @@ -1173,6 +1173,41 @@ you set + + /schemas/apps/metacity/general/disable_workarounds + /apps/metacity/general/disable_workarounds + metacity + bool + false + + Disable misfeatures that are required by old or broken + applications + + Some applications break specifications in ways that result + in window manager misfeatures. For example, ideally Metacity + would place all dialogs in a consistent position with + respect to their parent window. This requires ignoring + application-specified positions for dialogs. But some + versions of Java/Swing mark their popup menus as dialogs, + so Metacity has to disable dialog positioning to allow + menus to work in broken Java applications. There are + several other examples like this. + + This option puts Metacity in full-on Correct mode, which + perhaps gives a moderately nicer UI if you don't need to run + any broken apps. Sadly, workarounds must be enabled by + default; the real world is an ugly place. + + Some of the workarounds are workarounds for limitations in + the specifications themselves, so sometimes a bug + in no-workarounds mode won't be fixable without + amending a spec. + + + + + + diff --git a/src/place.c b/src/place.c index ae255f730..ade971bc0 100644 --- a/src/place.c +++ b/src/place.c @@ -220,7 +220,9 @@ meta_window_place (MetaWindow *window, * put it at 1/5 down and horizontally centered */ - if (window->xtransient_for != None) + if ((window->type == META_WINDOW_DIALOG || + window->type == META_WINDOW_MODAL_DIALOG) && + window->xtransient_for != None) { /* Center horizontally, at top of parent vertically */ @@ -252,6 +254,10 @@ meta_window_place (MetaWindow *window, } } + /* FIXME UTILITY with transient set should be stacked up + * on the sides of the parent window or something. + */ + if (window->type == META_WINDOW_DIALOG || window->type == META_WINDOW_MODAL_DIALOG || window->type == META_WINDOW_SPLASHSCREEN) diff --git a/src/prefs.c b/src/prefs.c index def0f07d3..58946c4cd 100644 --- a/src/prefs.c +++ b/src/prefs.c @@ -36,6 +36,7 @@ #define KEY_TITLEBAR_FONT_SIZE "/apps/metacity/general/titlebar_font_size" #define KEY_NUM_WORKSPACES "/apps/metacity/general/num_workspaces" #define KEY_APPLICATION_BASED "/apps/metacity/general/application_based" +#define KEY_DISABLE_WORKAROUNDS "/apps/metacity/general/disable_workarounds" #define KEY_SCREEN_BINDINGS_PREFIX "/apps/metacity/global_keybindings" #define KEY_WINDOW_BINDINGS_PREFIX "/apps/metacity/window_keybindings" @@ -51,6 +52,7 @@ static MetaFocusMode focus_mode = META_FOCUS_MODE_CLICK; static char* current_theme = NULL; static int num_workspaces = 4; static gboolean application_based = FALSE; +static gboolean disable_workarounds = FALSE; static gboolean update_use_desktop_font (gboolean value); static gboolean update_titlebar_font (const char *value); @@ -59,6 +61,7 @@ static gboolean update_focus_mode (const char *value); static gboolean update_theme (const char *value); static gboolean update_num_workspaces (int value); static gboolean update_application_based (gboolean value); +static gboolean update_disable_workarounds (gboolean value); static gboolean update_window_binding (const char *name, const char *value); static gboolean update_screen_binding (const char *name, @@ -265,6 +268,11 @@ meta_prefs_init (void) cleanup_error (&err); update_application_based (bool_val); + bool_val = gconf_client_get_bool (default_client, KEY_DISABLE_WORKAROUNDS, + &err); + cleanup_error (&err); + update_disable_workarounds (bool_val); + /* Load keybindings prefs */ init_bindings (); @@ -425,6 +433,22 @@ change_notify (GConfClient *client, if (update_application_based (b)) queue_changed (META_PREF_APPLICATION_BASED); } + else if (strcmp (key, KEY_DISABLE_WORKAROUNDS) == 0) + { + gboolean b; + + if (value && value->type != GCONF_VALUE_BOOL) + { + meta_warning (_("GConf key \"%s\" is set to an invalid type\n"), + KEY_APPLICATION_BASED); + goto out; + } + + b = value ? gconf_value_get_bool (value) : disable_workarounds; + + if (update_disable_workarounds (b)) + queue_changed (META_PREF_DISABLE_WORKAROUNDS); + } else if (str_has_prefix (key, KEY_WINDOW_BINDINGS_PREFIX)) { const char *str; @@ -651,6 +675,33 @@ meta_prefs_get_application_based (void) return application_based; } +static gboolean +update_disable_workarounds (gboolean value) +{ + gboolean old = disable_workarounds; + + disable_workarounds = value; + + { + static gboolean first_disable = TRUE; + + if (disable_workarounds && first_disable) + { + first_disable = FALSE; + + meta_warning (_("Workarounds for broken applications disabled. Some applications may not behave properly.\n")); + } + } + + return old != disable_workarounds; +} + +gboolean +meta_prefs_get_disable_workarounds (void) +{ + return disable_workarounds; +} + const char* meta_preference_to_string (MetaPreference pref) { @@ -679,6 +730,9 @@ meta_preference_to_string (MetaPreference pref) case META_PREF_WINDOW_KEYBINDINGS: return "WINDOW_KEYBINDINGS"; + + case META_PREF_DISABLE_WORKAROUNDS: + return "DISABLE_WORKAROUNDS"; } return "(unknown)"; diff --git a/src/prefs.h b/src/prefs.h index 2b94ee774..d808cb704 100644 --- a/src/prefs.h +++ b/src/prefs.h @@ -35,7 +35,8 @@ typedef enum META_PREF_NUM_WORKSPACES, META_PREF_APPLICATION_BASED, META_PREF_WINDOW_KEYBINDINGS, - META_PREF_SCREEN_KEYBINDINGS + META_PREF_SCREEN_KEYBINDINGS, + META_PREF_DISABLE_WORKAROUNDS } MetaPreference; typedef void (* MetaPrefsChangedFunc) (MetaPreference pref, @@ -57,6 +58,7 @@ const PangoFontDescription* meta_prefs_get_titlebar_font (void); int meta_prefs_get_titlebar_font_size (void); int meta_prefs_get_num_workspaces (void); gboolean meta_prefs_get_application_based (void); +gboolean meta_prefs_get_disable_workarounds (void); void meta_prefs_set_num_workspaces (int n_workspaces); diff --git a/src/tools/metacity-window-demo.c b/src/tools/metacity-window-demo.c index dc64952de..73b27c478 100644 --- a/src/tools/metacity-window-demo.c +++ b/src/tools/metacity-window-demo.c @@ -260,6 +260,56 @@ utility_cb (gpointer callback_data, gtk_widget_show_all (window); } +static void +toolbar_cb (gpointer callback_data, + guint callback_action, + GtkWidget *widget) +{ + GtkWidget *window; + GtkWidget *vbox; + GtkWidget *label; + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + set_gtk_window_type (GTK_WINDOW (window), "_NET_WM_WINDOW_TYPE_TOOLBAR"); + gtk_window_set_title (GTK_WINDOW (window), "Toolbar"); + + gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (callback_data)); + + vbox = gtk_vbox_new (FALSE, 0); + + gtk_container_add (GTK_CONTAINER (window), vbox); + + label = gtk_label_new ("FIXME this needs a resize grip, etc."); + gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); + + gtk_widget_show_all (window); +} + +static void +menu_cb (gpointer callback_data, + guint callback_action, + GtkWidget *widget) +{ + GtkWidget *window; + GtkWidget *vbox; + GtkWidget *label; + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + set_gtk_window_type (GTK_WINDOW (window), "_NET_WM_WINDOW_TYPE_MENU"); + gtk_window_set_title (GTK_WINDOW (window), "Menu"); + + gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (callback_data)); + + vbox = gtk_vbox_new (FALSE, 0); + + gtk_container_add (GTK_CONTAINER (window), vbox); + + label = gtk_label_new ("FIXME this isn't a menu."); + gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); + + gtk_widget_show_all (window); +} + static gboolean focus_in_event_cb (GtkWidget *window, GdkEvent *event, @@ -470,7 +520,9 @@ static GtkItemFactoryEntry menu_items[] = { "/Windows/_Left dock", NULL, dock_cb, DOCK_LEFT, NULL }, { "/Windows/_Right dock", NULL, dock_cb, DOCK_RIGHT, NULL }, { "/Windows/_All docks", NULL, dock_cb, DOCK_ALL, NULL }, - { "/Windows/Des_ktop", NULL, desktop_cb, 0, NULL } + { "/Windows/Des_ktop", NULL, desktop_cb, 0, NULL }, + { "/Windows/Me_nu", NULL, menu_cb, 0, NULL }, + { "/Windows/Tool_bar", NULL, toolbar_cb, 0, NULL } }; static void @@ -481,8 +533,8 @@ sleep_cb (GtkWidget *button, } static void -toolbar_cb (GtkWidget *button, - gpointer data) +clicked_toolbar_cb (GtkWidget *button, + gpointer data) { GtkWidget *dialog; @@ -629,7 +681,7 @@ do_appwindow (void) GTK_STOCK_QUIT, "This is a demo button with a 'quit' icon", NULL, - G_CALLBACK (toolbar_cb), + G_CALLBACK (clicked_toolbar_cb), window, /* user data for callback */ -1); /* -1 means "append" */ diff --git a/src/window.c b/src/window.c index 534a660c7..12dab9593 100644 --- a/src/window.c +++ b/src/window.c @@ -2765,6 +2765,7 @@ meta_window_configure_request (MetaWindow *window, { int x, y, width, height; gboolean only_resize; + gboolean allow_position_change; /* it's essential to use only the explicitly-set fields, * and otherwise use our current up-to-date position. @@ -2778,15 +2779,31 @@ meta_window_configure_request (MetaWindow *window, meta_window_get_gravity_position (window, &x, &y); only_resize = TRUE; + + allow_position_change = FALSE; - if (((window->type == META_WINDOW_DESKTOP || - window->type == META_WINDOW_DOCK || - window->type == META_WINDOW_TOOLBAR || - window->type == META_WINDOW_MENU || - window->type == META_WINDOW_NORMAL || - window->type == META_WINDOW_UTILITY) && - (window->size_hints.flags & PPosition)) || - (window->size_hints.flags & USPosition)) + if (meta_prefs_get_disable_workarounds ()) + { + if (window->type == META_WINDOW_DIALOG || + window->type == META_WINDOW_MODAL_DIALOG || + window->type == META_WINDOW_SPLASHSCREEN) + ; /* No position change for these */ + else if ((window->size_hints.flags & PPosition) || + /* USPosition is just stale if window is placed; + * no --geometry involved here. + */ + ((window->size_hints.flags & USPosition) && + !window->placed)) + allow_position_change = TRUE; + } + else + { + allow_position_change = + (window->size_hints.flags & PPosition) || + (window->size_hints.flags & USPosition); + } + + if (allow_position_change) { if (event->xconfigurerequest.value_mask & CWX) x = event->xconfigurerequest.x; @@ -2795,25 +2812,24 @@ meta_window_configure_request (MetaWindow *window, y = event->xconfigurerequest.y; if (event->xconfigurerequest.value_mask & (CWX | CWY)) - only_resize = FALSE; + { + only_resize = FALSE; + + /* Once manually positioned, windows shouldn't be placed + * by the window manager. + */ + window->placed = TRUE; + } } width = window->rect.width; height = window->rect.height; - if (window->type == META_WINDOW_DESKTOP || - window->type == META_WINDOW_DOCK || - window->type == META_WINDOW_TOOLBAR || - window->type == META_WINDOW_MENU || - window->type == META_WINDOW_NORMAL || - window->type == META_WINDOW_UTILITY) - { - if (event->xconfigurerequest.value_mask & CWWidth) - width = event->xconfigurerequest.width; + if (event->xconfigurerequest.value_mask & CWWidth) + width = event->xconfigurerequest.width; - if (event->xconfigurerequest.value_mask & CWHeight) - height = event->xconfigurerequest.height; - } + if (event->xconfigurerequest.value_mask & CWHeight) + height = event->xconfigurerequest.height; /* ICCCM 4.1.5 */ @@ -4683,6 +4699,8 @@ recalc_window_features (MetaWindow *window) window->has_fullscreen_func = TRUE; /* Semantic category overrides the MWM hints */ + if (window->type == META_WINDOW_TOOLBAR) + window->decorated = FALSE; if (window->type == META_WINDOW_DESKTOP || window->type == META_WINDOW_DOCK || @@ -4691,6 +4709,15 @@ recalc_window_features (MetaWindow *window) window->decorated = FALSE; window->has_close_func = FALSE; window->has_shade_func = FALSE; + + /* FIXME this keeps panels and things from using + * NET_WM_MOVERESIZE; the problem is that some + * panels (edge panels) have fixed possible locations, + * and others ("floating panels") do not. + * + * Perhaps we should require edge panels to explicitly + * disable movement? + */ window->has_move_func = FALSE; window->has_resize_func = FALSE; }