forked from AuroraMiddleware/gtk
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:
parent
7ad08f19aa
commit
14e0cbe2d3
148
gtk/gtkmenu.c
148
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;
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user