option to display error when a command fails to run.

2002-07-11  Havoc Pennington  <hp@pobox.com>

	* src/metacity-dialog.c (main): option to display error when a
	command fails to run.

	* src/keybindings.c (handle_run_command): run commands
	in response to keybindings.

	* src/prefs.c: add command keybinding stuff

	* src/metacity.schemas.in: add keybindings for running commands,
	and keys to store the commands themselves.
This commit is contained in:
Havoc Pennington 2002-07-11 04:10:44 +00:00 committed by Havoc Pennington
parent a38c16e57e
commit 42639fc9fb
6 changed files with 392 additions and 2 deletions

View File

@ -1,3 +1,16 @@
2002-07-11 Havoc Pennington <hp@pobox.com>
* src/metacity-dialog.c (main): option to display error when a
command fails to run.
* src/keybindings.c (handle_run_command): run commands
in response to keybindings.
* src/prefs.c: add command keybinding stuff
* src/metacity.schemas.in: add keybindings for running commands,
and keys to store the commands themselves.
2002-07-10 Havoc Pennington <hp@redhat.com> 2002-07-10 Havoc Pennington <hp@redhat.com>
* src/display.c: properly attribute selection code to Matthias * src/display.c: properly attribute selection code to Matthias

View File

@ -102,6 +102,10 @@ static void handle_raise_or_lower (MetaDisplay *display,
MetaWindow *window, MetaWindow *window,
XEvent *event, XEvent *event,
MetaKeyBinding *binding); MetaKeyBinding *binding);
static void handle_run_command (MetaDisplay *display,
MetaWindow *window,
XEvent *event,
MetaKeyBinding *binding);
/* debug */ /* debug */
static void handle_spew_mark (MetaDisplay *display, static void handle_spew_mark (MetaDisplay *display,
@ -190,6 +194,30 @@ static const MetaKeyHandler screen_handlers[] = {
GINT_TO_POINTER (META_TAB_LIST_DOCKS) }, GINT_TO_POINTER (META_TAB_LIST_DOCKS) },
{ META_KEYBINDING_SHOW_DESKTOP, handle_toggle_desktop, { META_KEYBINDING_SHOW_DESKTOP, handle_toggle_desktop,
NULL }, NULL },
{ META_KEYBINDING_COMMAND_1, handle_run_command,
GINT_TO_POINTER (0) },
{ META_KEYBINDING_COMMAND_2, handle_run_command,
GINT_TO_POINTER (1) },
{ META_KEYBINDING_COMMAND_3, handle_run_command,
GINT_TO_POINTER (2) },
{ META_KEYBINDING_COMMAND_4, handle_run_command,
GINT_TO_POINTER (3) },
{ META_KEYBINDING_COMMAND_5, handle_run_command,
GINT_TO_POINTER (4) },
{ META_KEYBINDING_COMMAND_6, handle_run_command,
GINT_TO_POINTER (5) },
{ META_KEYBINDING_COMMAND_7, handle_run_command,
GINT_TO_POINTER (6) },
{ META_KEYBINDING_COMMAND_8, handle_run_command,
GINT_TO_POINTER (7) },
{ META_KEYBINDING_COMMAND_9, handle_run_command,
GINT_TO_POINTER (8) },
{ META_KEYBINDING_COMMAND_10, handle_run_command,
GINT_TO_POINTER (9) },
{ META_KEYBINDING_COMMAND_11, handle_run_command,
GINT_TO_POINTER (10) },
{ META_KEYBINDING_COMMAND_12, handle_run_command,
GINT_TO_POINTER (11) },
{ NULL, NULL, NULL } { NULL, NULL, NULL }
}; };
@ -1893,6 +1921,86 @@ handle_activate_workspace (MetaDisplay *display,
} }
} }
static void
error_on_command (int command_index,
const char *command,
const char *message)
{
GError *err;
char *argv[6];
char *key;
meta_warning ("Error on command %d \"%s\": %s\n",
command_index, command, message);
key = meta_prefs_get_gconf_key_for_command (command_index);
argv[0] = METACITY_LIBEXECDIR"/metacity-dialog";
argv[1] = "--command-failed-error";
argv[2] = key;
argv[3] = (char*) (command ? command : "");
argv[4] = (char*) message;
argv[5] = NULL;
err = NULL;
if (!g_spawn_async_with_pipes ("/",
argv,
NULL,
0,
NULL, NULL,
NULL,
NULL,
NULL,
NULL,
&err))
{
meta_warning (_("Error launching metacity-dialog to print an error about a command: %s\n"),
err->message);
g_error_free (err);
}
g_free (key);
}
static void
handle_run_command (MetaDisplay *display,
MetaWindow *window,
XEvent *event,
MetaKeyBinding *binding)
{
int which;
const char *command;
GError *err;
which = GPOINTER_TO_INT (binding->handler->data);
command = meta_prefs_get_command (which);
if (command == NULL)
{
char *s;
meta_topic (META_DEBUG_KEYBINDINGS,
"No command %d to run in response to keybinding press\n",
which);
s = g_strdup_printf (_("No command %d has been defined.\n"),
which + 1);
error_on_command (which, NULL, s);
g_free (s);
return;
}
err = NULL;
if (!g_spawn_command_line_async (command, &err))
{
error_on_command (which, command, err->message);
g_error_free (err);
}
}
static gboolean static gboolean
process_workspace_switch_grab (MetaDisplay *display, process_workspace_switch_grab (MetaDisplay *display,
XEvent *event, XEvent *event,

View File

@ -259,6 +259,35 @@ warn_about_no_sm_support (char **lame_apps)
return 0; return 0;
} }
static int
error_about_command (const char *gconf_key,
const char *command,
const char *error)
{
GtkWidget *dialog;
/* FIXME offer to change the value of the command's gconf key */
if (*command != '\0')
dialog = gtk_message_dialog_new (NULL, 0,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_CLOSE,
_("There was an error running \"%s\":\n"
"%s."),
command, error);
else
dialog = gtk_message_dialog_new (NULL, 0,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_CLOSE,
"%s", error);
gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (dialog);
return 0;
}
int int
main (int argc, char **argv) main (int argc, char **argv)
{ {
@ -295,6 +324,20 @@ main (int argc, char **argv)
return warn_about_no_sm_support (&argv[2]); return warn_about_no_sm_support (&argv[2]);
} }
else if (strcmp (argv[1], "--command-failed-error") == 0)
{
/* the args are the gconf key of the failed command, the text of
* the command, and the error message
*/
if (argc != 5)
{
g_printerr ("bad args to metacity-dialog\n");
return 1;
}
return error_about_command (argv[2], argv[3], argv[4]);
}
g_printerr ("bad args to metacity-dialog\n"); g_printerr ("bad args to metacity-dialog\n");
return 1; return 1;

