4 #include <gdk/gdkkeysyms.h>
5 #include "cellrendererkey.h"
10 #define CELL_RENDERER_TEXT_PATH "cell-renderer-key-text"
12 #define TOOLTIP_TEXT _("New accelerator...")
14 static void cell_renderer_key_finalize (GObject *object);
15 static void cell_renderer_key_init (CellRendererKey *cell_key);
16 static void cell_renderer_key_class_init (CellRendererKeyClass *cell_key_class);
17 static GtkCellEditable *cell_renderer_key_start_editing (GtkCellRenderer *cell,
21 GdkRectangle *background_area,
22 GdkRectangle *cell_area,
23 GtkCellRendererState flags);
25 static void cell_renderer_key_get_property (GObject *object,
29 static void cell_renderer_key_set_property (GObject *object,
33 static void cell_renderer_key_get_size (GtkCellRenderer *cell,
35 GdkRectangle *cell_area,
48 static GtkCellRendererTextClass *parent_class = NULL;
50 GType cell_renderer_key_get_type (void)
52 static GType cell_key_type = 0;
56 static const GTypeInfo cell_key_info =
58 sizeof (CellRendererKeyClass),
60 NULL, /* base_finalize */
61 (GClassInitFunc)cell_renderer_key_class_init,
62 NULL, /* class_finalize */
63 NULL, /* class_data */
64 sizeof (CellRendererKey),
66 (GInstanceInitFunc) cell_renderer_key_init
69 cell_key_type = g_type_register_static (GTK_TYPE_CELL_RENDERER_TEXT, "CellRendererKey", &cell_key_info, 0);
76 cell_renderer_key_init (CellRendererKey *key)
83 marshal_VOID__STRING_UINT (GClosure *closure,
86 const GValue *param_values,
87 gpointer invocation_hint,
88 gpointer marshal_data)
90 typedef void (*GMarshalFunc_VOID__STRING_UINT) (gpointer data1,
94 register GMarshalFunc_VOID__STRING_UINT callback;
95 register GCClosure *cc = (GCClosure*) closure;
96 register gpointer data1, data2;
98 g_return_if_fail (n_param_values == 3);
100 if (G_CCLOSURE_SWAP_DATA (closure))
102 data1 = closure->data;
103 data2 = g_value_peek_pointer (param_values + 0);
107 data1 = g_value_peek_pointer (param_values + 0);
108 data2 = closure->data;
111 callback = (GMarshalFunc_VOID__STRING_UINT) (marshal_data ? marshal_data : cc->callback);
114 g_value_get_string (param_values + 1),
115 g_value_get_uint (param_values + 2),
120 cell_renderer_key_class_init (CellRendererKeyClass *cell_key_class)
122 GObjectClass *object_class;
123 GtkCellRendererClass *cell_renderer_class;
125 object_class = G_OBJECT_CLASS (cell_key_class);
126 cell_renderer_class = GTK_CELL_RENDERER_CLASS (cell_key_class);
127 parent_class = g_type_class_peek_parent (object_class);
129 GTK_CELL_RENDERER_CLASS(cell_key_class)->start_editing = cell_renderer_key_start_editing;
131 object_class->set_property = cell_renderer_key_set_property;
132 object_class->get_property = cell_renderer_key_get_property;
133 cell_renderer_class->get_size = cell_renderer_key_get_size;
135 object_class->finalize = cell_renderer_key_finalize;
137 g_object_class_install_property (object_class,
139 g_param_spec_int ("scancode",
145 G_PARAM_READABLE | G_PARAM_WRITABLE));
147 g_signal_new ("accel_edited",
148 TYPE_CELL_RENDERER_KEY,
150 G_STRUCT_OFFSET(CellRendererKeyClass, accel_edited),
152 marshal_VOID__STRING_UINT,
154 2,G_TYPE_STRING,G_TYPE_UINT);
156 g_signal_new ("accel_cleared",
157 TYPE_CELL_RENDERER_KEY,
159 G_STRUCT_OFFSET(CellRendererKeyClass, accel_cleared),
161 gtk_marshal_VOID__STRING,
168 cell_renderer_key_new (void)
170 return GTK_CELL_RENDERER (g_object_new (TYPE_CELL_RENDERER_KEY, NULL));
174 cell_renderer_key_finalize (GObject *object)
177 (* G_OBJECT_CLASS (parent_class)->finalize) (object);
181 cell_renderer_key_get_property (GObject *object,
186 CellRendererKey *key;
188 g_return_if_fail (IS_CELL_RENDERER_KEY(object));
190 key = CELL_RENDERER_KEY(object);
195 g_value_set_int(value, key->scancode);
199 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
204 cell_renderer_key_set_property (GObject *object,
209 CellRendererKey *key;
211 g_return_if_fail (IS_CELL_RENDERER_KEY(object));
213 key = CELL_RENDERER_KEY(object);
218 cell_renderer_key_set_scancode(key, g_value_get_int(value));
222 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
227 cell_renderer_key_get_size (GtkCellRenderer *cell,
229 GdkRectangle *cell_area,
236 CellRendererKey *key = (CellRendererKey *) cell;
237 GtkRequisition requisition;
239 if (key->sizing_label == NULL)
240 key->sizing_label = gtk_label_new (TOOLTIP_TEXT);
242 gtk_widget_size_request (key->sizing_label, &requisition);
243 (* GTK_CELL_RENDERER_CLASS (parent_class)->get_size) (cell, widget, cell_area, x_offset, y_offset, width, height);
244 /* FIXME: need to take the cell_area et al. into account */
246 *width = MAX (*width, requisition.width);
248 *height = MAX (*height, requisition.height);
253 grab_key_callback (GtkWidget *widget,
261 CellRendererKey* key = CELL_RENDERER_KEY(data);
266 guint scancode = event->hardware_keycode;
269 gdk_keyboard_ungrab (event->time);
270 gdk_pointer_ungrab (event->time);
272 path = g_strdup (g_object_get_data (G_OBJECT (key->edit_widget), CELL_RENDERER_TEXT_PATH));
274 gtk_cell_editable_editing_done(GTK_CELL_EDITABLE (key->edit_widget));
275 gtk_cell_editable_remove_widget(GTK_CELL_EDITABLE (key->edit_widget));
276 key->edit_widget = NULL;
277 key->grab_widget = NULL;
281 cell_renderer_key_set_scancode(key, scancode);
282 g_signal_emit_by_name (G_OBJECT(key), "accel_edited", path, scancode);
286 cell_renderer_key_set_scancode(key, 0);
287 g_signal_emit_by_name (G_OBJECT(key), "accel_cleared", path);
295 ungrab_stuff (GtkWidget *widget, gpointer data)
297 CellRendererKey *key = CELL_RENDERER_KEY(data);
299 gdk_keyboard_ungrab (GDK_CURRENT_TIME);
300 gdk_pointer_ungrab (GDK_CURRENT_TIME);
302 g_signal_handlers_disconnect_by_func (G_OBJECT (key->grab_widget),
303 G_CALLBACK (grab_key_callback), data);
307 pointless_eventbox_start_editing (GtkCellEditable *cell_editable,
310 /* do nothing, because we are pointless */
314 pointless_eventbox_cell_editable_init (GtkCellEditableIface *iface)
316 iface->start_editing = pointless_eventbox_start_editing;
320 pointless_eventbox_subclass_get_type (void)
322 static GType eventbox_type = 0;
326 static const GTypeInfo eventbox_info =
328 sizeof (GtkEventBoxClass),
329 NULL, /* base_init */
330 NULL, /* base_finalize */
332 NULL, /* class_finalize */
333 NULL, /* class_data */
334 sizeof (GtkEventBox),
336 (GInstanceInitFunc) NULL,
339 static const GInterfaceInfo cell_editable_info = {
340 (GInterfaceInitFunc) pointless_eventbox_cell_editable_init,
343 eventbox_type = g_type_register_static (GTK_TYPE_EVENT_BOX, "EggCellEditableEventBox", &eventbox_info, 0);
345 g_type_add_interface_static (eventbox_type,
346 GTK_TYPE_CELL_EDITABLE,
347 &cell_editable_info);
350 return eventbox_type;
353 static GtkCellEditable *
354 cell_renderer_key_start_editing (GtkCellRenderer *cell,
358 GdkRectangle *background_area,
359 GdkRectangle *cell_area,
360 GtkCellRendererState flags)
362 GtkCellRendererText *celltext;
363 CellRendererKey *key;
367 celltext = GTK_CELL_RENDERER_TEXT (cell);
368 key = CELL_RENDERER_KEY (cell);
370 /* If the cell isn't editable we return NULL. */
371 if (celltext->editable == FALSE)
374 g_return_val_if_fail (widget->window != NULL, NULL);
376 if (gdk_keyboard_grab (widget->window, FALSE,
377 gdk_event_get_time (event)) != GDK_GRAB_SUCCESS)
380 if (gdk_pointer_grab (widget->window, FALSE,
381 GDK_BUTTON_PRESS_MASK,
383 gdk_event_get_time (event)) != GDK_GRAB_SUCCESS)
385 gdk_keyboard_ungrab (gdk_event_get_time (event));
389 key->grab_widget = widget;
391 g_signal_connect (G_OBJECT (widget), "key_press_event",
392 G_CALLBACK (grab_key_callback), key);
394 eventbox = g_object_new (pointless_eventbox_subclass_get_type (),
396 key->edit_widget = eventbox;
397 g_object_add_weak_pointer (G_OBJECT (key->edit_widget),
398 (void**) &key->edit_widget);
400 label = gtk_label_new (NULL);
401 //gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
403 gtk_widget_modify_bg (eventbox, GTK_STATE_NORMAL,
404 &widget->style->bg[GTK_STATE_SELECTED]);
406 gtk_widget_modify_fg (label, GTK_STATE_NORMAL,
407 &widget->style->fg[GTK_STATE_SELECTED]);
409 gtk_label_set_text (GTK_LABEL (label),
412 gtk_container_add (GTK_CONTAINER (eventbox), label);
414 g_object_set_data_full (G_OBJECT (key->edit_widget), CELL_RENDERER_TEXT_PATH,
415 g_strdup (path), g_free);
417 gtk_widget_show_all (key->edit_widget);
419 g_signal_connect (G_OBJECT (key->edit_widget), "unrealize",
420 G_CALLBACK (ungrab_stuff), key);
422 return GTK_CELL_EDITABLE (key->edit_widget);
425 void cell_renderer_key_set_scancode (CellRendererKey *key, gint scancode)
429 g_return_if_fail (IS_CELL_RENDERER_KEY(key));
431 g_object_freeze_notify(G_OBJECT(key));
435 if (scancode != key->scancode) {
436 key->scancode = scancode;
437 g_object_notify(G_OBJECT(key), "scancode");
441 g_object_thaw_notify(G_OBJECT(key));
445 /* sync string to the key values */
451 gdk_keymap_translate_keyboard_state(gdk_keymap_get_default(),
452 scancode, 0, 0, &keyval, NULL, NULL, NULL);
453 text = gdk_keyval_name(keyval);
455 g_object_set(key, "text", text, NULL);
459 gint cell_renderer_keys_get_scancode(CellRendererKey *key)
461 g_return_if_fail (IS_CELL_RENDERER_KEY(key));
462 return key->scancode;