[gtk+] Get rid of navigation region in GtkMenu
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+] Get rid of navigation region in GtkMenu
- Date: Mon, 28 Jun 2010 12:19:36 +0000 (UTC)
commit 14e0cbe2d35215fb299e84c193d3438dfbcc7a88
Author: Benjamin Otte <otte redhat com>
Date: Wed Jun 16 13:14:01 2010 +0200
Get rid of navigation region in GtkMenu
This completes the move to get rid of using a GdkRegion for the
navigation region and the only user of gdk_region_polygon(). We keep
track of the triangle and compute in/out points ourselves now.
Unfortunately the DRAW_STAYUP_TRIANGLES debugging code doesn't work
using cairo, so I removed it completely.
gtk/gtkmenu.c | 146 +++++++++++++++++++++++++++++++--------------------------
gtk/gtkmenu.h | 2 +-
2 files changed, 81 insertions(+), 67 deletions(-)
---
diff --git a/gtk/gtkmenu.c b/gtk/gtkmenu.c
index 3835e73..c9b2382 100644
--- a/gtk/gtkmenu.c
+++ b/gtk/gtkmenu.c
@@ -94,6 +94,12 @@ struct _GtkMenuPrivate
GtkStateType lower_arrow_state;
GtkStateType upper_arrow_state;
+ /* navigation region */
+ int navigation_x;
+ int navigation_y;
+ int navigation_width;
+ int navigation_height;
+
guint have_layout : 1;
guint seen_item_enter : 1;
guint have_position : 1;
@@ -3326,6 +3332,16 @@ definitely_within_item (GtkWidget *widget,
}
static gboolean
+gtk_menu_has_navigation_triangle (GtkMenu *menu)
+{
+ GtkMenuPrivate *priv;
+
+ priv = gtk_menu_get_private (menu);
+
+ return priv->navigation_height && priv->navigation_width;
+}
+
+static gboolean
gtk_menu_motion_notify (GtkWidget *widget,
GdkEventMotion *event)
{
@@ -3366,7 +3382,7 @@ gtk_menu_motion_notify (GtkWidget *widget,
if (definitely_within_item (menu_item, event->x, event->y))
menu_shell->activate_time = 0;
- need_enter = (menu->navigation_region != NULL || menu_shell->ignore_enter);
+ need_enter = (gtk_menu_has_navigation_triangle (menu) || menu_shell->ignore_enter);
/* Check to see if we are within an active submenu's navigation region
*/
@@ -4066,11 +4082,13 @@ gtk_menu_leave_notify (GtkWidget *widget,
static void
gtk_menu_stop_navigating_submenu (GtkMenu *menu)
{
- if (menu->navigation_region)
- {
- gdk_region_destroy (menu->navigation_region);
- menu->navigation_region = NULL;
- }
+ GtkMenuPrivate *priv = gtk_menu_get_private (menu);
+
+ priv->navigation_x = 0;
+ priv->navigation_y = 0;
+ priv->navigation_width = 0;
+ priv->navigation_height = 0;
+
if (menu->navigation_timeout)
{
g_source_remove (menu->navigation_timeout);
@@ -4119,49 +4137,48 @@ gtk_menu_navigating_submenu (GtkMenu *menu,
gint event_x,
gint event_y)
{
- if (menu->navigation_region)
- {
- if (gdk_region_point_in (menu->navigation_region, event_x, event_y))
- return TRUE;
- else
- {
- gtk_menu_stop_navigating_submenu (menu);
- return FALSE;
- }
- }
- return FALSE;
-}
+ GtkMenuPrivate *priv;
+ int width, height;
-#undef DRAW_STAY_UP_TRIANGLE
+ if (!gtk_menu_has_navigation_triangle (menu))
+ return FALSE;
-#ifdef DRAW_STAY_UP_TRIANGLE
+ priv = gtk_menu_get_private (menu);
+ width = priv->navigation_width;
+ height = priv->navigation_height;
-static void
-draw_stay_up_triangle (GdkWindow *window,
- GdkRegion *region)
-{
- /* Draw ugly color all over the stay-up triangle */
- GdkColor ugly_color = { 0, 50000, 10000, 10000 };
- GdkGCValues gc_values;
- GdkGC *ugly_gc;
- GdkRectangle clipbox;
-
- gc_values.subwindow_mode = GDK_INCLUDE_INFERIORS;
- ugly_gc = gdk_gc_new_with_values (window, &gc_values, 0 | GDK_GC_SUBWINDOW);
- gdk_gc_set_rgb_fg_color (ugly_gc, &ugly_color);
- gdk_gc_set_clip_region (ugly_gc, region);
-
- gdk_region_get_clipbox (region, &clipbox);
-
- gdk_draw_rectangle (window,
- ugly_gc,
- TRUE,
- clipbox.x, clipbox.y,
- clipbox.width, clipbox.height);
-
- g_object_unref (ugly_gc);
+ /* check if x/y are in the triangle spanned by the navigation parameters */
+
+ /* 1) Move the coordinates so the triangle starts at 0,0 */
+ event_x -= priv->navigation_x;
+ event_y -= priv->navigation_y;
+
+ /* 2) Ensure both legs move along the positive axis */
+ if (width < 0)
+ {
+ event_x = -event_x;
+ width = -width;
+ }
+ if (height < 0)
+ {
+ event_y = -event_y;
+ height = -height;
+ }
+
+ /* 3) Check that the given coordinate is inside the triangle. The formula
+ * is a transformed form of this formula: x/w + y/h <= 1
+ */
+ if (event_x >= 0 && event_y >= 0 &&
+ event_x * height + event_y * width <= width * height)
+ {
+ return TRUE;
+ }
+ else
+ {
+ gtk_menu_stop_navigating_submenu (menu);
+ return FALSE;
+ }
}
-#endif
static void
gtk_menu_set_submenu_navigation_region (GtkMenu *menu,
@@ -4174,13 +4191,15 @@ gtk_menu_set_submenu_navigation_region (GtkMenu *menu,
gint submenu_bottom = 0;
gint width = 0;
gint height = 0;
- GdkPoint point[3];
GtkWidget *event_widget;
GtkMenuPopdownData *popdown_data;
+ GtkMenuPrivate *priv;
g_return_if_fail (menu_item->submenu != NULL);
g_return_if_fail (event != NULL);
+ priv = gtk_menu_get_private (menu);
+
event_widget = gtk_get_event_widget ((GdkEvent*) event);
gdk_window_get_origin (menu_item->submenu->window, &submenu_left, &submenu_top);
@@ -4197,43 +4216,43 @@ gtk_menu_set_submenu_navigation_region (GtkMenu *menu,
gtk_menu_stop_navigating_submenu (menu);
+ /* The navigation region is the triangle closest to the x/y
+ * location of the rectangle. This is why the width or height
+ * can be negative.
+ */
+
if (menu_item->submenu_direction == GTK_DIRECTION_RIGHT)
{
/* right */
- point[0].x = event->x_root;
- point[1].x = submenu_left;
+ priv->navigation_x = submenu_left;
+ priv->navigation_width = event->x_root - submenu_left;
}
else
{
/* left */
- point[0].x = event->x_root + 1;
- point[1].x = submenu_right;
+ priv->navigation_x = submenu_right;
+ priv->navigation_width = event->x_root - submenu_right;
}
if (event->y < 0)
{
/* top */
- point[0].y = event->y_root;
- point[1].y = submenu_top - NAVIGATION_REGION_OVERSHOOT;
+ priv->navigation_y = event->y_root;
+ priv->navigation_height = submenu_top - event->y_root - NAVIGATION_REGION_OVERSHOOT;
- if (point[0].y <= submenu_top)
+ if (priv->navigation_height >= 0)
return;
}
else
{
/* bottom */
- point[0].y = event->y_root + 1;
- point[1].y = submenu_bottom + NAVIGATION_REGION_OVERSHOOT;
+ priv->navigation_y = event->y_root;
+ priv->navigation_height = submenu_bottom - event->y_root + NAVIGATION_REGION_OVERSHOOT;
- if (point[0].y >= submenu_bottom)
+ if (priv->navigation_height <= 0)
return;
}
- point[2].x = point[1].x;
- point[2].y = point[0].y;
-
- menu->navigation_region = gdk_region_polygon (point, 3, GDK_WINDING_RULE);
-
g_object_get (gtk_widget_get_settings (GTK_WIDGET (menu)),
"gtk-menu-popdown-delay", &popdown_delay,
NULL);
@@ -4247,11 +4266,6 @@ gtk_menu_set_submenu_navigation_region (GtkMenu *menu,
gtk_menu_stop_navigating_submenu_cb,
popdown_data,
(GDestroyNotify) g_free);
-
-#ifdef DRAW_STAY_UP_TRIANGLE
- draw_stay_up_triangle (gdk_get_default_root_window(),
- menu->navigation_region);
-#endif
}
}
diff --git a/gtk/gtkmenu.h b/gtk/gtkmenu.h
index 0929472..4e4746f 100644
--- a/gtk/gtkmenu.h
+++ b/gtk/gtkmenu.h
@@ -92,7 +92,7 @@ struct _GtkMenu
/* When a submenu of this menu is popped up, motion in this
* region is ignored
*/
- GdkRegion *GSEAL (navigation_region);
+ GdkRegion *GSEAL (navigation_region); /* unused */
guint GSEAL (navigation_timeout);
guint GSEAL (needs_destruction_ref_count) : 1;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]