diff --git a/ChangeLog b/ChangeLog index f9f2021a2..8be972d27 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,27 @@ +2002-10-07 Havoc Pennington + + Add a modifier key preference for the Alt+click stuff. + Can be set to "disabled" as well. + + * src/run-metacity.sh: load .Xmodmap in the Xnest if it exists + + * src/display.c (meta_display_ungrab_window_buttons): ungrab + AnyModifier in case the modifier changed since we grabbed + (meta_display_open): rearrange code to use meta_display_close() to + mop up when we can't find any screens, avoiding the need to + keep the bail-out code in sync with meta_display_close. + + * src/keybindings.c (devirtualize_modifiers): move this function + to a public place in display.c + + * src/metacity.schemas.in: add setting for the modifier key + to use for Alt+left/middle/right click. + + * src/prefs.c (update_binding): add a missing newline to a warning + (meta_prefs_get_mouse_button_mods): new function + + * src/ui.c (meta_ui_parse_modifier): new function + 2002-10-07 Havoc Pennington * src/async-getprop.c: don't include unportable Xproto.h, fix from diff --git a/rationales.txt b/rationales.txt index 536b46d5a..31d97e2aa 100644 --- a/rationales.txt +++ b/rationales.txt @@ -2,3 +2,4 @@ Focus windows on map: see http://bugzilla.gnome.org/show_bug.cgi?id=82921 Keep panel always on top: http://bugzilla.gnome.org/show_bug.cgi?id=81551 Edge flipping: http://bugzilla.gnome.org/show_bug.cgi?id=82917 +Opaque resize: http://bugzilla.gnome.org/show_bug.cgi?id=92618 diff --git a/src/display.c b/src/display.c index dc9cbaf2b..a5d8daad2 100644 --- a/src/display.c +++ b/src/display.c @@ -79,6 +79,10 @@ static void process_selection_request (MetaDisplay *display, static void process_selection_clear (MetaDisplay *display, XEvent *event); +static void update_window_grab_modifiers (MetaDisplay *display); + +static void prefs_changed_callback (MetaPreference pref, + void *data); static int set_utf8_string_hint (MetaDisplay *display, @@ -275,6 +279,10 @@ meta_display_open (const char *name) meta_display_init_keys (display); + update_window_grab_modifiers (display); + + meta_prefs_add_listener (prefs_changed_callback, display); + XInternAtoms (display->xdisplay, atom_names, G_N_ELEMENTS (atom_names), False, atoms); display->atom_net_wm_name = atoms[0]; @@ -364,47 +372,9 @@ meta_display_open (const char *name) display->xinerama_cache_invalidated = TRUE; display->groups_by_leader = NULL; + + display->screens = NULL; - screens = NULL; - -#ifdef HAVE_GTK_MULTIHEAD - - i = 0; - while (i < ScreenCount (xdisplay)) - { - MetaScreen *screen; - - screen = meta_screen_new (display, i); - - if (screen) - screens = g_slist_prepend (screens, screen); - ++i; - } -#else - { - MetaScreen *screen; - screen = meta_screen_new (display, DefaultScreen (xdisplay)); - if (screen) - screens = g_slist_prepend (screens, screen); - } -#endif - - if (screens == NULL) - { - /* This would typically happen because all the screens already - * have window managers - */ -#ifndef USE_GDK_DISPLAY - XCloseDisplay (xdisplay); -#endif - all_displays = g_slist_remove (all_displays, display); - g_free (display->name); - g_free (display); - return FALSE; - } - - display->screens = screens; - #ifdef USE_GDK_DISPLAY display->events = NULL; @@ -441,6 +411,44 @@ meta_display_open (const char *name) display->grab_window = NULL; display->grab_screen = NULL; display->grab_resize_popup = NULL; + + screens = NULL; + +#ifdef HAVE_GTK_MULTIHEAD + i = 0; + while (i < ScreenCount (xdisplay)) + { + MetaScreen *screen; + + screen = meta_screen_new (display, i); + + if (screen) + screens = g_slist_prepend (screens, screen); + ++i; + } +#else + { + MetaScreen *screen; + screen = meta_screen_new (display, DefaultScreen (xdisplay)); + if (screen) + screens = g_slist_prepend (screens, screen); + } +#endif + + display->screens = screens; + + if (screens == NULL) + { + /* This would typically happen because all the screens already + * have window managers. + */ + meta_display_close (display); + return FALSE; + } + + /* display->leader_window was created as a side effect of + * initializing the screens + */ set_utf8_string_hint (display, display->leader_window, @@ -467,8 +475,9 @@ meta_display_open (const char *name) XA_WINDOW, 32, PropModeReplace, (guchar*) data, 1); } - + meta_display_grab (display); + /* Now manage all existing windows */ tmp = display->screens; while (tmp != NULL) @@ -579,6 +588,8 @@ meta_display_close (MetaDisplay *display) meta_bug ("Display closed with error traps pending\n"); display->closing += 1; + + meta_prefs_remove_listener (prefs_changed_callback, display); if (display->autoraise_timeout_id != 0) { @@ -1046,10 +1057,10 @@ event_callback (XEvent *event, else if (window && display->grab_op == META_GRAB_OP_NONE) { gboolean begin_move = FALSE; - guint grab_mask; + unsigned int grab_mask; gboolean unmodified; - grab_mask = Mod1Mask; + grab_mask = display->window_grab_modifiers; if (g_getenv ("METACITY_DEBUG_BUTTON_GRABS")) grab_mask |= ControlMask; @@ -2570,53 +2581,61 @@ meta_change_button_grab (MetaDisplay *display, void meta_display_grab_window_buttons (MetaDisplay *display, Window xwindow) -{ +{ /* Grab Alt + button1 and Alt + button2 for moving window, * and Alt + button3 for popping up window menu. */ meta_verbose ("Grabbing window buttons for 0x%lx\n", xwindow); - + /* FIXME If we ignored errors here instead of spewing, we could * put one big error trap around the loop and avoid a bunch of * XSync() */ - - { - gboolean debug = g_getenv ("METACITY_DEBUG_BUTTON_GRABS") != NULL; - int i = 1; - while (i < 4) - { - meta_change_button_grab (display, - xwindow, - TRUE, - FALSE, - i, Mod1Mask); - - /* This is for debugging, since I end up moving the Xnest - * otherwise ;-) - */ - if (debug) - meta_change_button_grab (display, xwindow, + if (display->window_grab_modifiers != 0) + { + gboolean debug = g_getenv ("METACITY_DEBUG_BUTTON_GRABS") != NULL; + int i = 1; + while (i < 4) + { + meta_change_button_grab (display, + xwindow, TRUE, FALSE, - i, ControlMask); - - ++i; - } - } + i, display->window_grab_modifiers); + + /* This is for debugging, since I end up moving the Xnest + * otherwise ;-) + */ + if (debug) + meta_change_button_grab (display, xwindow, + TRUE, + FALSE, + i, ControlMask); + + ++i; + } + } } void meta_display_ungrab_window_buttons (MetaDisplay *display, Window xwindow) { - gboolean debug = g_getenv ("METACITY_DEBUG_BUTTON_GRABS") != NULL; - int i = 1; + gboolean debug; + int i; + + if (display->window_grab_modifiers == 0) + return; + + debug = g_getenv ("METACITY_DEBUG_BUTTON_GRABS") != NULL; + i = 1; while (i < 4) { meta_change_button_grab (display, xwindow, - FALSE, FALSE, i, Mod1Mask); + FALSE, FALSE, i, + display->window_grab_modifiers); + if (debug) meta_change_button_grab (display, xwindow, FALSE, FALSE, i, ControlMask); @@ -3495,3 +3514,85 @@ meta_display_unmanage_windows_for_screen (MetaDisplay *display, } g_slist_free (winlist); } + +void +meta_display_devirtualize_modifiers (MetaDisplay *display, + MetaVirtualModifier modifiers, + unsigned int *mask) +{ + *mask = 0; + + if (modifiers & META_VIRTUAL_SHIFT_MASK) + *mask |= ShiftMask; + if (modifiers & META_VIRTUAL_CONTROL_MASK) + *mask |= ControlMask; + if (modifiers & META_VIRTUAL_ALT_MASK) + *mask |= Mod1Mask; + if (modifiers & META_VIRTUAL_META_MASK) + *mask |= display->meta_mask; + if (modifiers & META_VIRTUAL_HYPER_MASK) + *mask |= display->hyper_mask; + if (modifiers & META_VIRTUAL_SUPER_MASK) + *mask |= display->super_mask; + if (modifiers & META_VIRTUAL_MOD2_MASK) + *mask |= Mod2Mask; + if (modifiers & META_VIRTUAL_MOD3_MASK) + *mask |= Mod3Mask; + if (modifiers & META_VIRTUAL_MOD4_MASK) + *mask |= Mod4Mask; + if (modifiers & META_VIRTUAL_MOD5_MASK) + *mask |= Mod5Mask; +} + +static void +update_window_grab_modifiers (MetaDisplay *display) + +{ + MetaVirtualModifier virtual_mods; + unsigned int mods; + + virtual_mods = meta_prefs_get_mouse_button_mods (); + meta_display_devirtualize_modifiers (display, virtual_mods, + &mods); + + display->window_grab_modifiers = mods; +} + +static void +prefs_changed_callback (MetaPreference pref, + void *data) +{ + if (pref == META_PREF_MOUSE_BUTTON_MODS) + { + MetaDisplay *display = data; + GSList *windows; + GSList *tmp; + + windows = meta_display_list_windows (display); + + /* Ungrab all */ + tmp = windows; + while (tmp != NULL) + { + MetaWindow *w = tmp->data; + meta_display_ungrab_window_buttons (display, w->xwindow); + meta_display_ungrab_focus_window_button (display, w->xwindow); + tmp = tmp->next; + } + + /* change our modifier */ + update_window_grab_modifiers (display); + + /* Grab all */ + tmp = windows; + while (tmp != NULL) + { + MetaWindow *w = tmp->data; + meta_display_grab_focus_window_button (display, w->xwindow); + meta_display_grab_window_buttons (display, w->xwindow); + tmp = tmp->next; + } + + g_slist_free (windows); + } +} diff --git a/src/display.h b/src/display.h index fa36a0af2..3b17d640a 100644 --- a/src/display.h +++ b/src/display.h @@ -204,6 +204,9 @@ struct _MetaDisplay /* Pending autoraise */ guint autoraise_timeout_id; + + /* Alt+click button grabs */ + unsigned int window_grab_modifiers; /* current window operation */ MetaGrabOp grab_op; @@ -382,4 +385,8 @@ gboolean meta_rectangle_intersect (MetaRectangle *src1, MetaRectangle *src2, MetaRectangle *dest); +void meta_display_devirtualize_modifiers (MetaDisplay *display, + MetaVirtualModifier modifiers, + unsigned int *mask); + #endif diff --git a/src/keybindings.c b/src/keybindings.c index 0f26cdf8c..3fee1396e 100644 --- a/src/keybindings.c +++ b/src/keybindings.c @@ -439,35 +439,6 @@ reload_keycodes (MetaDisplay *display) } } -static void -devirtualize_modifiers (MetaDisplay *display, - MetaVirtualModifier modifiers, - unsigned int *mask) -{ - *mask = 0; - - if (modifiers & META_VIRTUAL_SHIFT_MASK) - *mask |= ShiftMask; - if (modifiers & META_VIRTUAL_CONTROL_MASK) - *mask |= ControlMask; - if (modifiers & META_VIRTUAL_ALT_MASK) - *mask |= Mod1Mask; - if (modifiers & META_VIRTUAL_META_MASK) - *mask |= display->meta_mask; - if (modifiers & META_VIRTUAL_HYPER_MASK) - *mask |= display->hyper_mask; - if (modifiers & META_VIRTUAL_SUPER_MASK) - *mask |= display->super_mask; - if (modifiers & META_VIRTUAL_MOD2_MASK) - *mask |= Mod2Mask; - if (modifiers & META_VIRTUAL_MOD3_MASK) - *mask |= Mod3Mask; - if (modifiers & META_VIRTUAL_MOD4_MASK) - *mask |= Mod4Mask; - if (modifiers & META_VIRTUAL_MOD5_MASK) - *mask |= Mod5Mask; -} - static void reload_modifiers (MetaDisplay *display) { @@ -481,9 +452,9 @@ reload_modifiers (MetaDisplay *display) i = 0; while (display->screen_bindings[i].keysym != None) { - devirtualize_modifiers (display, - display->screen_bindings[i].modifiers, - &display->screen_bindings[i].mask); + meta_display_devirtualize_modifiers (display, + display->screen_bindings[i].modifiers, + &display->screen_bindings[i].mask); ++i; } @@ -496,9 +467,9 @@ reload_modifiers (MetaDisplay *display) i = 0; while (display->window_bindings[i].keysym != None) { - devirtualize_modifiers (display, - display->window_bindings[i].modifiers, - &display->window_bindings[i].mask); + meta_display_devirtualize_modifiers (display, + display->window_bindings[i].modifiers, + &display->window_bindings[i].mask); ++i; } diff --git a/src/metacity.schemas.in b/src/metacity.schemas.in index a4c344721..931a3d985 100644 --- a/src/metacity.schemas.in +++ b/src/metacity.schemas.in @@ -3,6 +3,24 @@ + + /schemas/apps/metacity/general/mouse_button_modifier + /apps/metacity/general/mouse_button_modifier + metacity + string + <Alt> + + Modifier to use for modified window click actions (Alt+left/middle/right click) + + Clicking a window while holding down this modifier key + will move the window (left click), resize the window + (middle click), or show the window menu (right click). + Modifier is expressed as "<Alt>" or "<Super>" + for example. + + + + /schemas/apps/metacity/general/focus_mode /apps/metacity/general/focus_mode diff --git a/src/prefs.c b/src/prefs.c index aa66a43cd..19338b3b2 100644 --- a/src/prefs.c +++ b/src/prefs.c @@ -30,6 +30,7 @@ /* If you add a key, it needs updating in init() and in the gconf * notify listener and of course in the .schemas file */ +#define KEY_MOUSE_BUTTON_MODS "/apps/metacity/general/mouse_button_modifier" #define KEY_FOCUS_MODE "/apps/metacity/general/focus_mode" #define KEY_AUTO_RAISE "/apps/metacity/general/auto_raise" #define KEY_AUTO_RAISE_DELAY "/apps/metacity/general/auto_raise_delay" @@ -50,6 +51,7 @@ static GList *changes = NULL; static guint changed_idle; static gboolean use_system_font = TRUE; static PangoFontDescription *titlebar_font = NULL; +static MetaVirtualModifier mouse_button_mods = Mod1Mask; static MetaFocusMode focus_mode = META_FOCUS_MODE_CLICK; static char* current_theme = NULL; static int num_workspaces = 4; @@ -63,6 +65,7 @@ static char *commands[NUM_COMMANDS] = { NULL, NULL, NULL, NULL, NULL, NULL, static gboolean update_use_system_font (gboolean value); static gboolean update_titlebar_font (const char *value); +static gboolean update_mouse_button_mods (const char *value); static gboolean update_focus_mode (const char *value); static gboolean update_theme (const char *value); static gboolean update_num_workspaces (int value); @@ -236,6 +239,12 @@ meta_prefs_init (void) &err); cleanup_error (&err); + str_val = gconf_client_get_string (default_client, KEY_MOUSE_BUTTON_MODS, + &err); + cleanup_error (&err); + update_mouse_button_mods (str_val); + g_free (str_val); + str_val = gconf_client_get_string (default_client, KEY_FOCUS_MODE, &err); cleanup_error (&err); @@ -336,7 +345,23 @@ change_notify (GConfClient *client, key = gconf_entry_get_key (entry); value = gconf_entry_get_value (entry); - + + if (strcmp (key, KEY_MOUSE_BUTTON_MODS) == 0) + { + const char *str; + + if (value && value->type != GCONF_VALUE_STRING) + { + meta_warning (_("GConf key \"%s\" is set to an invalid type\n"), + KEY_MOUSE_BUTTON_MODS); + goto out; + } + + str = value ? gconf_value_get_string (value) : NULL; + + if (update_mouse_button_mods (str)) + queue_changed (META_PREF_MOUSE_BUTTON_MODS); + } if (strcmp (key, KEY_FOCUS_MODE) == 0) { const char *str; @@ -545,6 +570,36 @@ change_notify (GConfClient *client, return; /* AIX compiler wants something after a label like out: */ } +static gboolean +update_mouse_button_mods (const char *value) +{ + MetaVirtualModifier old_mods = mouse_button_mods; + + if (value != NULL) + { + MetaVirtualModifier mods; + + meta_topic (META_DEBUG_KEYBINDINGS, + "Mouse button modifier has new gconf value \"%s\"\n", + value ? value : "none"); + + if (meta_ui_parse_modifier (value, &mods)) + { + mouse_button_mods = mods; + } + else + { + meta_topic (META_DEBUG_KEYBINDINGS, + "Failed to parse new gconf value\n"); + + meta_warning (_("\"%s\" found in configuration database is not a valid value for mouse button modifier\n"), + value); + } + } + + return old_mods != mouse_button_mods; +} + static gboolean update_focus_mode (const char *value) { @@ -559,7 +614,7 @@ update_focus_mode (const char *value) else if (g_ascii_strcasecmp (value, "mouse") == 0) focus_mode = META_FOCUS_MODE_MOUSE; else - meta_warning (_("GConf key '%s' is set to an invalid value"), + meta_warning (_("GConf key '%s' is set to an invalid value\n"), KEY_FOCUS_MODE); } @@ -598,6 +653,13 @@ update_theme (const char *value) return changed; } + +MetaVirtualModifier +meta_prefs_get_mouse_button_mods (void) +{ + return mouse_button_mods; +} + MetaFocusMode meta_prefs_get_focus_mode (void) { @@ -767,6 +829,9 @@ meta_preference_to_string (MetaPreference pref) { switch (pref) { + case META_PREF_MOUSE_BUTTON_MODS: + return "MOUSE_BUTTON_MODS"; + case META_PREF_FOCUS_MODE: return "FOCUS_MODE"; @@ -1004,7 +1069,7 @@ update_binding (MetaKeyPref *binding, { meta_topic (META_DEBUG_KEYBINDINGS, "Failed to parse new gconf value\n"); - meta_warning (_("\"%s\" found in configuration database is not a valid value for keybinding \"%s\""), + meta_warning (_("\"%s\" found in configuration database is not a valid value for keybinding \"%s\"\n"), value, binding->name); } } diff --git a/src/prefs.h b/src/prefs.h index b10432c1e..e03b12345 100644 --- a/src/prefs.h +++ b/src/prefs.h @@ -28,6 +28,7 @@ typedef enum { + META_PREF_MOUSE_BUTTON_MODS, META_PREF_FOCUS_MODE, META_PREF_AUTO_RAISE, META_PREF_AUTO_RAISE_DELAY, @@ -53,6 +54,7 @@ void meta_prefs_remove_listener (MetaPrefsChangedFunc func, void meta_prefs_init (void); const char* meta_preference_to_string (MetaPreference pref); +MetaVirtualModifier meta_prefs_get_mouse_button_mods (void); MetaFocusMode meta_prefs_get_focus_mode (void); const char* meta_prefs_get_theme (void); /* returns NULL if GTK default should be used */ diff --git a/src/run-metacity.sh b/src/run-metacity.sh index df851c491..4d885df29 100755 --- a/src/run-metacity.sh +++ b/src/run-metacity.sh @@ -72,6 +72,10 @@ if test -z "$ONLY_WM"; then DISPLAY=$CLIENT_DISPLAY gnome-terminal --geometry 25x15 & done fi + + if test -e ~/.Xmodmap; then + DISPLAY=$CLIENT_DISPLAY xmodmap ~/.Xmodmap + fi usleep 50000 diff --git a/src/ui.c b/src/ui.c index d242ffb17..b6d03de37 100644 --- a/src/ui.c +++ b/src/ui.c @@ -668,6 +668,51 @@ meta_ui_parse_accelerator (const char *accel, return TRUE; } +gboolean +meta_ui_parse_modifier (const char *accel, + MetaVirtualModifier *mask) +{ + EggVirtualModifierType gdk_mask = 0; + guint gdk_sym = 0; + + *mask = 0; + + if (strcmp (accel, "disabled") == 0) + return TRUE; + + if (!egg_accelerator_parse_virtual (accel, &gdk_sym, &gdk_mask)) + return FALSE; + + if (gdk_sym != None) + return FALSE; + + if (gdk_mask & EGG_VIRTUAL_RELEASE_MASK) /* we don't allow this */ + return FALSE; + + if (gdk_mask & EGG_VIRTUAL_SHIFT_MASK) + *mask |= META_VIRTUAL_SHIFT_MASK; + if (gdk_mask & EGG_VIRTUAL_CONTROL_MASK) + *mask |= META_VIRTUAL_CONTROL_MASK; + if (gdk_mask & EGG_VIRTUAL_ALT_MASK) + *mask |= META_VIRTUAL_ALT_MASK; + if (gdk_mask & EGG_VIRTUAL_MOD2_MASK) + *mask |= META_VIRTUAL_MOD2_MASK; + if (gdk_mask & EGG_VIRTUAL_MOD3_MASK) + *mask |= META_VIRTUAL_MOD3_MASK; + if (gdk_mask & EGG_VIRTUAL_MOD4_MASK) + *mask |= META_VIRTUAL_MOD4_MASK; + if (gdk_mask & EGG_VIRTUAL_MOD5_MASK) + *mask |= META_VIRTUAL_MOD5_MASK; + if (gdk_mask & EGG_VIRTUAL_SUPER_MASK) + *mask |= META_VIRTUAL_SUPER_MASK; + if (gdk_mask & EGG_VIRTUAL_HYPER_MASK) + *mask |= META_VIRTUAL_HYPER_MASK; + if (gdk_mask & EGG_VIRTUAL_META_MASK) + *mask |= META_VIRTUAL_META_MASK; + + return TRUE; +} + gboolean meta_ui_window_is_widget (MetaUI *ui, Window xwindow) diff --git a/src/ui.h b/src/ui.h index d671f21ba..90598f8f3 100644 --- a/src/ui.h +++ b/src/ui.h @@ -156,6 +156,8 @@ gboolean meta_ui_have_a_theme (void); gboolean meta_ui_parse_accelerator (const char *accel, unsigned int *keysym, MetaVirtualModifier *mask); +gboolean meta_ui_parse_modifier (const char *accel, + MetaVirtualModifier *mask); gboolean meta_ui_window_is_widget (MetaUI *ui, Window xwindow);