Implement proper menu positioning.

Menu position is computed according to the widget position
and size as well as a hint indicating alignment to the
mouse pointer, left or right.
This commit is contained in:
Przemek Sitek 2008-03-29 22:38:59 +01:00 committed by Christian Dywan
parent 173b05dd78
commit b01eb78c9d
5 changed files with 92 additions and 20 deletions

View file

@ -865,7 +865,8 @@ midori_browser_menu_trash_activate_cb (GtkWidget* widget,
menuitem = gtk_action_create_menu_item (action); menuitem = gtk_action_create_menu_item (action);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
gtk_widget_show (menuitem); gtk_widget_show (menuitem);
sokoke_widget_popup (widget, GTK_MENU (menu), NULL); sokoke_widget_popup (widget, GTK_MENU (menu), NULL,
SOKOKE_MENU_POSITION_RIGHT);
} }
static void static void
@ -1310,7 +1311,8 @@ _midori_panel_bookmarks_popup (GtkWidget* widget,
_action_set_sensitive (browser, "BookmarkOpenTab", is_bookmark); _action_set_sensitive (browser, "BookmarkOpenTab", is_bookmark);
_action_set_sensitive (browser, "BookmarkOpenWindow", is_bookmark); _action_set_sensitive (browser, "BookmarkOpenWindow", is_bookmark);
sokoke_widget_popup (widget, GTK_MENU (priv->popup_bookmark), event); sokoke_widget_popup (widget, GTK_MENU (priv->popup_bookmark),
event, SOKOKE_MENU_POSITION_CURSOR);
} }
static gboolean static gboolean
@ -1471,7 +1473,8 @@ midori_browser_bookmarkbar_folder_activate_cb (GtkToolItem* toolitem,
// FIXME: We really *should* run the line below, but it won't work like that // FIXME: We really *should* run the line below, but it won't work like that
/*g_signal_connect (menu, "hide", G_CALLBACK (gtk_container_foreach), /*g_signal_connect (menu, "hide", G_CALLBACK (gtk_container_foreach),
gtk_widget_destroy);*/ gtk_widget_destroy);*/
sokoke_widget_popup (GTK_WIDGET (toolitem), GTK_MENU (menu), NULL); sokoke_widget_popup (GTK_WIDGET (toolitem), GTK_MENU (menu),
NULL, SOKOKE_MENU_POSITION_LEFT);
} }
static void static void

View file

@ -923,7 +923,7 @@ midori_web_view_get_proxy_tab_label (MidoriWebView* web_view)
priv->tab_label = gtk_label_new (title); priv->tab_label = gtk_label_new (title);
gtk_misc_set_alignment (GTK_MISC (priv->tab_label), 0.0, 0.5); gtk_misc_set_alignment (GTK_MISC (priv->tab_label), 0.0, 0.5);
// TODO: make the tab initially look "unvisited" until it's focused // TODO: make the tab initially look "unvisited" until it's focused
gtk_box_pack_start (GTK_BOX (hbox), priv->tab_label, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (hbox), priv->tab_label, FALSE, TRUE, 0);
priv->proxy_tab_label = event_box; priv->proxy_tab_label = event_box;
_midori_web_view_update_tab_label_size (web_view); _midori_web_view_update_tab_label_size (web_view);
@ -936,7 +936,7 @@ midori_web_view_get_proxy_tab_label (MidoriWebView* web_view)
GtkWidget* image = gtk_image_new_from_stock (GTK_STOCK_CLOSE, GtkWidget* image = gtk_image_new_from_stock (GTK_STOCK_CLOSE,
GTK_ICON_SIZE_MENU); GTK_ICON_SIZE_MENU);
gtk_button_set_image (GTK_BUTTON(close_button), image); gtk_button_set_image (GTK_BUTTON(close_button), image);
gtk_box_pack_start (GTK_BOX (hbox), close_button, FALSE, FALSE, 0); gtk_box_pack_end (GTK_BOX (hbox), close_button, FALSE, FALSE, 0);
gtk_widget_show_all (GTK_WIDGET (event_box)); gtk_widget_show_all (GTK_WIDGET (event_box));
if (!priv->close_button) if (!priv->close_button)
gtk_widget_hide (close_button); gtk_widget_hide (close_button);

View file

