rpms/rhythmbox/devel rhythmbox-0.9.6-fix-keybinding.patch, NONE, 1.1 rhythmbox.spec, 1.83, 1.84
fedora-cvs-commits at redhat.com
fedora-cvs-commits at redhat.com
Mon Oct 23 02:06:19 UTC 2006
- Previous message (by thread): rpms/rhythmbox/devel rhythmbox-0.9.6-use-icon-name.patch, NONE, 1.1 rhythmbox.spec, 1.82, 1.83
- Next message (by thread): rpms/scim-bridge/devel .cvsignore, 1.23, 1.24 scim-bridge.spec, 1.35, 1.36 sources, 1.23, 1.24
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Author: mclasen
Update of /cvs/dist/rpms/rhythmbox/devel
In directory cvs.devel.redhat.com:/tmp/cvs-serv30469
Modified Files:
rhythmbox.spec
Added Files:
rhythmbox-0.9.6-fix-keybinding.patch
Log Message:
0.9.6
rhythmbox-0.9.6-fix-keybinding.patch:
lib/rb-preferences.h | 7
shell/rb-shell-player.c | 767 ++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 743 insertions(+), 31 deletions(-)
--- NEW FILE rhythmbox-0.9.6-fix-keybinding.patch ---
--- rhythmbox-0.9.6/lib/rb-preferences.h.fix-keybinding 2006-08-02 08:16:03.000000000 -0400
+++ rhythmbox-0.9.6/lib/rb-preferences.h 2006-10-22 21:58:29.000000000 -0400
@@ -69,6 +69,13 @@
#define CONF_PLUGIN_ACTIVE_KEY CONF_PLUGINS_PREFIX "/%s/active"
#define CONF_PLUGIN_HIDDEN_KEY CONF_PLUGINS_PREFIX "/%s/hidden"
+#define CONF_KEYBINDINGS_PREFIX "/apps/gnome_settings_daemon/keybindings"
+#define CONF_KEYBINDING_PLAY CONF_KEYBINDINGS_PREFIX "/play"
+#define CONF_KEYBINDING_PAUSE CONF_KEYBINDINGS_PREFIX "/pause"
+#define CONF_KEYBINDING_STOP CONF_KEYBINDINGS_PREFIX "/stop"
+#define CONF_KEYBINDING_PREVIOUS CONF_KEYBINDINGS_PREFIX "/previous"
+#define CONF_KEYBINDING_NEXT CONF_KEYBINDINGS_PREFIX "/next"
+
G_END_DECLS
#endif /* __RB_PREFERENCES_H */
--- rhythmbox-0.9.6/shell/rb-shell-player.c.fix-keybinding 2006-09-24 07:03:49.000000000 -0400
+++ rhythmbox-0.9.6/shell/rb-shell-player.c 2006-10-22 22:07:49.000000000 -0400
@@ -23,6 +23,7 @@
#include "config.h"
+#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
@@ -41,6 +42,11 @@
#include <gdk/gdkx.h>
#endif /* HAVE_MMKEYS */
+#define HAVE_XKB
+#ifdef HAVE_XKB
+#include <X11/XKBlib.h>
+#include <gdk/gdkx.h>
+#endif
#include "rb-property-view.h"
#include "rb-shell-player.h"
#include "rb-stock-icons.h"
@@ -164,12 +170,31 @@
#define CONF_STATE CONF_PREFIX "/state"
+typedef enum
+{
+ RB_SHELL_PLAYER_MEDIA_ACTION_TYPE_NONE = 0,
+ RB_SHELL_PLAYER_MEDIA_ACTION_TYPE_PLAY,
+ RB_SHELL_PLAYER_MEDIA_ACTION_TYPE_PAUSE,
+ RB_SHELL_PLAYER_MEDIA_ACTION_TYPE_STOP,
+ RB_SHELL_PLAYER_MEDIA_ACTION_TYPE_PREVIOUS,
+ RB_SHELL_PLAYER_MEDIA_ACTION_TYPE_NEXT,
+ RB_SHELL_PLAYER_NUMBER_OF_MEDIA_ACTIONS
+} RBShellPlayerMediaActionType;
+
+typedef struct
+{
+ RBShellPlayerMediaActionType type;
+ guint gconf_global_keybinding_id;
+ GList *key_grab_list;
+} RBShellPlayerMediaAction;
+
struct RBShellPlayerPrivate
{
RhythmDB *db;
gboolean syncing_state;
gboolean queue_only;
+ gboolean uses_xkb;
RBSource *selected_source;
RBSource *source;
@@ -201,6 +226,8 @@
guint gconf_play_order_id;
guint gconf_song_position_slider_visibility_id;
+ RBShellPlayerMediaAction media_actions[RB_SHELL_PLAYER_NUMBER_OF_MEDIA_ACTIONS - 1];
+
gboolean mute;
float volume;
@@ -686,6 +713,623 @@
GDK_THREADS_LEAVE ();
}
+typedef struct {
+ KeyCode key_code;
+ guint xmodifier_mask;
+ gint group;
+} RBShellPlayerKeyGrab;
+
+static gint
+get_current_group (void)
+{
+ gint current_group = 0;
+
+#ifdef HAVE_XKB
+ XkbStateRec state = { 0 };
+
+
+ if (XkbGetState (GDK_DISPLAY (), XkbUseCoreKbd, &state) == Success)
+ current_group = (gint) XkbStateGroup (&state);
+#endif
+ return current_group;
+}
+
+static void
+set_current_group (gint group)
+{
+ XkbLockGroup (GDK_DISPLAY (), XkbUseCoreKbd, group);
+}
+
+static RBShellPlayerKeyGrab *
+rb_shell_player_key_grab_new (RBShellPlayer *player,
+ KeyCode key_code,
+ guint xmodifier_mask,
+ gint group)
+{
+ RBShellPlayerKeyGrab *key_grab;
+ Screen *screen;
+ Window root_window;
+ gint old_group, status;
+
+ key_grab = NULL;
+
+ screen = GDK_SCREEN_XSCREEN (gtk_widget_get_screen (GTK_WIDGET (player)));
+ root_window = RootWindowOfScreen (screen);
+
+ if (group >= 0) {
+ gdk_x11_grab_server ();
+ old_group = get_current_group ();
+
+ if (old_group != group)
+ set_current_group (group);
+
+ XkbChangeEnabledControls (GDK_DISPLAY (), XkbUseCoreKbd,
+ XkbIgnoreGroupLockMask, 0);
+ } else {
+ XkbChangeEnabledControls (GDK_DISPLAY (), XkbUseCoreKbd,
+ XkbIgnoreGroupLockMask,
+ XkbIgnoreGroupLockMask);
+ }
+
+ if (status = XGrabKey (GDK_DISPLAY (), key_code, xmodifier_mask,
+ root_window, True, GrabModeAsync,
+ GrabModeAsync) != True) {
+ goto out;
+ }
+
+ key_grab = g_slice_new0 (RBShellPlayerKeyGrab);
+
+ key_grab->key_code = key_code;
+ key_grab->xmodifier_mask = xmodifier_mask;
+ key_grab->group = group;
+
+out:
+ if (group >= 0) {
+ if (old_group != group)
+ set_current_group (old_group);
+ gdk_x11_ungrab_server ();
+ }
+
+ return key_grab;
+}
+
+static void
+rb_shell_player_key_grab_free (RBShellPlayer *player,
+ RBShellPlayerKeyGrab *key_grab)
+{
+ Screen *screen;
+ Window root_window;
+
+ screen = GDK_SCREEN_XSCREEN (gtk_widget_get_screen (GTK_WIDGET (player)));
+ root_window = RootWindowOfScreen (screen);
+
+ XUngrabKey (GDK_DISPLAY (), key_grab->key_code,
+ key_grab->xmodifier_mask,
+ root_window);
+
+ g_slice_free (RBShellPlayerKeyGrab, key_grab);
+}
+
+
+
+/* Translate real and virtual modifiers specified in GdkModifierType
+ * to something that can be passed to XGrabKey.
+ * Returns FALSE if a virtual modifier can not be mapped because it
+ * is not bound.
+ */
+static gboolean
+modifiers_to_xmodifiers (GdkModifierType modifiers, guint *xmodifiers)
+{
+#ifdef HAVE_XKB
+ XkbDescRec *xkb;
+#endif
+ gboolean mask_is_translated;
+ guint new_xmodifiers;
+ gint i, j;
+
+ static struct {
+ GdkModifierType type;
+ guint xmodifier_mask;
+ const gchar *virtual_name;
+ } modifier_mapping[] = {
+ { GDK_SHIFT_MASK, ShiftMask },
+ { GDK_LOCK_MASK, LockMask },
+ { GDK_CONTROL_MASK, ControlMask },
+ { GDK_MOD1_MASK, Mod1Mask },
+ { GDK_MOD2_MASK, Mod2Mask },
+ { GDK_MOD3_MASK, Mod3Mask },
+ { GDK_MOD4_MASK, Mod4Mask },
+ { GDK_MOD5_MASK, Mod5Mask },
+ { GDK_BUTTON1_MASK, Button1Mask },
+ { GDK_BUTTON2_MASK, Button2Mask },
+ { GDK_BUTTON3_MASK, Button3Mask },
+ { GDK_BUTTON4_MASK, Button4Mask },
+ { GDK_BUTTON5_MASK, Button5Mask },
+ { GDK_META_MASK, 0, "Meta" },
+ { GDK_SUPER_MASK, 0, "Super" },
+ { GDK_HYPER_MASK, 0, "Hyper" },
+ { (GdkModifierType) 0 }
+ };
+
+ mask_is_translated = TRUE;
+
+#if HAVE_XKB
+ xkb = XkbGetMap (GDK_DISPLAY (), XkbModifierMapMask | XkbVirtualModsMask, XkbUseCoreKbd);
+ XkbGetNames (GDK_DISPLAY (), XkbGroupNamesMask | XkbVirtualModNamesMask, xkb);
+#endif
+
+ new_xmodifiers = 0;
+ for (i = 0; modifier_mapping[i].type != (GdkModifierType) 0; i++) {
+ if (modifiers & modifier_mapping[i].type) {
+ Atom atom;
+
+ if (modifier_mapping[j].xmodifier_mask != 0) {
+ new_xmodifiers |= modifier_mapping[i].xmodifier_mask;
+ continue;
+ }
+
+#if HAVE_XKB
+ g_assert (modifier_mapping[j].virtual_name != NULL);
+
+ atom = gdk_x11_get_xatom_by_name (modifier_mapping[j].virtual_name);
+ for (j = 0; j < XkbNumVirtualMods; j++) {
+
+ if (atom == xkb->names->vmods[j]) {
+ if (!xkb->server->vmods[j]) {
+ XkbFreeKeyboard (xkb, 0, True);
+ return FALSE;
+ }
+
+ new_xmodifiers |= xkb->server->vmods[j];
+ break;
+ }
+ }
+#endif
+ }
+ }
+
+#if HAVE_XKB
+ XkbFreeKeyboard (xkb, 0, True);
+#endif
+
+ if (xmodifiers)
+ *xmodifiers = new_xmodifiers;
+
+ return TRUE;
+}
+
+static gboolean
+global_keybindings_are_independent_of_lock_modifiers (void)
+{
+ gboolean lock_modifiers_are_ignored;
+
+#ifdef HAVE_XKB
+ XkbDescRec *xkb;
+
+ lock_modifiers_are_ignored = FALSE;
+
+ xkb = XkbGetMap (GDK_DISPLAY (), 0, XkbUseCoreKbd);
+
+ if (XkbGetControls (GDK_DISPLAY (),
+ XkbIgnoreLockModsMask, xkb) != Success)
+ goto out;
+
+ if (xkb->ctrls == NULL)
+ goto out;
+
+ if (!(xkb->ctrls->enabled_ctrls & XkbIgnoreGroupLockMask))
+ goto out;
+
+ if (xkb->ctrls->ignore_lock.mask == 0)
+ goto out;
+
+ /* We assume that a non-zero ignore_lock mask means
+ * that settings daemon has setup xkb to make XGrabKey
+ * have sane semantics (where changing capslock doesn't
+ * make key bindings stop working)
+ */
+ lock_modifiers_are_ignored = TRUE;
+out:
+ if (xkb->ctrls != NULL)
+ XkbFreeControls (xkb, 0, True);
+
+ if (xkb != NULL)
+ XkbFreeKeyboard (xkb, 0, True);
+#endif
+
+ return lock_modifiers_are_ignored;
+}
+
+static gboolean
+get_key_code_from_keyval (guint keyval, GdkModifierType modifiers,
+ KeyCode *key_code, guint *xmodifiers)
+{
+ GdkKeymapKey *keys;
+ gint number_of_keys, i, current_group;
+
+ keys = NULL;
+ number_of_keys = 0;
+ if (!gdk_keymap_get_entries_for_keyval (gdk_keymap_get_default (),
+ keyval, &keys, &number_of_keys))
+ return FALSE;
+
+ current_group = get_current_group ();
+ for (i = 0; i < number_of_keys; i++) {
+ if (keys[i].group == current_group)
+ break;
+ }
+
+ if (i != number_of_keys) {
+ if (key_code)
+ *key_code = keys[i].keycode;
+ }
+
+ g_free (keys);
+
+ if (xmodifiers) {
+ if (!modifiers_to_xmodifiers (modifiers, xmodifiers))
+ return FALSE;
+ }
+
+ return i != number_of_keys;
+}
+static gboolean
+rb_shell_player_bind_keyval_globally_fallback (RBShellPlayer *player,
+ guint keyval,
+ GdkModifierType modifiers)
+{
+ return FALSE;
+}
+
+static gboolean
+rb_shell_player_bind_keyval_globally (RBShellPlayer *player,
+ guint keyval,
+ GdkModifierType modifiers,
+ RBShellPlayerKeyGrab ***key_grabs)
+{
+ KeyCode key_code;
+ guint key_mask;
+ gboolean keyval_is_bound;
+ Window root_window;
+ GdkKeymapKey *keys;
+ gint number_of_keys, i, group;
+ GPtrArray *key_grabs_array;
+ RBShellPlayerKeyGrab *key_grab;
+
+
+#if 0
+ if (!player->priv->uses_xkb ||
+ !global_keybindings_are_independent_of_lock_modifiers ())
+ return rb_shell_player_bind_keyval_globally_fallback (player,
+ keyval,
+ modifiers);
+#endif
+
+ /* So there is conceivably more than one "keycode" (think physical key)
+ * per "keyval" (think the symbol that actually gets produced,
+ * ~KeySym in X speak). This can happen because some keyboards are
+ * configured to have multiple layouts (say qwerty and dvorak).
+ *
+ * In those cases we really only want to grab one keycode because it
+ * would be rather strange if "ctrl-o" got grabbed just because ctrl-s
+ * got grabbed (in the qwerty/dvorak case). We can't grab for both and
+ * then filter out (ignore) based on group, because then other apps
+ * won't be able to grab for the ignored keybindings.
+ *
+ * There is another multiple layout case that's also interesting here,
+ * a keyboard with multiple alphabets (say latin and cyrillic).
+ * In these cases there is no overlap in between layouts so there won't
+ * be any conflict. We do want (say) ctrl-Ñ to act like ctrl-s
+ * is pressed though.
+ *
+ * Loosely, we could say the way we want to handle those two types of
+ * cases are "bind to keyval" and "bind to keycode", respectively.
+ *
+ * Now that's the semantics we want, how do we implement it? The core
+ * X protocol only gives us XGrabKey which takes a key code and a
+ * modifier mask and produces a passive grab that, by default,
+ * will only activate when the exact combination of modifiers
+ * specified in the mask are present. This is just a broken design,
+ * because it means global keybindings stop working if the user presses
+ * caps lock or scroll lock (which are modifiers, too!). With a little
+ * XKB tweaking, (namely a call to XkbSetIgnoreLockMods after some prep
+ * work) we can change the semantics of this function to activate only
+ * when the interesting modifiers are present. Now how do groups fit
+ * in? XKB doesn't give us a lot of help here. We can only say whether
+ * the grab is per the current group or for ALL groups (by setting the
+ * IgnoreGroupLock boolean). The latter case is fine for our
+ * "bind to keycode" case but we still need to figure out the "bind to
+ * keyval" case. I guess the answer is GrabServer, set group, GrabKey,
+ * unset group, UnGrabServer. ick. So the final plan is, given a keyval
+ * and modifier mask:
+ *
+ * - loop through all the available groups of the system.
+ * - If only one group has the keyval in their layout then we look up
+ * the key code associated with keyval and grab it for all groups.
+ * - If more than one group has the keyval in their layout then all
+ * those layouts need "bind to keyval" semantics. We grab the
+ * server, switch to each group in turn, grab the key with the passed
+ * in mask for each group, revert to the original group and ungrab
+ * the server. The groups that don't have the keysym in their
+ * layout need the "bind to keycode" semantics. The keycode to
+ * bind to is given by the keysym in the original group.
+ *
+ * One interesting note is that we are jumping through A LOT of hoops to
+ * support users with qwerty and dvorak layouts. I'm wondering if it's
+ * really, actually worth it. If we didn't support that case, then we
+ * could just use IgnoreGroupLock and be done.
+ */
+
+ keyval_is_bound = FALSE;
+
+ keys = NULL;
+ number_of_keys = 0;
+ if (!gdk_keymap_get_entries_for_keyval (NULL, keyval, &keys, &number_of_keys))
+ return FALSE;
+
+ g_assert (number_of_keys > 0);
+
+ root_window =
+ RootWindowOfScreen (GDK_SCREEN_XSCREEN (gtk_widget_get_screen (GTK_WIDGET (player))));
+
+ group = keys[0].group;
+ for (i = 0; i < number_of_keys; i++) {
+ if (keys[i].group != group)
+ break;
+ }
+
+ key_grabs_array = g_ptr_array_new ();
+
+ /* every entry for keyval is in the same group
+ * we need to use "bind to keycode" semantics
+ */
+ if (i == number_of_keys) {
+ g_free (keys);
+ keys = NULL;
+
+ get_key_code_from_keyval (keyval, modifiers, &key_code, &key_mask);
+ key_grab = rb_shell_player_key_grab_new (player, key_code, key_mask,
+ -1);
+
+ if (!key_grab)
+ goto out;
+
+ g_ptr_array_add (key_grabs_array, key_grab);
+ g_ptr_array_add (key_grabs_array, NULL);
+
+ keyval_is_bound = TRUE;
+ goto out;
+
+ } else {
+ /* Otherwise, we need to pick between
+ * "bind to keyval" and "bind to keycode" based
+ * on whether the group matches the current group
+ * (well actually the group that was active when the
+ * user set the keybinding, but we don't currently
+ * export that information)
+ */
+ for (i = 0; i < number_of_keys; i++) {
+
+ /* "bind to keycode"
+ */
+ if (keys[i].group == group) {
+ key_grab = rb_shell_player_key_grab_new (player,
+ keys[i].keycode,
+ key_mask,
+ -1);
+
+ if (!key_grab)
+ goto out;
+
+ g_ptr_array_add (key_grabs_array, key_grab);
+ continue;
+ }
+
+ /* "bind to keyval"
+ */
+ set_current_group (keys[i].group);
+ get_key_code_from_keyval (keyval, modifiers, &key_code, &key_mask);
+ key_grab = rb_shell_player_key_grab_new (player, key_code, key_mask,
+ keys[i].group);
+
+ if (!key_grab)
+ goto out;
+
+ g_ptr_array_add (key_grabs_array, key_grab);
+ }
+ g_ptr_array_add (key_grabs_array, NULL);
+
+ g_free (keys);
+ keys = NULL;
+ }
+
+out:
+ if (keyval_is_bound && key_grabs != NULL)
+ *key_grabs = (RBShellPlayerKeyGrab **) g_ptr_array_free (key_grabs_array, FALSE);
+ else
+ g_ptr_array_free (key_grabs_array, TRUE);
+
+ return keyval_is_bound;
+}
+
+static void
+rb_shell_player_unbind_keyval_globally (RBShellPlayer *player,
+ RBShellPlayerKeyGrab **key_grabs)
+{
+ Window root_window;
+ int i;
+
+ root_window =
+ RootWindowOfScreen (GDK_SCREEN_XSCREEN (gtk_widget_get_screen (GTK_WIDGET (player))));
+
+ for (i = 0; key_grabs[i] != NULL; i++) {
+ rb_shell_player_key_grab_free (player, key_grabs[i]);
+ }
+ g_free (key_grabs);
+}
+
+static gboolean
+rb_shell_player_bind_media_action (RBShellPlayer *player,
+ RBShellPlayerMediaActionType action_type,
+ const char *accelerator)
+{
+ guint keyval;
+ int i, action_index;
+ GdkModifierType modifiers;
+ RBShellPlayerKeyGrab *key_grab, **key_grabs;
+
+ keyval = 0;
+ modifiers = 0;
+
+ if (action_type == RB_SHELL_PLAYER_MEDIA_ACTION_TYPE_NONE)
+ return FALSE;
+
+ if (accelerator == NULL)
+ return FALSE;
+
+ gtk_accelerator_parse (accelerator, &keyval, &modifiers);
+
+ /* Not a valid accelerator name. Maybe it's just a raw
+ * hex key code?
+ */
+ if (keyval == 0) {
+ gulong key_code;
+ char *end;
+
+ end = NULL;
+ errno = 0;
+ key_code = strtoul (accelerator, &end, 0);
+ g_print ("trying key code 0x%x for accelerator '%s'\n", key_code,
+ accelerator);
+
+ if ((accelerator[0] != '\0') && (*end == '\0') &&
+ (((KeyCode) key_code) == key_code) &&
+ ((key_code != G_MAXLONG) || (errno == 0))) {
+ key_grab = rb_shell_player_key_grab_new (player, key_code, 0,
+ -1);
+
+ if (!key_grab)
+ return FALSE;
+
+ for (i = 0; i < G_N_ELEMENTS (player->priv->media_actions); i++)
+ if (player->priv->media_actions[i].type == action_type) {
+ player->priv->media_actions[i].key_grab_list =
+ g_list_append (player->priv->media_actions[i].key_grab_list,
+ key_grab);
+ break;
+ }
+ }
+ return FALSE;
+ }
+
+ key_grabs = NULL;
+ if (!rb_shell_player_bind_keyval_globally (player, keyval, modifiers, &key_grabs))
+ return FALSE;
+
+ action_index = -1;
+ for (i = 0; i < G_N_ELEMENTS (player->priv->media_actions); i++) {
+ if (player->priv->media_actions[i].type == action_type) {
+ action_index = i;
+ break;
+ }
+ }
+
+ if (action_index >= 0)
+ for (i = 0; key_grabs[i] != NULL; i++) {
+ player->priv->media_actions[action_index].key_grab_list =
+ g_list_append (player->priv->media_actions[action_index].key_grab_list,
+ key_grabs[i]);
+ }
+ g_free (key_grabs);
+
+ return TRUE;
+}
+
+static void
+rb_shell_player_unbind_media_action (RBShellPlayer *player,
+ RBShellPlayerMediaActionType action_type)
+{
+ int i;
+
+ for (i = 0; i < G_N_ELEMENTS (player->priv->media_actions); i++) {
+ if (player->priv->media_actions[i].type == action_type) {
+ GList *tmp;
+ GPtrArray *key_grabs_array;
+ RBShellPlayerKeyGrab **key_grabs;
+
+ key_grabs_array = g_ptr_array_new ();
+ tmp = player->priv->media_actions[i].key_grab_list;
+ while (tmp != NULL) {
+ g_ptr_array_add (key_grabs_array, tmp->data);
+
+ tmp = tmp->next;
+ }
+ g_ptr_array_add (key_grabs_array, NULL);
+ key_grabs = (RBShellPlayerKeyGrab **)
+ g_ptr_array_free (key_grabs_array, FALSE);
+ rb_shell_player_unbind_keyval_globally (player, key_grabs);
+ break;
+ }
+ }
+}
+
+static RBShellPlayerMediaActionType
+rb_shell_player_get_action_type_from_conf_key (const char *conf_key)
+{
+ static const struct {
+ const char *conf_key;
+ RBShellPlayerMediaActionType action_type;
+ } action_key_map[] = {
+ { CONF_KEYBINDING_PLAY, RB_SHELL_PLAYER_MEDIA_ACTION_TYPE_PLAY },
+ { CONF_KEYBINDING_PAUSE, RB_SHELL_PLAYER_MEDIA_ACTION_TYPE_PAUSE },
+ { CONF_KEYBINDING_STOP, RB_SHELL_PLAYER_MEDIA_ACTION_TYPE_STOP },
+ { CONF_KEYBINDING_PREVIOUS, RB_SHELL_PLAYER_MEDIA_ACTION_TYPE_PREVIOUS },
+ { CONF_KEYBINDING_NEXT, RB_SHELL_PLAYER_MEDIA_ACTION_TYPE_NEXT },
+ { NULL, RB_SHELL_PLAYER_MEDIA_ACTION_TYPE_NONE },
+ };
+ int i;
+
+ for (i = 0; action_key_map[i].conf_key != NULL; i++) {
+ if (strcmp (action_key_map[i].conf_key, conf_key) == 0)
+ return action_key_map[i].action_type;
+ }
+
+ return RB_SHELL_PLAYER_MEDIA_ACTION_TYPE_NONE;
+}
+
+static void
+gconf_global_keybinding_changed (GConfClient *client, guint cnxn_id, GConfEntry *entry, gpointer user_data)
+{
+ RBShellPlayer *player;
+ RBShellPlayerMediaActionType action_type;
+ const gchar *keybinding;
+
+ player = RB_SHELL_PLAYER (user_data);
+ keybinding = gconf_value_get_string (gconf_entry_get_value (entry));
+
+ action_type = rb_shell_player_get_action_type_from_conf_key (gconf_entry_get_key (entry));
+
+ rb_shell_player_unbind_media_action (player, action_type);
+ rb_shell_player_bind_media_action (player, action_type, keybinding);
+}
+
+static void
+rb_shell_player_init_xkb (RBShellPlayer *player)
+{
+#ifdef HAVE_XKB
+ int op_code, xkb_event_code, error_code, major, minor;
+
+ error_code = 0;
+ major = XkbMajorVersion;
+ minor = XkbMinorVersion;
+
+ player->priv->uses_xkb =
+ XkbQueryExtension (GDK_DISPLAY (),
+ &op_code, &xkb_event_code,
+ &error_code, &major, &minor) == Success;
+#endif
+}
+
static void
rb_shell_player_init (RBShellPlayer *player)
{
@@ -705,6 +1349,8 @@
exit (1);
}
+ rb_shell_player_init_xkb (player);
+
gtk_box_set_spacing (GTK_BOX (player), 12);
gtk_container_set_border_width (GTK_CONTAINER (player), 3);
@@ -758,6 +1404,40 @@
player);
#ifdef HAVE_MMKEYS
+ struct {
+ RBShellPlayerMediaActionType type;
+ const gchar *conf_key;
+ } type_key_map[] = {
+ { RB_SHELL_PLAYER_MEDIA_ACTION_TYPE_PLAY, CONF_KEYBINDING_PLAY },
+ { RB_SHELL_PLAYER_MEDIA_ACTION_TYPE_PAUSE, CONF_KEYBINDING_PAUSE },
+ { RB_SHELL_PLAYER_MEDIA_ACTION_TYPE_STOP, CONF_KEYBINDING_STOP },
+ { RB_SHELL_PLAYER_MEDIA_ACTION_TYPE_PREVIOUS, CONF_KEYBINDING_PREVIOUS },
+ { RB_SHELL_PLAYER_MEDIA_ACTION_TYPE_NEXT, CONF_KEYBINDING_NEXT },
+ { RB_SHELL_PLAYER_MEDIA_ACTION_TYPE_NONE, NULL }
+ };
+ int i;
+
+ gconf_client_add_dir (eel_gconf_client_get_global (),
+ CONF_KEYBINDINGS_PREFIX,
+ GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
+ for (i = 0; type_key_map[i].type != RB_SHELL_PLAYER_MEDIA_ACTION_TYPE_NONE; i++) {
+ const char *keybinding;
+
+ player->priv->media_actions[i].type = type_key_map[i].type;
+ player->priv->media_actions[i].gconf_global_keybinding_id =
+ eel_gconf_notification_add (type_key_map[i].conf_key,
+ (GConfClientNotifyFunc) gconf_global_keybinding_changed,
+ player);
+ player->priv->media_actions[i].key_grab_list = NULL;
+ keybinding = gconf_client_get_string (eel_gconf_client_get_global (),
+ type_key_map[i].conf_key,
+ NULL);
+
+ rb_shell_player_bind_media_action (player,
+ player->priv->media_actions[i].type,
+ keybinding);
+ }
+
/* Enable Multimedia Keys */
rb_shell_player_init_mmkeys (player);
#endif /* HAVE_MMKEYS */
@@ -2970,6 +3650,38 @@
}
}
+static RBShellPlayerMediaActionType
+rb_shell_player_find_action_from_key_press (RBShellPlayer *player,
+ XKeyEvent *event)
+{
+ XkbDescRec *xkb;
+ int i;
+ int group;
+ KeySym keysym;
+
+ group = XkbGroupForCoreState (event->state);
+ for (i = 0; i < G_N_ELEMENTS (player->priv->media_actions); i++) {
+ GList *tmp;
+
+ tmp = player->priv->media_actions[i].key_grab_list;
+ while (tmp != NULL) {
+ RBShellPlayerKeyGrab *key_grab;
+
+ key_grab = (RBShellPlayerKeyGrab *) tmp->data;
+
+ if ((key_grab->key_code == event->keycode) &&
+ (((key_grab->group < 0) || (key_grab->group == group))) &&
+ (key_grab->xmodifier_mask == event->state)) {
+ return player->priv->media_actions[i].type;
+ }
+
+ tmp = tmp->next;
+ }
+ }
+
+ return RB_SHELL_PLAYER_MEDIA_ACTION_TYPE_NONE;
+}
+
static GdkFilterReturn
filter_mmkeys (GdkXEvent *xevent,
GdkEvent *event,
@@ -2978,6 +3690,7 @@
XEvent *xev;
XKeyEvent *key;
RBShellPlayer *player;
+ RBShellPlayerMediaActionType action_type;
xev = (XEvent *) xevent;
if (xev->type != KeyPress) {
return GDK_FILTER_CONTINUE;
@@ -2986,41 +3699,38 @@
key = (XKeyEvent *) xevent;
player = (RBShellPlayer *)data;
+ action_type = rb_shell_player_find_action_from_key_press (player, key);
- if (XKeysymToKeycode (GDK_DISPLAY (), XF86XK_AudioPlay) == key->keycode) {
- rb_shell_player_playpause (player, FALSE, NULL);
- return GDK_FILTER_REMOVE;
- } else if (XKeysymToKeycode (GDK_DISPLAY (), XF86XK_AudioPause) == key->keycode) {
- rb_shell_player_pause (player, NULL);
- return GDK_FILTER_REMOVE;
- } else if (XKeysymToKeycode (GDK_DISPLAY (), XF86XK_AudioStop) == key->keycode) {
- rb_shell_player_stop (player);
- return GDK_FILTER_REMOVE;
- } else if (XKeysymToKeycode (GDK_DISPLAY (), XF86XK_AudioPrev) == key->keycode) {
- rb_shell_player_cmd_previous (NULL, player);
- return GDK_FILTER_REMOVE;
- } else if (XKeysymToKeycode (GDK_DISPLAY (), XF86XK_AudioNext) == key->keycode) {
- rb_shell_player_cmd_next (NULL, player);
- return GDK_FILTER_REMOVE;
- } else {
- return GDK_FILTER_CONTINUE;
- }
+ switch (action_type) {
+ case RB_SHELL_PLAYER_MEDIA_ACTION_TYPE_PLAY:
+ rb_shell_player_playpause (player, FALSE, NULL);
+ return GDK_FILTER_REMOVE;
+ case RB_SHELL_PLAYER_MEDIA_ACTION_TYPE_PAUSE:
+ rb_shell_player_pause (player, NULL);
+ return GDK_FILTER_REMOVE;
+ case RB_SHELL_PLAYER_MEDIA_ACTION_TYPE_STOP:
+ rb_shell_player_stop (player);
+ return GDK_FILTER_REMOVE;
+ case RB_SHELL_PLAYER_MEDIA_ACTION_TYPE_PREVIOUS:
+ rb_shell_player_cmd_previous (NULL, player);
+ return GDK_FILTER_REMOVE;
+ case RB_SHELL_PLAYER_MEDIA_ACTION_TYPE_NEXT:
+ rb_shell_player_cmd_next (NULL, player);
+ return GDK_FILTER_REMOVE;
+ default:
+ break;
+ }
+
+ return GDK_FILTER_CONTINUE;
}
static void
rb_shell_player_init_mmkeys (RBShellPlayer *shell_player)
{
- gint keycodes[] = {0, 0, 0, 0, 0};
GdkDisplay *display;
GdkScreen *screen;
GdkWindow *root;
- guint i, j;
-
- keycodes[0] = XKeysymToKeycode (GDK_DISPLAY (), XF86XK_AudioPlay);
- keycodes[1] = XKeysymToKeycode (GDK_DISPLAY (), XF86XK_AudioStop);
- keycodes[2] = XKeysymToKeycode (GDK_DISPLAY (), XF86XK_AudioPrev);
- keycodes[3] = XKeysymToKeycode (GDK_DISPLAY (), XF86XK_AudioNext);
- keycodes[4] = XKeysymToKeycode (GDK_DISPLAY (), XF86XK_AudioPause);
+ guint i;
display = gdk_display_get_default ();
@@ -3030,11 +3740,6 @@
if (screen != NULL) {
root = gdk_screen_get_root_window (screen);
- for (j = 0; j < G_N_ELEMENTS (keycodes) ; j++) {
- if (keycodes[j] != 0)
- grab_mmkey (keycodes[j], root);
- }
-
gdk_window_add_filter (root, filter_mmkeys,
(gpointer) shell_player);
}
Index: rhythmbox.spec
===================================================================
RCS file: /cvs/dist/rpms/rhythmbox/devel/rhythmbox.spec,v
retrieving revision 1.83
retrieving revision 1.84
diff -u -r1.83 -r1.84
--- rhythmbox.spec 23 Oct 2006 01:46:27 -0000 1.83
+++ rhythmbox.spec 23 Oct 2006 02:06:17 -0000 1.84
@@ -40,11 +40,7 @@
BuildRequires: perl-XML-Parser
Patch2: rhythmbox-0.9.6-use-icon-name.patch
-Patch3: rhythmbox-0.9.5-dbus-deprecated.patch
-Patch4: rhythmbox-0.9.5-transparent.patch
-# http://bugzilla.gnome.org/show_bug.cgi?id=355713
-Patch5: rhythmbox-0.9.5-missing-radio-crash.patch
-Patch6: rhythmbox-0.9.5-fix-keybinding.patch
+Patch6: rhythmbox-0.9.6-fix-keybinding.patch
%description
Rhythmbox is an integrated music management application based on the powerful
@@ -55,9 +51,6 @@
%prep
%setup -q
%patch2 -p1 -b .use-icon-name
-%patch3 -p1 -b .dbus-deprecated
-%patch4 -p1 -b .transparent
-%patch5 -p1 -b .missing-radio-crash
%patch6 -p1 -b .fix-keybinding
%build
- Previous message (by thread): rpms/rhythmbox/devel rhythmbox-0.9.6-use-icon-name.patch, NONE, 1.1 rhythmbox.spec, 1.82, 1.83
- Next message (by thread): rpms/scim-bridge/devel .cvsignore, 1.23, 1.24 scim-bridge.spec, 1.35, 1.36 sources, 1.23, 1.24
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the fedora-cvs-commits
mailing list