View File

@ -1231,6 +1231,71 @@ you set
</locale> </locale>
</schema> </schema>
<schema>
<key>/schemas/apps/metacity/global_keybindings/run_command</key>
<applyto>/apps/metacity/global_keybindings/run_command_1</applyto>
<applyto>/apps/metacity/global_keybindings/run_command_2</applyto>
<applyto>/apps/metacity/global_keybindings/run_command_3</applyto>
<applyto>/apps/metacity/global_keybindings/run_command_4</applyto>
<applyto>/apps/metacity/global_keybindings/run_command_5</applyto>
<applyto>/apps/metacity/global_keybindings/run_command_6</applyto>
<applyto>/apps/metacity/global_keybindings/run_command_7</applyto>
<applyto>/apps/metacity/global_keybindings/run_command_8</applyto>
<applyto>/apps/metacity/global_keybindings/run_command_9</applyto>
<applyto>/apps/metacity/global_keybindings/run_command_10</applyto>
<applyto>/apps/metacity/global_keybindings/run_command_11</applyto>
<applyto>/apps/metacity/global_keybindings/run_command_12</applyto>
<owner>metacity</owner>
<type>string</type>
<default>disabled</default>
<locale name="C">
<short>Run a defined command</short>
<long>
The keybinding that runs the correspondingly-numbered
command in /apps/metacity/keybinding_commands
The format looks like "&lt;Control&gt;a" or
"&lt;Shift&gt;&lt;Alt&gt;F1.
The parser is fairly liberal and allows lower or upper case,
and also abbreviations such as "&lt;Ctl&gt;" and
"&lt;Ctrl&gt;". If you set the option to the special string
"disabled", then there will be no keybinding for this
action.
</long>
</locale>
</schema>
<!-- commands to run with the run_command keybindings -->
<schema>
<key>/schemas/apps/metacity/keybinding_commands/command</key>
<applyto>/apps/metacity/keybinding_commands/command_1</applyto>
<applyto>/apps/metacity/keybinding_commands/command_2</applyto>
<applyto>/apps/metacity/keybinding_commands/command_3</applyto>
<applyto>/apps/metacity/keybinding_commands/command_4</applyto>
<applyto>/apps/metacity/keybinding_commands/command_5</applyto>
<applyto>/apps/metacity/keybinding_commands/command_6</applyto>
<applyto>/apps/metacity/keybinding_commands/command_7</applyto>
<applyto>/apps/metacity/keybinding_commands/command_8</applyto>
<applyto>/apps/metacity/keybinding_commands/command_9</applyto>
<applyto>/apps/metacity/keybinding_commands/command_10</applyto>
<applyto>/apps/metacity/keybinding_commands/command_11</applyto>
<applyto>/apps/metacity/keybinding_commands/command_12</applyto>
<owner>metacity</owner>
<type>string</type>
<default> </default>
<locale name="C">
<short>Commands to run in response to keybindings</short>
<long>
The /apps/metacity/global_keybindings/run_command_N
keys define keybindings that correspond to these commands.
Pressing the keybinding for run_command_N will
execute command_N.
</long>
</locale>
</schema>
<!-- Not used and/or crackrock --> <!-- Not used and/or crackrock -->
<schema> <schema>