@ -1,5 +1,5 @@
/* /*
Copyright (C) 2007 Christian Dywan <christian@twotoasts.de> Copyright (C) 2007-2008 Christian Dywan <christian@twotoasts.de>
This library is free software; you can redistribute it and/or This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public modify it under the terms of the GNU Lesser General Public
@ -69,12 +69,65 @@ void sokoke_tool_item_set_tooltip_text(GtkToolItem* toolitem, const gchar* text)
gtk_tool_item_set_tooltip(toolitem, tooltips, text, NULL); gtk_tool_item_set_tooltip(toolitem, tooltips, text, NULL);
} }
void sokoke_widget_popup(GtkWidget* widget, GtkMenu* menu typedef struct
, GdkEventButton* event) {
GtkWidget* widget;
SokokeMenuPos position;
} SokokePopupInfo;
static void
sokoke_widget_popup_position_menu (GtkMenu* menu,
gint* x,
gint* y,
gboolean* push_in,
gpointer user_data)
{
gint wx, wy;
gint menu_width;
GtkRequisition menu_req;
GtkRequisition widget_req;
SokokePopupInfo* info = user_data;
GtkWidget* widget = info->widget;
// Retrieve size and position of both widget and menu
if (GTK_WIDGET_NO_WINDOW (widget))
{
gdk_window_get_position (widget->window, &wx, &wy);
wx += widget->allocation.x;
wy += widget->allocation.y;
}
else
gdk_window_get_origin (widget->window, &wx, &wy);
gtk_widget_size_request (GTK_WIDGET (menu), &menu_req);
gtk_widget_size_request (widget, &widget_req);
menu_width = menu_req.width;
gint widget_height = widget_req.height; // Better than allocation.height
// Calculate menu position
if (info->position == SOKOKE_MENU_POSITION_CURSOR)
; // Do nothing?
else if (info->position == SOKOKE_MENU_POSITION_RIGHT)
{
*x = wx + widget->allocation.width - menu_width;
*y = wy + widget_height;
} else if (info->position == SOKOKE_MENU_POSITION_LEFT)
{
*x = wx;
*y = wy + widget_height;
}
*push_in = TRUE;
}
void
sokoke_widget_popup (GtkWidget* widget,
GtkMenu* menu,
GdkEventButton* event,
SokokeMenuPos pos)
{ {
// TODO: Provide a GtkMenuPositionFunc in case a keyboard invoked this
int button, event_time; int button, event_time;
if(event) if (event)
{ {
button = event->button; button = event->button;
event_time = event->time; event_time = event->time;
@ -82,12 +135,21 @@ void sokoke_widget_popup(GtkWidget* widget, GtkMenu* menu
else else
{ {
button = 0; button = 0;
event_time = gtk_get_current_event_time(); event_time = gtk_get_current_event_time ();
} }
if(!gtk_menu_get_attach_widget(menu)) if (!gtk_menu_get_attach_widget(menu))
gtk_menu_attach_to_widget(menu, widget, NULL); gtk_menu_attach_to_widget (menu, widget, NULL);
gtk_menu_popup(menu, NULL, NULL, NULL, NULL, button, event_time);
if (widget)
{
SokokePopupInfo info = { widget, pos };
gtk_menu_popup (menu, NULL, NULL,
sokoke_widget_popup_position_menu, &info,
button, event_time);
}
else
gtk_menu_popup (menu, NULL, NULL, NULL, NULL, button, event_time);
} }
typedef enum typedef enum

View file

@ -1,5 +1,5 @@
/* /*
Copyright (C) 2007 Christian Dywan <christian@twotoasts.de> Copyright (C) 2007-2008 Christian Dywan <christian@twotoasts.de>
This library is free software; you can redistribute it and/or This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public modify it under the terms of the GNU Lesser General Public
@ -17,6 +17,12 @@
// Many themes need this hack for small toolbars to work // Many themes need this hack for small toolbars to work
#define GTK_ICON_SIZE_SMALL_TOOLBAR GTK_ICON_SIZE_BUTTON #define GTK_ICON_SIZE_SMALL_TOOLBAR GTK_ICON_SIZE_BUTTON
typedef enum {
SOKOKE_MENU_POSITION_CURSOR = 0,
SOKOKE_MENU_POSITION_LEFT,
SOKOKE_MENU_POSITION_RIGHT
} SokokeMenuPos;
void void
sokoke_combo_box_add_strings(GtkComboBox*, const gchar*, ...); sokoke_combo_box_add_strings(GtkComboBox*, const gchar*, ...);
@ -33,7 +39,7 @@ void
sokoke_tool_item_set_tooltip_text(GtkToolItem*, const gchar*); sokoke_tool_item_set_tooltip_text(GtkToolItem*, const gchar*);
void void
sokoke_widget_popup(GtkWidget*, GtkMenu*, GdkEventButton*); sokoke_widget_popup(GtkWidget*, GtkMenu*, GdkEventButton*, SokokeMenuPos pos);
gpointer gpointer
sokoke_xfce_header_new(const gchar*, const gchar*); sokoke_xfce_header_new(const gchar*, const gchar*);

View file

@ -93,7 +93,8 @@ void on_webSearch_icon_released(GtkWidget* widget, SexyIconEntryPosition* pos
menuitem = gtk_action_create_menu_item(action); menuitem = gtk_action_create_menu_item(action);
gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
gtk_widget_show(menuitem);*/ gtk_widget_show(menuitem);*/
sokoke_widget_popup(widget, GTK_MENU(menu), NULL); sokoke_widget_popup(widget, GTK_MENU(menu),
NULL, SOKOKE_MENU_POSITION_LEFT);
} }
static void on_webSearch_engines_render_icon(GtkTreeViewColumn* column static void on_webSearch_engines_render_icon(GtkTreeViewColumn* column