My cut at fixing the GnomeCanvas focus and grab issues
- From: Darin Adler <darin bentspoon com>
- To: <gnome-libs-devel gnome org>
- Subject: My cut at fixing the GnomeCanvas focus and grab issues
- Date: Thu, 06 Dec 2001 16:30:59 -0800
Here's my cut at fixing a few problems in GnomeCanvas. I decoupled
current_item from grabbed_item, fixed handling of GDK_FOCUS_CHANGE events so
we don't get multiple events and miss some we should get, and removed some
dead code.
The GnomeCanvasRichText fix is separate. I ran into that problem while
testing the changes with canvas_demo.
By the way, it's confusing that left_grabbed_item has nothing to do with
grabbed_item. It's a totally separate concept of grabbed that means "item
you moused down on" that works even if you don't call gnome_canvas_item_grab
at all.
Index: libgnomecanvas/gnome-canvas-rich-text.c
===================================================================
RCS file:
/cvs/gnome/libgnomecanvas/libgnomecanvas/gnome-canvas-rich-text.c,v
retrieving revision 1.12
diff -p -u -r1.12 gnome-canvas-rich-text.c
--- libgnomecanvas/gnome-canvas-rich-text.c 2001/11/06 07:18:55 1.12
+++ libgnomecanvas/gnome-canvas-rich-text.c 2001/12/07 00:25:09
@@ -1850,8 +1850,9 @@ gnome_canvas_rich_text_update(GnomeCanva
get_bounds(text, &x1, &y1, &x2, &y2);
gtk_text_buffer_get_iter_at_offset(text->_priv->buffer, &start, 0);
- gtk_text_layout_validate_yrange(
- text->_priv->layout, &start, 0, y2 - y1);
+ if (text->_priv->layout)
+ gtk_text_layout_validate_yrange(
+ text->_priv->layout, &start, 0, y2 - y1);
gnome_canvas_update_bbox(item, x1, y1, x2, y2);
} /* gnome_canvas_rich_text_update */
Index: libgnomecanvas/gnome-canvas.c
===================================================================
RCS file: /cvs/gnome/libgnomecanvas/libgnomecanvas/gnome-canvas.c,v
retrieving revision 1.140
diff -p -u -r1.140 gnome-canvas.c
--- libgnomecanvas/gnome-canvas.c 2001/12/06 22:51:35 1.140
+++ libgnomecanvas/gnome-canvas.c 2001/12/07 00:25:09
@@ -1007,7 +1007,6 @@ gnome_canvas_item_grab (GnomeCanvasItem
item->canvas->grabbed_item = item;
item->canvas->grabbed_event_mask = event_mask;
- item->canvas->current_item = item; /* So that events go to the grabbed
item */
return retval;
}
@@ -1202,34 +1201,45 @@ gnome_canvas_item_reparent (GnomeCanvasI
void
gnome_canvas_item_grab_focus (GnomeCanvasItem *item)
{
- GnomeCanvasItem *focused_item;
GdkEvent ev;
g_return_if_fail (GNOME_IS_CANVAS_ITEM (item));
g_return_if_fail (GTK_WIDGET_CAN_FOCUS (GTK_WIDGET (item->canvas)));
- focused_item = item->canvas->focused_item;
+ /* If we have to grab focus, the GDK_FOCUS_CHANGE event that
+ * comes in from GTK will suffice so we don't need to send any
+ * events of our own. Also, it doesn't matter what the old
+ * value of focused_item is, since the canvas itself wasn't
+ * focused.
+ */
+ if (! GTK_WIDGET_HAS_FOCUS (GTK_WIDGET (item->canvas))) {
+ item->canvas->focused_item = item;
+ gtk_widget_grab_focus (GTK_WIDGET (item->canvas));
+ return;
+ }
+
+ /* If the canvas is focused and the correct item is focused,
+ * we have no work to do.
+ */
+ if (item->canvas->focused_item == item)
+ return;
- if (focused_item) {
- ev.focus_change.type = GDK_FOCUS_CHANGE;
- ev.focus_change.window = GTK_LAYOUT (item->canvas)->bin_window;
- ev.focus_change.send_event = FALSE;
+ /* Send focus change events explicitly, since we aren't
+ * changing the focus at the GTK level.
+ */
+ ev.focus_change.type = GDK_FOCUS_CHANGE;
+ ev.focus_change.window = GTK_LAYOUT (item->canvas)->bin_window;
+ ev.focus_change.send_event = FALSE;
+
+ if (item->canvas->focused_item) {
ev.focus_change.in = FALSE;
-
emit_event (item->canvas, &ev);
}
-
+
item->canvas->focused_item = item;
- gtk_widget_grab_focus (GTK_WIDGET (item->canvas));
-
- if (focused_item) {
- ev.focus_change.type = GDK_FOCUS_CHANGE;
- ev.focus_change.window = GTK_LAYOUT (item->canvas)->bin_window;
- ev.focus_change.send_event = FALSE;
- ev.focus_change.in = TRUE;
-
- emit_event (item->canvas, &ev);
- }
+
+ ev.focus_change.in = TRUE;
+ emit_event (item->canvas, &ev);
}
@@ -2496,62 +2506,7 @@ emit_event (GnomeCanvas *canvas, GdkEven
GnomeCanvasItem *item;
GnomeCanvasItem *parent;
guint mask;
- guint signal_num;
-
- /* Perform checks for grabbed items */
-
- if (canvas->grabbed_item &&
- !is_descendant (canvas->current_item, canvas->grabbed_item)) {
- g_warning ("emit_event() returning FALSE!\n");
- return FALSE;
- }
-
- signal_num = -1;
-
- if (canvas->grabbed_item) {
- switch (event->type) {
- case GDK_ENTER_NOTIFY:
- mask = GDK_ENTER_NOTIFY_MASK;
- break;
-
- case GDK_LEAVE_NOTIFY:
- mask = GDK_LEAVE_NOTIFY_MASK;
- break;
-
- case GDK_MOTION_NOTIFY:
- mask = GDK_POINTER_MOTION_MASK;
- break;
-
- case GDK_BUTTON_PRESS:
- case GDK_2BUTTON_PRESS:
- case GDK_3BUTTON_PRESS:
- mask = GDK_BUTTON_PRESS_MASK;
- break;
-
- case GDK_BUTTON_RELEASE:
- mask = GDK_BUTTON_RELEASE_MASK;
- break;
-
- case GDK_KEY_PRESS:
- signal_num = ITEM_KEY_PRESS_EVENT;
- mask = GDK_KEY_PRESS_MASK;
- break;
-
- case GDK_KEY_RELEASE:
- signal_num = ITEM_KEY_RELEASE_EVENT;
- mask = GDK_KEY_RELEASE_MASK;
- break;
- default:
- signal_num = -1;
- mask = 0;
- break;
- }
-
- if (!(mask & canvas->grabbed_event_mask))
- return FALSE;
- }
-
/* Convert to world coordinates -- we have two cases because of
diferent
* offsets of the fields in the event structures.
*/
@@ -2600,6 +2555,43 @@ emit_event (GnomeCanvas *canvas, GdkEven
(event->type == GDK_KEY_RELEASE) ||
(event->type == GDK_FOCUS_CHANGE)))
item = canvas->focused_item;
+
+ if (canvas->grabbed_item) {
+ switch (event->type) {
+ case GDK_ENTER_NOTIFY:
+ mask = GDK_ENTER_NOTIFY_MASK;
+ break;
+
+ case GDK_LEAVE_NOTIFY:
+ mask = GDK_LEAVE_NOTIFY_MASK;
+ break;
+
+ case GDK_MOTION_NOTIFY:
+ mask = GDK_POINTER_MOTION_MASK;
+ break;
+
+ case GDK_BUTTON_PRESS:
+ case GDK_2BUTTON_PRESS:
+ case GDK_3BUTTON_PRESS:
+ mask = GDK_BUTTON_PRESS_MASK;
+ break;
+
+ case GDK_BUTTON_RELEASE:
+ mask = GDK_BUTTON_RELEASE_MASK;
+ break;
+
+ default:
+ mask = 0;
+ break;
+ }
+
+ if (mask) {
+ if (mask & canvas->grabbed_event_mask)
+ item = canvas->grabbed_item;
+ else
+ item = NULL;
+ }
+ }
/* The event is propagated up the hierarchy (for if someone connected
to
* a group instead of a leaf event), and emission is stopped if a
===================================================================
-- Darin
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]