]> spindle.queued.net Git - midori/commitdiff
Revamp completion popup positioning
authorChristian Dywan <christian@twotoasts.de>
Mon, 20 Feb 2012 20:53:10 +0000 (21:53 +0100)
committerChristian Dywan <christian@twotoasts.de>
Mon, 20 Feb 2012 20:53:10 +0000 (21:53 +0100)
midori/midori-locationaction.c

index 0e9bcaa76d0c2a285a5f11b3e793177d3077c9c7..2bc59e88d9f5ae150f4d46da2dabc59ba52664a1 100644 (file)
@@ -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);
+    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))
+    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;
 }