View File

@ -25,6 +25,7 @@
#include "util.h" #include "util.h"
#include <gconf/gconf-client.h> #include <gconf/gconf-client.h>
#include <string.h> #include <string.h>
#include <stdlib.h>
/* If you add a key, it needs updating in init() and in the gconf /* If you add a key, it needs updating in init() and in the gconf
* notify listener and of course in the .schemas file * notify listener and of course in the .schemas file
@ -39,6 +40,7 @@
#define KEY_APPLICATION_BASED "/apps/metacity/general/application_based" #define KEY_APPLICATION_BASED "/apps/metacity/general/application_based"
#define KEY_DISABLE_WORKAROUNDS "/apps/metacity/general/disable_workarounds" #define KEY_DISABLE_WORKAROUNDS "/apps/metacity/general/disable_workarounds"
#define KEY_COMMAND_PREFIX "/apps/metacity/keybinding_commands/command_"
#define KEY_SCREEN_BINDINGS_PREFIX "/apps/metacity/global_keybindings" #define KEY_SCREEN_BINDINGS_PREFIX "/apps/metacity/global_keybindings"
#define KEY_WINDOW_BINDINGS_PREFIX "/apps/metacity/window_keybindings" #define KEY_WINDOW_BINDINGS_PREFIX "/apps/metacity/window_keybindings"
@ -55,6 +57,9 @@ static gboolean application_based = FALSE;
static gboolean disable_workarounds = FALSE; static gboolean disable_workarounds = FALSE;
static gboolean auto_raise = FALSE; static gboolean auto_raise = FALSE;
static gboolean auto_raise_delay = 500; static gboolean auto_raise_delay = 500;
#define NUM_COMMANDS 12
static char *commands[NUM_COMMANDS] = { NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL };
static gboolean update_use_system_font (gboolean value); static gboolean update_use_system_font (gboolean value);
static gboolean update_titlebar_font (const char *value); static gboolean update_titlebar_font (const char *value);
@ -72,6 +77,9 @@ static gboolean update_screen_binding (const char *name,
static void init_bindings (void); static void init_bindings (void);
static gboolean update_binding (MetaKeyPref *binding, static gboolean update_binding (MetaKeyPref *binding,
const char *value); const char *value);
static gboolean update_command (const char *name,
const char *value);
static void init_commands (void);
static void queue_changed (MetaPreference pref); static void queue_changed (MetaPreference pref);
static void change_notify (GConfClient *client, static void change_notify (GConfClient *client,
@ -285,6 +293,9 @@ meta_prefs_init (void)
/* Load keybindings prefs */ /* Load keybindings prefs */
init_bindings (); init_bindings ();
/* commands */
init_commands ();
gconf_client_notify_add (default_client, "/apps/metacity", gconf_client_notify_add (default_client, "/apps/metacity",
change_notify, change_notify,
NULL, NULL,
@ -505,6 +516,23 @@ change_notify (GConfClient *client,
if (update_auto_raise_delay (d)) if (update_auto_raise_delay (d))
queue_changed (META_PREF_AUTO_RAISE_DELAY); queue_changed (META_PREF_AUTO_RAISE_DELAY);
}
else if (str_has_prefix (key, KEY_COMMAND_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_command (key, str))
queue_changed (META_PREF_COMMANDS);
} }
else else
{ {
@ -767,6 +795,9 @@ meta_preference_to_string (MetaPreference pref)
case META_PREF_AUTO_RAISE_DELAY: case META_PREF_AUTO_RAISE_DELAY:
return "AUTO_RAISE_DELAY"; return "AUTO_RAISE_DELAY";
case META_PREF_COMMANDS:
return "COMMANDS";
} }
return "(unknown)"; return "(unknown)";
@ -822,6 +853,18 @@ static MetaKeyPref screen_bindings[] = {
{ META_KEYBINDING_CYCLE_WINDOWS, 0, 0 }, { META_KEYBINDING_CYCLE_WINDOWS, 0, 0 },
{ META_KEYBINDING_CYCLE_PANELS, 0, 0 }, { META_KEYBINDING_CYCLE_PANELS, 0, 0 },
{ META_KEYBINDING_SHOW_DESKTOP, 0, 0 }, { META_KEYBINDING_SHOW_DESKTOP, 0, 0 },
{ META_KEYBINDING_COMMAND_1, 0, 0 },
{ META_KEYBINDING_COMMAND_2, 0, 0 },
{ META_KEYBINDING_COMMAND_3, 0, 0 },
{ META_KEYBINDING_COMMAND_4, 0, 0 },
{ META_KEYBINDING_COMMAND_5, 0, 0 },
{ META_KEYBINDING_COMMAND_6, 0, 0 },
{ META_KEYBINDING_COMMAND_7, 0, 0 },
{ META_KEYBINDING_COMMAND_8, 0, 0 },
{ META_KEYBINDING_COMMAND_9, 0, 0 },
{ META_KEYBINDING_COMMAND_10, 0, 0 },
{ META_KEYBINDING_COMMAND_11, 0, 0 },
{ META_KEYBINDING_COMMAND_12, 0, 0 },
{ NULL, 0, 0 } { NULL, 0, 0 }
}; };
@ -904,6 +947,33 @@ init_bindings (void)
} }
} }
static void
init_commands (void)
{
int i;
GError *err;
i = 0;
while (i < NUM_COMMANDS)
{
char *str_val;
char *key;
key = meta_prefs_get_gconf_key_for_command (i);
err = NULL;
str_val = gconf_client_get_string (default_client, key, &err);
cleanup_error (&err);
update_command (key, str_val);
g_free (str_val);
g_free (key);
++i;
}
}
static gboolean static gboolean
update_binding (MetaKeyPref *binding, update_binding (MetaKeyPref *binding,
const char *value) const char *value)
@ -1004,6 +1074,68 @@ update_screen_binding (const char *name,
return find_and_update_binding (screen_bindings, name, value); return find_and_update_binding (screen_bindings, name, value);
} }
static gboolean
update_command (const char *name,
const char *value)
{
char *p;
int i;
p = strrchr (name, '_');
if (p == NULL)
{
meta_topic (META_DEBUG_KEYBINDINGS,
"Command %s has no underscore?\n", name);
return FALSE;
}
++p;
if (!g_ascii_isdigit (*p))
{
meta_topic (META_DEBUG_KEYBINDINGS,
"Command %s doesn't end in number?\n", name);
return FALSE;
}
i = atoi (p);
i -= 1; /* count from 0 not 1 */
if (i >= NUM_COMMANDS)
{
meta_topic (META_DEBUG_KEYBINDINGS,
"Command %d is too highly numbered, ignoring\n", i);
return FALSE;
}
g_free (commands[i]);
commands[i] = g_strdup (value);
meta_topic (META_DEBUG_KEYBINDINGS,
"Updated command %d to \"%s\"\n",
i, commands[i] ? commands[i] : "none");
return TRUE;
}
const char*
meta_prefs_get_command (int i)
{
g_return_val_if_fail (i >= 0 && i < NUM_COMMANDS, NULL);
return commands[i];
}
char*
meta_prefs_get_gconf_key_for_command (int i)
{
char *key;
key = g_strdup_printf (KEY_COMMAND_PREFIX"%d", i + 1);
return key;
}
void void
meta_prefs_get_screen_bindings (const MetaKeyPref **bindings, meta_prefs_get_screen_bindings (const MetaKeyPref **bindings,
int *n_bindings) int *n_bindings)

