diff --git a/ChangeLog b/ChangeLog index 1e6d558b97..8f4e4d94dd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2005-08-15 Matthias Clasen + + * tests/testtoolbar.c: Add some more tests for menu placement. + + * gtk/gtkmenutoolbutton.c (menu_position_func): + * gtk/gtktoolbar.c (menu_position_func): Improve positioning + of toolbutton menus and of the overflow menu. (#312937, + #153870, Christian Persch, Paolo Borelli) + 2005-08-15 Tor Lillqvist * gtk/updateiconcache.c: Use g_path_get_dirname() instead of diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 1e6d558b97..8f4e4d94dd 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,12 @@ +2005-08-15 Matthias Clasen + + * tests/testtoolbar.c: Add some more tests for menu placement. + + * gtk/gtkmenutoolbutton.c (menu_position_func): + * gtk/gtktoolbar.c (menu_position_func): Improve positioning + of toolbutton menus and of the overflow menu. (#312937, + #153870, Christian Persch, Paolo Borelli) + 2005-08-15 Tor Lillqvist * gtk/updateiconcache.c: Use g_path_get_dirname() instead of diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 1e6d558b97..8f4e4d94dd 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,12 @@ +2005-08-15 Matthias Clasen + + * tests/testtoolbar.c: Add some more tests for menu placement. + + * gtk/gtkmenutoolbutton.c (menu_position_func): + * gtk/gtktoolbar.c (menu_position_func): Improve positioning + of toolbutton menus and of the overflow menu. (#312937, + #153870, Christian Persch, Paolo Borelli) + 2005-08-15 Tor Lillqvist * gtk/updateiconcache.c: Use g_path_get_dirname() instead of diff --git a/gtk/gtkmenutoolbutton.c b/gtk/gtkmenutoolbutton.c index 976ce3f39f..0496260b36 100644 --- a/gtk/gtkmenutoolbutton.c +++ b/gtk/gtkmenutoolbutton.c @@ -278,36 +278,61 @@ menu_position_func (GtkMenu *menu, GtkMenuToolButton *button) { GtkMenuToolButtonPrivate *priv = button->priv; + GtkWidget *widget = GTK_WIDGET (button); GtkRequisition req; GtkRequisition menu_req; GtkOrientation orientation; GtkTextDirection direction; + GdkRectangle monitor; + gint monitor_num; + GdkScreen *screen; - gdk_window_get_origin (GTK_BUTTON (priv->arrow_button)->event_window, x, y); - gtk_widget_size_request (priv->arrow_button, &req); gtk_widget_size_request (GTK_WIDGET (priv->menu), &menu_req); orientation = gtk_tool_item_get_orientation (GTK_TOOL_ITEM (button)); - direction = gtk_widget_get_direction (GTK_WIDGET (priv->arrow_button)); + direction = gtk_widget_get_direction (widget); + + screen = gtk_widget_get_screen (GTK_WIDGET (menu)); + monitor_num = gdk_screen_get_monitor_at_window (screen, widget->window); + if (monitor_num < 0) + monitor_num = 0; + gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor); if (orientation == GTK_ORIENTATION_HORIZONTAL) { + gdk_window_get_origin (widget->window, x, y); + *x += widget->allocation.x; + if (direction == GTK_TEXT_DIR_LTR) - *x += priv->arrow_button->allocation.width - req.width; + *x += MAX (widget->allocation.width - menu_req.width, 0); + else if (menu_req.width > widget->allocation.width) + *x -= menu_req.width - widget->allocation.width; + + if ((*y + priv->arrow_button->allocation.height + menu_req.height) <= monitor.y + monitor.height) + *y += priv->arrow_button->allocation.height; + else if ((*y - menu_req.height) >= monitor.y) + *y -= menu_req.height; + else if (monitor.y + monitor.height - (*y + priv->arrow_button->allocation.height) > *y) + *y += priv->arrow_button->allocation.height; else - *x += req.width - menu_req.width; - *y += priv->arrow_button->allocation.height; + *y -= menu_req.height; } else { + gdk_window_get_origin (GTK_BUTTON (priv->arrow_button)->event_window, x, y); + gtk_widget_size_request (priv->arrow_button, &req); + if (direction == GTK_TEXT_DIR_LTR) *x += priv->arrow_button->allocation.width; else *x -= menu_req.width; - *y += priv->arrow_button->allocation.height - req.height; + + if (*y + menu_req.height > monitor.y + monitor.height && + *y + priv->arrow_button->allocation.height - monitor.y > monitor.y + monitor.height - *y) + *y += priv->arrow_button->allocation.height - menu_req.height; } - *push_in = TRUE; + *push_in = FALSE; } static void diff --git a/gtk/gtktoolbar.c b/gtk/gtktoolbar.c index a567357d64..db6551cbf0 100644 --- a/gtk/gtktoolbar.c +++ b/gtk/gtktoolbar.c @@ -2538,18 +2538,35 @@ menu_position_func (GtkMenu *menu, GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar); GtkRequisition req; GtkRequisition menu_req; + GdkRectangle monitor; + gint monitor_num; + GdkScreen *screen; - gdk_window_get_origin (GTK_BUTTON (priv->arrow_button)->event_window, x, y); gtk_widget_size_request (priv->arrow_button, &req); gtk_widget_size_request (GTK_WIDGET (menu), &menu_req); + screen = gtk_widget_get_screen (GTK_WIDGET (menu)); + monitor_num = gdk_screen_get_monitor_at_window (screen, priv->arrow_button->window); + if (monitor_num < 0) + monitor_num = 0; + gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor); + + gdk_window_get_origin (GTK_BUTTON (priv->arrow_button)->event_window, x, y); if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL) { - *y += priv->arrow_button->allocation.height; if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_LTR) *x += priv->arrow_button->allocation.width - req.width; else *x += req.width - menu_req.width; + + if ((*y + priv->arrow_button->allocation.height + menu_req.height) <= monitor.y + monitor.height) + *y += priv->arrow_button->allocation.height; + else if ((*y - menu_req.height) >= monitor.y) + *y -= menu_req.height; + else if (monitor.y + monitor.height - (*y + priv->arrow_button->allocation.height) > *y) + *y += priv->arrow_button->allocation.height; + else + *y -= menu_req.height; } else { @@ -2557,10 +2574,13 @@ menu_position_func (GtkMenu *menu, *x += priv->arrow_button->allocation.width; else *x -= menu_req.width; - *y += priv->arrow_button->allocation.height - req.height; + + if (*y + menu_req.height > monitor.y + monitor.height && + *y + priv->arrow_button->allocation.height - monitor.y > monitor.y + monitor.height - *y) + *y += priv->arrow_button->allocation.height - menu_req.height; } - - *push_in = TRUE; + + *push_in = FALSE; } static void diff --git a/tests/testtoolbar.c b/tests/testtoolbar.c index 9af5d92792..0818c5dcea 100644 --- a/tests/testtoolbar.c +++ b/tests/testtoolbar.c @@ -488,6 +488,15 @@ timeout_cb (GtkWidget *widget) return TRUE; } +static gboolean +timeout_cb1 (GtkWidget *widget) +{ + static gboolean sensitive = TRUE; + sensitive = !sensitive; + gtk_widget_set_sensitive (widget, sensitive); + return TRUE; +} + gint main (gint argc, gchar **argv) { @@ -603,17 +612,37 @@ main (gint argc, gchar **argv) gtk_tool_item_set_expand (item, TRUE); menu = gtk_menu_new (); - menuitem = gtk_menu_item_new_with_label ("foo.txt"); - gtk_widget_show (menuitem); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - menuitem = gtk_menu_item_new_with_label ("bar.txt"); - gtk_widget_show (menuitem); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); + for (i = 0; i < 20; i++) + { + char *text; + text = g_strdup_printf ("Menuitem %d", i); + menuitem = gtk_menu_item_new_with_label (text); + g_free (text); + gtk_widget_show (menuitem); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); + } item = gtk_menu_tool_button_new_from_stock (GTK_STOCK_OPEN); gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (item), menu); add_item_to_list (store, item, "Open"); gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1); + g_timeout_add (3000, (GSourceFunc) timeout_cb1, item); + + menu = gtk_menu_new (); + for (i = 0; i < 20; i++) + { + char *text; + text = g_strdup_printf ("A%d", i); + menuitem = gtk_menu_item_new_with_label (text); + g_free (text); + gtk_widget_show (menuitem); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); + } + + item = gtk_menu_tool_button_new_from_stock (GTK_STOCK_GO_BACK); + gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (item), menu); + add_item_to_list (store, item, "BackWithHistory"); + gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1); item = gtk_separator_tool_item_new (); add_item_to_list (store, item, "-----");