diff --git a/midori/midori-locationaction.c b/midori/midori-locationaction.c index 0e9bcaa7..2bc59e88 100644 --- a/midori/midori-locationaction.c +++ b/midori/midori-locationaction.c @@ -277,43 +277,97 @@ midori_location_action_create_model (void) } static void -midori_location_action_popup_position (GtkWidget* popup, - GtkWidget* widget) +midori_location_action_popup_position (MidoriLocationAction* action, + gint matches) { + GtkWidget* popup = action->popup; + GtkWidget* widget = action->entry; GdkWindow* window = gtk_widget_get_window (widget); - gint wx, wy; + gint wx, wy, x_border, y_border, items; GtkRequisition menu_req; GtkRequisition widget_req; GdkScreen* screen; gint monitor_num; GdkRectangle monitor; - GtkAllocation allocation; + GtkAllocation alloc; + gint height, sep, width, toplevel_height; + gboolean above; + GtkWidget* scrolled = gtk_widget_get_parent (action->treeview); + GtkWidget* toplevel; + GtkTreePath* path; + if (!window) + return; + + gtk_widget_get_allocation (widget, &alloc); + #if GTK_CHECK_VERSION (3, 0, 0) + gtk_widget_get_preferred_size (widget, &widget_req, NULL); + #else + gtk_widget_size_request (widget, &widget_req); + #endif gdk_window_get_origin (window, &wx, &wy); - if (!gtk_widget_get_has_window (widget)) - { - GtkAllocation alloc; - gtk_widget_get_allocation (widget, &alloc); - wx += alloc.x; - wy += alloc.y; - } + #if GTK_CHECK_VERSION (3, 0, 0) + wx += alloc.x; + wy += alloc.y + (alloc.height - widget_req.height) / 2; + #endif + /* _gtk_entry_get_borders (GTK_ENTRY (widget), &x_border, &y_border); */ + x_border = y_border = 0; - gtk_widget_size_request (popup, &menu_req); - gtk_widget_size_request (widget, &widget_req); + gtk_tree_view_column_cell_get_size ( + gtk_tree_view_get_column (GTK_TREE_VIEW (action->treeview), 0), + NULL, NULL, NULL, NULL, &height); + gtk_widget_style_get (action->treeview, "vertical-separator", &sep, NULL); + height += sep; + gtk_widget_realize (action->treeview); + /* Constrain to screen/ window size */ screen = gtk_widget_get_screen (widget); monitor_num = gdk_screen_get_monitor_at_window (screen, window); gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor); - - if (wy + widget_req.height + menu_req.height <= monitor.y + monitor.height - || wy - monitor.y < (monitor.y + monitor.height) - (wy + widget_req.height)) - wy += widget_req.height; + toplevel = gtk_widget_get_toplevel (widget); + gtk_window_get_size (GTK_WINDOW (toplevel), NULL, &toplevel_height); + toplevel_height = MIN (toplevel_height, monitor.height); + if (wy > toplevel_height / 2) + items = MIN (matches, ((monitor.y + wy) / height) - 1); else + items = MIN (matches, ((toplevel_height - wy) / height) - 1); + width = MIN (alloc.width, monitor.width) - 2 * x_border; + + gtk_tree_view_columns_autosize (GTK_TREE_VIEW (action->treeview)); + #if GTK_CHECK_VERSION (3, 0, 0) + gtk_widget_set_size_request (scrolled, width, -1); + gtk_scrolled_window_set_min_content_width (GTK_SCROLLED_WINDOW (scrolled), width); + gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (scrolled), items * height); + gtk_widget_get_preferred_size (popup, &menu_req, NULL); + #else + gtk_widget_set_size_request (scrolled, width, items * height); + gtk_widget_size_request (popup, &menu_req); + #endif + + if (wx < monitor.x) + wx = monitor.x; + else if (wx + menu_req.width > monitor.x + monitor.width) + wx = monitor.x + monitor.width - menu_req.width; + + if (wy + widget_req.height + menu_req.height <= monitor.y + monitor.height || + wy - monitor.y < (monitor.y + monitor.height) - (wy + widget_req.height)) + { + wy += widget_req.height; + above = FALSE; + } + else + { wy -= menu_req.height; - gtk_window_move (GTK_WINDOW (popup), wx, wy); - gtk_widget_get_allocation (widget, &allocation); - gtk_window_resize (GTK_WINDOW (popup), allocation.width, 1); + above = TRUE; + } + + path = gtk_tree_path_new_from_indices (above ? matches - 1 : 0, -1); + gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (action->treeview), path, + NULL, FALSE, 0.0, 0.0); + gtk_tree_path_free (path); + + gtk_window_move (GTK_WINDOW (popup), wx, wy); } static gboolean @@ -357,8 +411,7 @@ midori_location_action_popup_timeout_cb (gpointer data) gint result; static sqlite3_stmt* stmt; const gchar* sqlcmd; - gint matches, searches, height, screen_height, browser_height, sep; - MidoriBrowser* browser; + gint matches, searches; GtkStyle* style; if (!action->entry || !gtk_widget_has_focus (action->entry) || !action->history) @@ -557,22 +610,10 @@ midori_location_action_popup_timeout_cb (gpointer data) gtk_window_set_screen (GTK_WINDOW (action->popup), gtk_widget_get_screen (action->entry)); gtk_window_set_transient_for (GTK_WINDOW (action->popup), GTK_WINDOW (toplevel)); - gtk_tree_view_columns_autosize (GTK_TREE_VIEW (action->treeview)); + gtk_widget_show_all (action->popup); } - browser = midori_browser_get_for_widget (action->entry); - column = gtk_tree_view_get_column (GTK_TREE_VIEW (action->treeview), 0); - gtk_tree_view_column_cell_get_size (column, NULL, NULL, NULL, NULL, &height); - screen_height = gdk_screen_get_height (gtk_widget_get_screen (action->popup)); - gtk_window_get_size (GTK_WINDOW (browser), NULL, &browser_height); - screen_height = MIN (MIN (browser_height, screen_height / 1.5), screen_height / 1.5); - gtk_widget_style_get (action->treeview, "vertical-separator", &sep, NULL); - /* FIXME: Instead of 1.5 we should relate to the height of one line */ - height = MIN (matches * height + (matches + searches) * sep - + searches * height / 1.5, screen_height); - gtk_widget_set_size_request (action->treeview, -1, height); - midori_location_action_popup_position (action->popup, action->entry); - gtk_widget_show_all (action->popup); + midori_location_action_popup_position (action, matches + searches); return FALSE; }