View File

@ -37,7 +37,8 @@ typedef enum
META_PREF_APPLICATION_BASED, META_PREF_APPLICATION_BASED,
META_PREF_WINDOW_KEYBINDINGS, META_PREF_WINDOW_KEYBINDINGS,
META_PREF_SCREEN_KEYBINDINGS, META_PREF_SCREEN_KEYBINDINGS,
META_PREF_DISABLE_WORKAROUNDS META_PREF_DISABLE_WORKAROUNDS,
META_PREF_COMMANDS
} MetaPreference; } MetaPreference;
typedef void (* MetaPrefsChangedFunc) (MetaPreference pref, typedef void (* MetaPrefsChangedFunc) (MetaPreference pref,
@ -61,6 +62,10 @@ gboolean meta_prefs_get_disable_workarounds (void);
gboolean meta_prefs_get_auto_raise (void); gboolean meta_prefs_get_auto_raise (void);
int meta_prefs_get_auto_raise_delay (void); int meta_prefs_get_auto_raise_delay (void);
const char* meta_prefs_get_command (int i);
char* meta_prefs_get_gconf_key_for_command (int i);
void meta_prefs_set_num_workspaces (int n_workspaces); void meta_prefs_set_num_workspaces (int n_workspaces);
/* Screen bindings */ /* Screen bindings */
@ -85,6 +90,18 @@ void meta_prefs_set_num_workspaces (int n_workspaces);
#define META_KEYBINDING_CYCLE_WINDOWS "cycle_windows" #define META_KEYBINDING_CYCLE_WINDOWS "cycle_windows"
#define META_KEYBINDING_CYCLE_PANELS "cycle_panels" #define META_KEYBINDING_CYCLE_PANELS "cycle_panels"
#define META_KEYBINDING_SHOW_DESKTOP "show_desktop" #define META_KEYBINDING_SHOW_DESKTOP "show_desktop"
#define META_KEYBINDING_COMMAND_1 "run_command_1"
#define META_KEYBINDING_COMMAND_2 "run_command_2"
#define META_KEYBINDING_COMMAND_3 "run_command_3"
#define META_KEYBINDING_COMMAND_4 "run_command_4"
#define META_KEYBINDING_COMMAND_5 "run_command_5"
#define META_KEYBINDING_COMMAND_6 "run_command_6"
#define META_KEYBINDING_COMMAND_7 "run_command_7"
#define META_KEYBINDING_COMMAND_8 "run_command_8"
#define META_KEYBINDING_COMMAND_9 "run_command_9"
#define META_KEYBINDING_COMMAND_10 "run_command_10"
#define META_KEYBINDING_COMMAND_11 "run_command_11"
#define META_KEYBINDING_COMMAND_12 "run_command_12"
/* Window bindings */ /* Window bindings */
#define META_KEYBINDING_WINDOW_MENU "activate_window_menu" #define META_KEYBINDING_WINDOW_MENU "activate_window_menu"
@ -137,7 +154,19 @@ typedef enum _MetaKeyBindingAction
META_KEYBINDING_ACTION_SWITCH_PANELS, META_KEYBINDING_ACTION_SWITCH_PANELS,
META_KEYBINDING_ACTION_CYCLE_WINDOWS, META_KEYBINDING_ACTION_CYCLE_WINDOWS,
META_KEYBINDING_ACTION_CYCLE_PANELS, META_KEYBINDING_ACTION_CYCLE_PANELS,
META_KEYBINDING_ACTION_SHOW_DESKTOP META_KEYBINDING_ACTION_SHOW_DESKTOP,
META_KEYBINDING_ACTION_COMMAND_1,
META_KEYBINDING_ACTION_COMMAND_2,
META_KEYBINDING_ACTION_COMMAND_3,
META_KEYBINDING_ACTION_COMMAND_4,
META_KEYBINDING_ACTION_COMMAND_5,
META_KEYBINDING_ACTION_COMMAND_6,
META_KEYBINDING_ACTION_COMMAND_7,
META_KEYBINDING_ACTION_COMMAND_8,
META_KEYBINDING_ACTION_COMMAND_9,
META_KEYBINDING_ACTION_COMMAND_10,
META_KEYBINDING_ACTION_COMMAND_11,
META_KEYBINDING_ACTION_COMMAND_12,
} MetaKeyBindingAction; } MetaKeyBindingAction;
typedef struct typedef struct