static void egg_cell_renderer_keys_get_property (GObject *object, guint param_id, GValue *value, GParamSpec *pspec) { EggCellRendererKeys *keys; g_return_if_fail (EGG_IS_CELL_RENDERER_KEYS (object)); keys = EGG_CELL_RENDERER_KEYS (object); switch (param_id) { case PROP_ACCEL_KEY: g_value_set_uint (value, keys->accel_key); break; case PROP_ACCEL_MASK: g_value_set_flags (value, keys->accel_mask); break; case PROP_ACCEL_MODE: g_value_set_int (value, keys->accel_mode); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); } }
static void ungrab_stuff(GtkWidget* widget, gpointer data) { EggCellRendererKeys* keys = EGG_CELL_RENDERER_KEYS(data); gdk_keyboard_ungrab(GDK_CURRENT_TIME); gdk_pointer_ungrab(GDK_CURRENT_TIME); g_signal_handlers_disconnect_by_func(G_OBJECT(keys->grab_widget), G_CALLBACK(grab_key_callback), data); }
static void ungrab_stuff(GtkWidget* widget, gpointer data) { EggCellRendererKeys* keys = EGG_CELL_RENDERER_KEYS(data); GdkDisplay *display; GdkSeat *seat; display = gtk_widget_get_display (widget); seat = gdk_display_get_default_seat (display); gdk_seat_ungrab (seat); g_signal_handlers_disconnect_by_func(G_OBJECT(keys->grab_widget), G_CALLBACK(grab_key_callback), data); }
static GtkCellEditable * egg_cell_renderer_keys_start_editing (GtkCellRenderer *cell, GdkEvent *event, GtkWidget *widget, const gchar *path, GdkRectangle *background_area, GdkRectangle *cell_area, GtkCellRendererState flags) { GtkCellRendererText *celltext; EggCellRendererKeys *keys; GtkWidget *label; GtkWidget *eventbox; GValue celltext_editable = {0}; celltext = GTK_CELL_RENDERER_TEXT (cell); keys = EGG_CELL_RENDERER_KEYS (cell); /* If the cell isn't editable we return NULL. */ g_value_init (&celltext_editable, G_TYPE_BOOLEAN); g_object_get_property (G_OBJECT (celltext), "editable", &celltext_editable); if (g_value_get_boolean (&celltext_editable) == FALSE) return NULL; g_return_val_if_fail (gtk_widget_get_window (widget) != NULL, NULL); if (gdk_keyboard_grab (gtk_widget_get_window (widget), FALSE, gdk_event_get_time (event)) != GDK_GRAB_SUCCESS) return NULL; if (gdk_pointer_grab (gtk_widget_get_window (widget), FALSE, GDK_BUTTON_PRESS_MASK, NULL, NULL, gdk_event_get_time (event)) != GDK_GRAB_SUCCESS) { gdk_keyboard_ungrab (gdk_event_get_time (event)); return NULL; } keys->grab_widget = widget; g_signal_connect (G_OBJECT (widget), "key_press_event", G_CALLBACK (grab_key_callback), keys); eventbox = g_object_new (pointless_eventbox_subclass_get_type (), NULL); keys->edit_widget = eventbox; g_object_add_weak_pointer (G_OBJECT (keys->edit_widget), (void**) &keys->edit_widget); label = gtk_label_new (NULL); gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); gtk_widget_modify_bg (eventbox, GTK_STATE_NORMAL, >k_widget_get_style (widget)->bg[GTK_STATE_SELECTED]); gtk_widget_modify_fg (label, GTK_STATE_NORMAL, >k_widget_get_style (widget)->fg[GTK_STATE_SELECTED]); gtk_label_set_text (GTK_LABEL (label), TOOLTIP_TEXT); gtk_container_add (GTK_CONTAINER (eventbox), label); g_object_set_data_full (G_OBJECT (keys->edit_widget), EGG_CELL_RENDERER_TEXT_PATH, g_strdup (path), g_free); gtk_widget_show_all (keys->edit_widget); g_signal_connect (G_OBJECT (keys->edit_widget), "unrealize", G_CALLBACK (ungrab_stuff), keys); keys->edit_key = keys->accel_key; return GTK_CELL_EDITABLE (keys->edit_widget); }
static gboolean grab_key_callback(GtkWidget* widget, GdkEventKey* event, void* data) { GdkModifierType accel_mods = 0; guint accel_keyval; EggCellRendererKeys *keys; char *path; gboolean edited; gboolean cleared; GdkModifierType consumed_modifiers; guint upper; GdkModifierType ignored_modifiers; keys = EGG_CELL_RENDERER_KEYS(data); if (is_modifier(event->hardware_keycode)) { return TRUE; } edited = FALSE; cleared = FALSE; consumed_modifiers = 0; gdk_keymap_translate_keyboard_state(gdk_keymap_get_default(), event->hardware_keycode, event->state, event->group, NULL, NULL, NULL, &consumed_modifiers); upper = event->keyval; accel_keyval = gdk_keyval_to_lower(upper); if (accel_keyval == GDK_ISO_Left_Tab) { accel_keyval = GDK_Tab; } /* Put shift back if it changed the case of the key, not otherwise. */ if (upper != accel_keyval && (consumed_modifiers & GDK_SHIFT_MASK)) { consumed_modifiers &= ~(GDK_SHIFT_MASK); } egg_keymap_resolve_virtual_modifiers(gdk_keymap_get_default(), EGG_VIRTUAL_NUM_LOCK_MASK | EGG_VIRTUAL_SCROLL_LOCK_MASK | EGG_VIRTUAL_LOCK_MASK, &ignored_modifiers); /* http://bugzilla.gnome.org/show_bug.cgi?id=139605 * mouse keys should effect keybindings */ ignored_modifiers |= GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK | GDK_BUTTON5_MASK; /* filter consumed/ignored modifiers */ if (keys->accel_mode == EGG_CELL_RENDERER_KEYS_MODE_GTK) { accel_mods = event->state & GDK_MODIFIER_MASK & ~(consumed_modifiers | ignored_modifiers); } else if (keys->accel_mode == EGG_CELL_RENDERER_KEYS_MODE_X) { accel_mods = event->state & GDK_MODIFIER_MASK & ~(ignored_modifiers); } else { g_assert_not_reached(); } if (accel_mods == 0 && accel_keyval == GDK_Escape) { goto out; /* cancel */ } /* clear the accelerator on Backspace */ if (accel_mods == 0 && accel_keyval == GDK_BackSpace) { cleared = TRUE; goto out; } if (keys->accel_mode == EGG_CELL_RENDERER_KEYS_MODE_GTK) { if (!gtk_accelerator_valid (accel_keyval, accel_mods)) { accel_keyval = 0; accel_mods = 0; } } edited = TRUE; out: gdk_keyboard_ungrab(event->time); gdk_pointer_ungrab(event->time); path = g_strdup(g_object_get_data(G_OBJECT(keys->edit_widget), EGG_CELL_RENDERER_TEXT_PATH)); gtk_cell_editable_editing_done(GTK_CELL_EDITABLE(keys->edit_widget)); gtk_cell_editable_remove_widget(GTK_CELL_EDITABLE(keys->edit_widget)); keys->edit_widget = NULL; keys->grab_widget = NULL; if (edited) { g_signal_emit_by_name(G_OBJECT(keys), "accel_edited", path, accel_keyval, accel_mods, event->hardware_keycode); } else if (cleared) { g_signal_emit_by_name(G_OBJECT(keys), "accel_cleared", path); } g_free (path); return TRUE; }