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.
This commit is contained in:
Benjamin Otte 2010-06-16 13:14:01 +02:00
parent 7ad08f19aa
commit 14e0cbe2d3
2 changed files with 82 additions and 68 deletions

View File

@ -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;
@ -3325,6 +3331,16 @@ definitely_within_item (GtkWidget *widget,
check_threshold (widget, 0, h - 1, x, y);
}
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,50 +4137,49 @@ gtk_menu_navigating_submenu (GtkMenu *menu,
gint event_x,
gint event_y)
{
if (menu->navigation_region)
GtkMenuPrivate *priv;
int width, height;
if (!gtk_menu_has_navigation_triangle (menu))
return FALSE;
priv = gtk_menu_get_private (menu);
width = priv->navigation_width;
height = priv->navigation_height;
/* 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)
{
if (gdk_region_point_in (menu->navigation_region, event_x, event_y))
return TRUE;
else
{
gtk_menu_stop_navigating_submenu (menu);
return FALSE;
}
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;
}
return FALSE;
}
#undef DRAW_STAY_UP_TRIANGLE
#ifdef DRAW_STAY_UP_TRIANGLE
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);
}
#endif
static void
gtk_menu_set_submenu_navigation_region (GtkMenu *menu,
GtkMenuItem *menu_item,
@ -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
}
}

View File

@ -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;