summaryrefslogtreecommitdiff
path: root/gtk/gtkmenu.c
diff options
context:
space:
mode:
authorSoeren Sandmann <sandmann@daimi.au.dk>2003-08-04 22:09:02 +0000
committerSøren Sandmann Pedersen <ssp@src.gnome.org>2003-08-04 22:09:02 +0000
commit094657e85bdc916860948c31cd99a9e0b15bf6d9 (patch)
tree2f9fe49b3e4ec48b75c2ed3c8cc2e2ce549e2bf0 /gtk/gtkmenu.c
parent6f6d3a2202194c441dfa4745caa1ab83db38789c (diff)
downloadgtk+-094657e85bdc916860948c31cd99a9e0b15bf6d9.tar.gz
New positioning algorithm.(#116649)
Tue Aug 5 00:24:13 2003 Soeren Sandmann <sandmann@daimi.au.dk> * gtk/gtkmenu.c (gtk_menu_position): New positioning algorithm.(#116649)
Diffstat (limited to 'gtk/gtkmenu.c')
-rw-r--r--gtk/gtkmenu.c114
1 files changed, 112 insertions, 2 deletions
diff --git a/gtk/gtkmenu.c b/gtk/gtkmenu.c
index 81907cfd06..81c518ea59 100644
--- a/gtk/gtkmenu.c
+++ b/gtk/gtkmenu.c
@@ -2750,8 +2750,118 @@ gtk_menu_position (GtkMenu *menu)
(* menu->position_func) (menu, &x, &y, &push_in, menu->position_func_data);
else
{
- x = CLAMP (x - 2, monitor.x, MAX (monitor.x, monitor.x + monitor.width - requisition.width));
- y = CLAMP (y - 2, monitor.y, MAX (monitor.y, monitor.y + monitor.height - requisition.height));
+ gint space_left, space_right, space_above, space_below;
+ gint needed_width;
+ gint needed_height;
+ gint xthickness = widget->style->xthickness;
+ gint ythickness = widget->style->ythickness;
+ gboolean rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
+
+ /* The placement of popup menus horizontally works like this (with
+ * RTL in parentheses)
+ *
+ * - If there is enough room to the right (left) of the mouse cursor,
+ * position the menu there.
+ *
+ * - Otherwise, if if there is enough room to the left (right) of the
+ * mouse cursor, position the menu there.
+ *
+ * - Otherwise if the menu is smaller than the monitor, position it
+ * on the side of the mouse cursor that has the most space available
+ *
+ * - Otherwise (if there is simply not enough room for the menu on the
+ * monitor), position it as far left (right) as possible.
+ *
+ * Positioning in the vertical direction is similar: first try below
+ * mouse cursor, then above.
+ */
+ space_left = x - monitor.x;
+ space_right = monitor.x + monitor.width - x - 1;
+ space_above = y - monitor.y;
+ space_below = monitor.y + monitor.height - y - 1;
+
+ /* position horizontally */
+
+ /* the amount of space we need to position the menu. Note the
+ * menu is offset "xthickness" pixels
+ */
+ needed_width = requisition.width - xthickness;
+
+ if (needed_width <= space_left ||
+ needed_width <= space_right)
+ {
+ if ((rtl && needed_width <= space_left) ||
+ (!rtl && needed_width > space_right))
+ {
+ /* position left */
+ x = x + xthickness - requisition.width + 1;
+ }
+ else
+ {
+ /* position right */
+ x = x - xthickness;
+ }
+
+ /* x is clamped on-screen further down */
+ }
+ else if (requisition.width <= monitor.width)
+ {
+ /* the menu is too big to fit on either side of the mouse
+ * cursor, but smaller than the monitor. Position it on
+ * the side that has the most space
+ */
+ if (space_left > space_right)
+ {
+ /* left justify */
+ x = monitor.x;
+ }
+ else
+ {
+ /* right justify */
+ x = monitor.x + monitor.width - requisition.width;
+ }
+ }
+ else /* menu is simply too big for the monitor */
+ {
+ if (rtl)
+ {
+ /* right justify */
+ x = monitor.x + monitor.width - requisition.width;
+ }
+ else
+ {
+ /* left justify */
+ x = monitor.x;
+ }
+ }
+
+ /* Position vertically. The algorithm is the same as above, but
+ * simpler because we don't have to take RTL into account.
+ */
+ needed_height = requisition.height - ythickness;
+
+ if (needed_height <= space_above ||
+ needed_height <= space_below)
+ {
+ if (needed_height <= space_below)
+ y = y - ythickness;
+ else
+ y = y + ythickness - requisition.height + 1;
+
+ y = CLAMP (y, monitor.y,
+ monitor.y + monitor.height - requisition.height);
+ }
+ else if (needed_height > space_below && needed_height > space_above)
+ {
+ if (space_below >= space_above)
+ y = monitor.y + monitor.height - requisition.height;
+ else
+ y = monitor.y;
+ }
+ else
+ {
+ y = monitor.y;
+ }
}
scroll_offset = 0;