Commit e4e200a1 authored by Havoc Pennington's avatar Havoc Pennington Committed by Havoc Pennington
Browse files

remove caveats about keybindings

2002-04-28  Havoc Pennington  <hp@pobox.com>

	* README: remove caveats about keybindings

	* src/metacity.schemas: add schemas for all the keybindings.

	* src/window.c (meta_window_activate): if in "show desktop" mode
	when a window is activated, leave show desktop mode. So e.g.
	when you click on a task in the task list, show desktop mode
	will be turned off.

	* src/workspace.c (meta_workspace_get_neighbor): new function
	that doesn't quite work yet (needs support for getting
	workspace layout from the pager)

	* src/prefs.c: keybindings stuff

	* src/keybindings.c: make keybindings configurable

	* src/ui.c (meta_ui_parse_accelerator): new function
parent e9053f1f
2002-04-28 Havoc Pennington <hp@pobox.com>
* README: remove caveats about keybindings
* src/metacity.schemas: add schemas for all the keybindings.
* src/window.c (meta_window_activate): if in "show desktop" mode
when a window is activated, leave show desktop mode. So e.g.
when you click on a task in the task list, show desktop mode
will be turned off.
* src/workspace.c (meta_workspace_get_neighbor): new function
that doesn't quite work yet (needs support for getting
workspace layout from the pager)
* src/prefs.c: keybindings stuff
* src/keybindings.c: make keybindings configurable
* src/ui.c (meta_ui_parse_accelerator): new function
2002-04-25 Havoc Pennington <hp@redhat.com>
* metacity.spec: fix to install gconf schemas
......
......@@ -51,19 +51,25 @@ METACITY FEATURES
gconftool-2 --type=string --set /apps/metacity/general/focus_mode sloppy
gconftool-2 --type=string --set /apps/metacity/general/focus_mode click
- Global keybindings:
Alt-F1 to Alt-F6 switch workspaces
Alt-1 to Alt-6 switch workspaces
- Global keybinding defaults:
Alt-Tab forward cycle window focus
Alt-Shift-Tab backward cycle focus
Alt-Ctrl-Tab forward cycle focus among panels
Alt-Ctrl-Shift-Tab backward cycle focus among panels
Alt-Escape focus previous window
Ctrl-Alt-Left Arrow previous workspace
Ctrl-Alt-Right Arrow next workspace
Alt-Left Arrow previous workspace
Alt-Right Arrow next workspace
Ctrl-Alt-D minimize/unminimize all, to show desktop
Change keybindings for example:
unst gconftool-2 --type=string --set /apps/metacity/global_keybindings/switch_to_workspace_1 '<Alt>F1'
See metacity.schemas for available bindings.
- Window keybindings:
Alt-space window menu
Mnemonics work in the menu. That is, Alt-space then underlined
......@@ -77,6 +83,9 @@ METACITY FEATURES
Choose Resize from menu, and nothing happens yet, but
eventually I might implement something.
Keybindings for things like maximize window, etc. can be bound,
but don't exist by default. See metacity.schemas.
- Window mouse bindings:
Clicking anywhere on frame with button 1 will raise/focus window
......@@ -130,23 +139,10 @@ METACITY FEATURES
METACITY BUGS, NON-FEATURES, AND CAVEATS
===
- If you want keybindings which are not the ones mentioned above
as features, you have to edit keybindings.c and recompile.
- Some of the default keybindings (notable Alt+number) are total
crackrock. This is just because I like those keybindings and
things aren't configurable yet. Once bindings are configurable
the dumb defaults will go away.
- You need an EWMH-spec compliant pager/tasklist to be able
to navigate graphically; this does NOT include GNOME 1.x,
but should include GNOME 2 and KDE 3.
- Metacity turns off its keybindings for Emacs, because I use
Alt-space in Emacs, and getting a window menu annoys me.
This is a broken feature that will go away when keybindings are
configurable.
- I haven't even read the ICCCM section about colormaps. So if you
have an 8-bit display you are probably screwed.
......
......@@ -552,6 +552,8 @@ meta_display_close (MetaDisplay *display)
all_displays = g_slist_remove (all_displays, display);
meta_display_shutdown_keys (display);
g_free (display);
if (all_displays == NULL)
......@@ -1308,6 +1310,10 @@ event_callback (XEvent *event,
}
break;
case MappingNotify:
/* Let XLib know that there is a new keyboard mapping.
*/
XRefreshKeyboardMapping (&event->xmapping);
meta_display_process_mapping_event (display, event);
break;
default:
break;
......@@ -2027,6 +2033,7 @@ meta_display_begin_grab_op (MetaDisplay *display,
display->grab_window = window;
display->grab_xwindow = grab_xwindow;
display->grab_button = button;
display->grab_mask = modmask;
display->grab_root_x = root_x;
display->grab_root_y = root_y;
display->grab_initial_window_pos = display->grab_window->rect;
......@@ -2108,9 +2115,6 @@ meta_display_end_grab_op (MetaDisplay *display,
}
}
#define IGNORED_MODIFIERS (LockMask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask)
#define INTERESTING_MODIFIERS (~IGNORED_MODIFIERS)
static void
meta_change_button_grab (MetaDisplay *display,
Window xwindow,
......@@ -2119,22 +2123,16 @@ meta_change_button_grab (MetaDisplay *display,
int button,
int modmask)
{
/* Instead of this hacky mess copied from fvwm, WindowMaker just
* grabs with all numlock/scrolllock combinations and doesn't grab
* for other weird bits.
*/
int ignored_mask;
g_return_if_fail ((modmask & INTERESTING_MODIFIERS) == modmask);
ignored_mask = 0;
while (ignored_mask < IGNORED_MODIFIERS)
while (ignored_mask < (int) display->ignored_modifier_mask)
{
int result;
if (ignored_mask & INTERESTING_MODIFIERS)
if (ignored_mask & ~(display->ignored_modifier_mask))
{
/* Not a combination of IGNORED_MODIFIERS
/* Not a combination of ignored modifiers
* (it contains some non-ignored modifiers)
*/
++ignored_mask;
......
......@@ -40,13 +40,14 @@ struct _MetaRectangle
int height;
};
typedef struct _MetaDisplay MetaDisplay;
typedef struct _MetaFrame MetaFrame;
typedef struct _MetaScreen MetaScreen;
typedef struct _MetaStack MetaStack;
typedef struct _MetaUISlave MetaUISlave;
typedef struct _MetaWindow MetaWindow;
typedef struct _MetaWorkspace MetaWorkspace;
typedef struct _MetaDisplay MetaDisplay;
typedef struct _MetaFrame MetaFrame;
typedef struct _MetaKeyBinding MetaKeyBinding;
typedef struct _MetaScreen MetaScreen;
typedef struct _MetaStack MetaStack;
typedef struct _MetaUISlave MetaUISlave;
typedef struct _MetaWindow MetaWindow;
typedef struct _MetaWorkspace MetaWorkspace;
typedef void (* MetaWindowPingFunc) (MetaDisplay *display,
Window xwindow,
......@@ -188,6 +189,22 @@ struct _MetaDisplay
guint grab_have_keyboard : 1;
MetaRectangle grab_initial_window_pos;
MetaResizePopup *grab_resize_popup;
/* Keybindings stuff */
MetaKeyBinding *screen_bindings;
int n_screen_bindings;
MetaKeyBinding *window_bindings;
int n_window_bindings;
int min_keycode;
int max_keycode;
KeySym *keymap;
int keysyms_per_keycode;
XModifierKeymap *modmap;
unsigned int ignored_modifier_mask;
unsigned int num_lock_mask;
unsigned int scroll_lock_mask;
unsigned int mode_switch_mask;
};
gboolean meta_display_open (const char *name);
......
This diff is collapsed.
......@@ -25,17 +25,20 @@
#include "display.h"
#include "window.h"
void meta_display_init_keys (MetaDisplay *display);
void meta_screen_grab_keys (MetaScreen *screen);
void meta_screen_ungrab_keys (MetaScreen *screen);
void meta_window_grab_keys (MetaWindow *window);
void meta_window_ungrab_keys (MetaWindow *window);
gboolean meta_window_grab_all_keys (MetaWindow *window);
void meta_window_ungrab_all_keys (MetaWindow *window);
void meta_display_process_key_event (MetaDisplay *display,
MetaWindow *window,
XEvent *event);
void meta_set_keybindings_disabled (gboolean setting);
void meta_display_init_keys (MetaDisplay *display);
void meta_display_shutdown_keys (MetaDisplay *display);
void meta_screen_grab_keys (MetaScreen *screen);
void meta_screen_ungrab_keys (MetaScreen *screen);
void meta_window_grab_keys (MetaWindow *window);
void meta_window_ungrab_keys (MetaWindow *window);
gboolean meta_window_grab_all_keys (MetaWindow *window);
void meta_window_ungrab_all_keys (MetaWindow *window);
void meta_display_process_key_event (MetaDisplay *display,
MetaWindow *window,
XEvent *event);
void meta_set_keybindings_disabled (gboolean setting);
void meta_display_process_mapping_event (MetaDisplay *display,
XEvent *event);
#endif
......
This diff is collapsed.
......@@ -21,6 +21,7 @@
#include <config.h>
#include "prefs.h"
#include "ui.h"
#include "util.h"
#include <gconf/gconf-client.h>
#include <string.h>
......@@ -36,6 +37,9 @@
#define KEY_NUM_WORKSPACES "/apps/metacity/general/num_workspaces"
#define KEY_APPLICATION_BASED "/apps/metacity/general/application_based"
#define KEY_SCREEN_BINDINGS_PREFIX "/apps/metacity/global_keybindings"
#define KEY_WINDOW_BINDINGS_PREFIX "/apps/metacity/window_keybindings"
static GConfClient *default_client = NULL;
static GList *listeners = NULL;
static GList *changes = NULL;
......@@ -55,6 +59,13 @@ 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_window_binding (const char *name,
const char *value);
static gboolean update_screen_binding (const char *name,
const char *value);
static void init_bindings (void);
static gboolean update_binding (MetaKeyPref *binding,
const char *value);
static void queue_changed (MetaPreference pref);
static void change_notify (GConfClient *client,
......@@ -173,9 +184,11 @@ queue_changed (MetaPreference pref)
else
meta_verbose ("Change of pref %s was already pending\n",
meta_preference_to_string (pref));
/* add idle at priority below the gconf notify idle */
if (changed_idle == 0)
changed_idle = g_idle_add (changed_idle_handler, NULL);
changed_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE + 10,
changed_idle_handler, NULL, NULL);
}
static void
......@@ -251,6 +264,9 @@ meta_prefs_init (void)
&err);
cleanup_error (&err);
update_application_based (bool_val);
/* Load keybindings prefs */
init_bindings ();
gconf_client_notify_add (default_client, "/apps/metacity",
change_notify,
......@@ -260,6 +276,27 @@ meta_prefs_init (void)
cleanup_error (&err);
}
/* from eel */
static gboolean
str_has_prefix (const char *haystack, const char *needle)
{
const char *h, *n;
/* Eat one character at a time. */
h = haystack == NULL ? "" : haystack;
n = needle == NULL ? "" : needle;
do
{
if (*n == '\0')
return TRUE;
if (*h == '\0')
return FALSE;
}
while (*h++ == *n++);
return FALSE;
}
static void
change_notify (GConfClient *client,
guint cnxn_id,
......@@ -388,6 +425,38 @@ change_notify (GConfClient *client,
if (update_application_based (b))
queue_changed (META_PREF_APPLICATION_BASED);
}
else if (str_has_prefix (key, KEY_WINDOW_BINDINGS_PREFIX))
{
const char *str;
if (value && value->type != GCONF_VALUE_STRING)
{
meta_warning (_("GConf key \"%s\" is set to an invalid type\n"),
key);
goto out;
}
str = value ? gconf_value_get_string (value) : NULL;
if (update_window_binding (key, str))
queue_changed (META_PREF_WINDOW_KEYBINDINGS);
}
else if (str_has_prefix (key, KEY_SCREEN_BINDINGS_PREFIX))
{
const char *str;
if (value && value->type != GCONF_VALUE_STRING)
{
meta_warning (_("GConf key \"%s\" is set to an invalid type\n"),
key);
goto out;
}
str = value ? gconf_value_get_string (value) : NULL;
if (update_screen_binding (key, str))
queue_changed (META_PREF_SCREEN_KEYBINDINGS);
}
else
{
meta_verbose ("Key %s doesn't mean anything to Metacity\n",
......@@ -589,27 +658,27 @@ meta_preference_to_string (MetaPreference pref)
{
case META_PREF_FOCUS_MODE:
return "FOCUS_MODE";
break;
case META_PREF_THEME:
return "THEME";
break;
case META_PREF_TITLEBAR_FONT:
return "TITLEBAR_FONT";
break;
case META_PREF_TITLEBAR_FONT_SIZE:
return "TITLEBAR_FONT_SIZE";
break;
case META_PREF_NUM_WORKSPACES:
return "NUM_WORKSPACES";
break;
case META_PREF_APPLICATION_BASED:
return "APPLICATION_BASED";
break;
case META_PREF_SCREEN_KEYBINDINGS:
return "SCREEN_KEYBINDINGS";
case META_PREF_WINDOW_KEYBINDINGS:
return "WINDOW_KEYBINDINGS";
}
return "(unknown)";
......@@ -642,3 +711,222 @@ meta_prefs_set_num_workspaces (int n_workspaces)
g_error_free (err);
}
}
static MetaKeyPref screen_bindings[] = {
{ META_KEYBINDING_WORKSPACE_1, 0, 0 },
{ META_KEYBINDING_WORKSPACE_2, 0, 0 },
{ META_KEYBINDING_WORKSPACE_3, 0, 0 },
{ META_KEYBINDING_WORKSPACE_4, 0, 0 },
{ META_KEYBINDING_WORKSPACE_5, 0, 0 },
{ META_KEYBINDING_WORKSPACE_6, 0, 0 },
{ META_KEYBINDING_WORKSPACE_7, 0, 0 },
{ META_KEYBINDING_WORKSPACE_8, 0, 0 },
{ META_KEYBINDING_WORKSPACE_9, 0, 0 },
{ META_KEYBINDING_WORKSPACE_10, 0, 0 },
{ META_KEYBINDING_WORKSPACE_11, 0, 0 },
{ META_KEYBINDING_WORKSPACE_12, 0, 0 },
{ META_KEYBINDING_WORKSPACE_LEFT, 0, 0 },
{ META_KEYBINDING_WORKSPACE_RIGHT, 0, 0 },
{ META_KEYBINDING_WORKSPACE_UP, 0, 0 },
{ META_KEYBINDING_WORKSPACE_DOWN, 0, 0 },
{ META_KEYBINDING_SWITCH_WINDOWS, 0, 0 },
{ META_KEYBINDING_SWITCH_PANELS, 0, 0 },
{ META_KEYBINDING_FOCUS_PREVIOUS, 0, 0 },
{ META_KEYBINDING_SHOW_DESKTOP, 0, 0 },
{ NULL, 0, 0 }
};
static MetaKeyPref window_bindings[] = {
{ META_KEYBINDING_WINDOW_MENU, 0, 0 },
{ META_KEYBINDING_TOGGLE_FULLSCREEN, 0, 0 },
{ META_KEYBINDING_TOGGLE_MAXIMIZE, 0, 0 },
{ META_KEYBINDING_TOGGLE_SHADE, 0, 0 },
{ META_KEYBINDING_CLOSE, 0, 0 },
{ META_KEYBINDING_BEGIN_MOVE, 0, 0 },
{ META_KEYBINDING_BEGIN_RESIZE, 0, 0 },
{ META_KEYBINDING_TOGGLE_STICKY, 0, 0 },
{ META_KEYBINDING_MOVE_WORKSPACE_1, 0, 0 },
{ META_KEYBINDING_MOVE_WORKSPACE_2, 0, 0 },
{ META_KEYBINDING_MOVE_WORKSPACE_3, 0, 0 },
{ META_KEYBINDING_MOVE_WORKSPACE_4, 0, 0 },
{ META_KEYBINDING_MOVE_WORKSPACE_5, 0, 0 },
{ META_KEYBINDING_MOVE_WORKSPACE_6, 0, 0 },
{ META_KEYBINDING_MOVE_WORKSPACE_7, 0, 0 },
{ META_KEYBINDING_MOVE_WORKSPACE_8, 0, 0 },
{ META_KEYBINDING_MOVE_WORKSPACE_9, 0, 0 },
{ META_KEYBINDING_MOVE_WORKSPACE_10, 0, 0 },
{ META_KEYBINDING_MOVE_WORKSPACE_11, 0, 0 },
{ META_KEYBINDING_MOVE_WORKSPACE_12, 0, 0 },
{ META_KEYBINDING_MOVE_WORKSPACE_LEFT, 0, 0 },
{ META_KEYBINDING_MOVE_WORKSPACE_RIGHT, 0, 0 },
{ META_KEYBINDING_MOVE_WORKSPACE_UP, 0, 0 },
{ META_KEYBINDING_MOVE_WORKSPACE_DOWN, 0, 0 },
{ NULL, 0, 0 }
};
static void
init_bindings (void)
{
int i;
GError *err;
i = 0;
while (window_bindings[i].name)
{
char *str_val;
char *key;
key = g_strconcat (KEY_WINDOW_BINDINGS_PREFIX, "/",
window_bindings[i].name, NULL);
err = NULL;
str_val = gconf_client_get_string (default_client, key, &err);
cleanup_error (&err);
update_binding (&window_bindings[i], str_val);
g_free (str_val);
g_free (key);
++i;
}
i = 0;
while (screen_bindings[i].name)
{
char *str_val;
char *key;
key = g_strconcat (KEY_SCREEN_BINDINGS_PREFIX, "/",
screen_bindings[i].name, NULL);
err = NULL;
str_val = gconf_client_get_string (default_client, key, &err);
cleanup_error (&err);
update_binding (&screen_bindings[i], str_val);
g_free (str_val);
g_free (key);
++i;
}
}
static gboolean
update_binding (MetaKeyPref *binding,
const char *value)
{
unsigned int keysym;
unsigned long mask;
gboolean changed;
meta_topic (META_DEBUG_KEYBINDINGS,
"Binding \"%s\" has new gconf value \"%s\"\n",
binding->name, value ? value : "none");
keysym = 0;
mask = 0;
if (value)
{
if (!meta_ui_parse_accelerator (value, &keysym, &mask))
{
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\""),
value, binding->name);
}
}
changed = FALSE;
if (keysym != binding->keysym ||
mask != binding->mask)
{
changed = TRUE;
binding->keysym = keysym;
binding->mask = mask;
meta_topic (META_DEBUG_KEYBINDINGS,
"New keybinding for \"%s\" is keysym = 0x%x mask = 0x%lx\n",
binding->name, binding->keysym, binding->mask);
}
else
{
meta_topic (META_DEBUG_KEYBINDINGS,
"Keybinding for \"%s\" is unchanged\n", binding->name);
}
return changed;
}
static const gchar*
relative_key (const gchar* key)
{
const gchar* end;
end = strrchr (key, '/');
++end;
return end;
}
/* Return value is TRUE if a preference changed and we need to
* notify
*/
static gboolean
find_and_update_binding (MetaKeyPref *bindings,
const char *name,
const char *value)
{
const char *key;
int i;
if (*name == '/')
key = relative_key (name);
else
key = name;
i = 0;
while (bindings[i].name &&
strcmp (key, bindings[i].name) != 0)
++i;
if (bindings[i].name)
return update_binding (&bindings[i], value);
else
return FALSE;
}
static gboolean
update_window_binding (const char *name,
const char *value)
{
return find_and_update_binding (window_bindings, name, value);
}
static gboolean
update_screen_binding (const char *name,
const char *value)
{
return find_and_update_binding (screen_bindings, name, value);
}
void
meta_prefs_get_screen_bindings (const MetaKeyPref **bindings,
int *n_bindings)
{
*bindings = screen_bindings;
*n_bindings = (int) G_N_ELEMENTS (screen_bindings) - 1;
}
void
meta_prefs_get_window_bindings (const MetaKeyPref **bindings,
int *n_bindings)
{
*bindings = window_bindings;
*n_bindings = (int) G_N_ELEMENTS (window_bindings) - 1;
}
......@@ -33,7 +33,9 @@ typedef enum
META_PREF_TITLEBAR_FONT,
META_PREF_TITLEBAR_FONT_SIZE,
META_PREF_NUM_WORKSPACES,
META_PREF_APPLICATION_BASED
META_PREF_APPLICATION_BASED,
META_PREF_WINDOW_KEYBINDINGS,
META_PREF_SCREEN_KEYBINDINGS
} MetaPreference;
typedef void (* MetaPrefsChangedFunc) (MetaPreference pref,
......@@ -58,6 +60,66 @@ gboolean meta_prefs_get_application_based (void);
void meta_prefs_set_num_workspaces (int n_workspaces);
/* Screen bindings */
#define META_KEYBINDING_WORKSPACE_1 "switch_to_workspace_1"