diff --git a/gtk/gtktooltip.c b/gtk/gtktooltip.c index 9918165..41d8a51 100644 --- a/gtk/gtktooltip.c +++ b/gtk/gtktooltip.c @@ -1094,53 +1094,128 @@ gtk_tooltip_position (GtkTooltip *tooltip, { gint x, y; GdkScreen *screen; + gint monitor_num; + GdkRectangle monitor; + GtkRequisition requisition; + guint cursor_size; + GdkRectangle bounds; + +#define MAX_DISTANCE 32 tooltip->tooltip_widget = new_tooltip_widget; + screen = gtk_widget_get_screen (new_tooltip_widget); + + gtk_widget_size_request (GTK_WIDGET (tooltip->current_window), &requisition); + + monitor_num = gdk_screen_get_monitor_at_point (screen, + tooltip->last_x, + tooltip->last_y); + gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor); + + get_bounding_box (new_tooltip_widget, &bounds); + /* Position the tooltip */ - /* FIXME: should we swap this when RTL is enabled? */ - if (tooltip->keyboard_mode_enabled) + + cursor_size = gdk_display_get_default_cursor_size (display); + + /* Try below */ + x = bounds.x + bounds.width / 2 - requisition.width / 2; + y = bounds.y + bounds.height + 4; + + if (y + requisition.height <= monitor.y + monitor.height) { - GdkRectangle bounds; + if (tooltip->keyboard_mode_enabled) + goto found; - get_bounding_box (new_tooltip_widget, &bounds); + if (y <= tooltip->last_y + cursor_size + MAX_DISTANCE) + { + if (tooltip->last_x + cursor_size + MAX_DISTANCE < x) + x = tooltip->last_x + cursor_size + MAX_DISTANCE; + else if (x + requisition.width < tooltip->last_x - MAX_DISTANCE) + x = tooltip->last_x - MAX_DISTANCE - requisition.width; - /* For keyboard mode we position the tooltip below the widget, - * right of the center of the widget. - */ - x = bounds.x + bounds.width / 2; - y = bounds.y + bounds.height + 4; + goto found; + } + } + + /* Try above */ + x = bounds.x + bounds.width / 2 - requisition.width / 2; + y = bounds.y - requisition.height - 4; + + if (y >= monitor.y) + { + if (tooltip->keyboard_mode_enabled) + goto found; + + if (y + requisition.height >= tooltip->last_y - MAX_DISTANCE) + { + if (tooltip->last_x + cursor_size + MAX_DISTANCE < x) + x = tooltip->last_x + cursor_size + MAX_DISTANCE; + else if (x + requisition.width < tooltip->last_x - MAX_DISTANCE) + x = tooltip->last_x - MAX_DISTANCE - requisition.width; + + goto found; + } } - else + + /* Try right FIXME: flip on rtl ? */ + x = bounds.x + bounds.width + 4; + y = bounds.y + bounds.height / 2 - requisition.height / 2; + + if (x + requisition.width <= monitor.x + monitor.width) { - guint cursor_size; + if (tooltip->keyboard_mode_enabled) + goto found; - x = tooltip->last_x; - y = tooltip->last_y; + if (x <= tooltip->last_x + cursor_size + MAX_DISTANCE) + { + if (tooltip->last_y + cursor_size + MAX_DISTANCE < y) + y = tooltip->last_y + cursor_size + MAX_DISTANCE; + else if (y + requisition.height < tooltip->last_y - MAX_DISTANCE) + y = tooltip->last_y - MAX_DISTANCE - requisition.height; - /* For mouse mode, we position the tooltip right of the cursor, - * a little below the cursor's center. - */ - cursor_size = gdk_display_get_default_cursor_size (display); - x += cursor_size / 2; - y += cursor_size / 2; + goto found; + } } - screen = gtk_widget_get_screen (new_tooltip_widget); + /* Try left FIXME: flip on rtl ? */ + x = bounds.x - requisition.width - 4; + y = bounds.y + bounds.height / 2 - requisition.height / 2; - /* Show it */ - if (tooltip->current_window) + if (x >= monitor.x) { - gint monitor_num; - GdkRectangle monitor; - GtkRequisition requisition; + if (tooltip->keyboard_mode_enabled) + goto found; - gtk_widget_size_request (GTK_WIDGET (tooltip->current_window), - &requisition); + if (x + requisition.width >= tooltip->last_x - MAX_DISTANCE) + { + if (tooltip->last_y + cursor_size + MAX_DISTANCE < y) + y = tooltip->last_y + cursor_size + MAX_DISTANCE; + else if (y + requisition.height < tooltip->last_y - MAX_DISTANCE) + y = tooltip->last_y - MAX_DISTANCE - requisition.height; - monitor_num = gdk_screen_get_monitor_at_point (screen, x, y); - gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor); + goto found; + } + } + /* Fallback */ + if (tooltip->keyboard_mode_enabled) + { + x = bounds.x + bounds.width / 2 - requisition.width / 2; + y = bounds.y + bounds.height + 4; + } + else + { + /* At cursor */ + x = tooltip->last_x + cursor_size * 3 / 4; + y = tooltip->last_y + cursor_size * 3 / 4; + } + +found: + /* Show it */ + if (tooltip->current_window) + { if (x + requisition.width > monitor.x + monitor.width) x -= x - (monitor.x + monitor.width) + requisition.width; else if (x < monitor.x) @@ -1148,7 +1223,9 @@ gtk_tooltip_position (GtkTooltip *tooltip, if (y + requisition.height > monitor.y + monitor.height) y -= y - (monitor.y + monitor.height) + requisition.height; - + else if (y < monitor.y) + y = monitor.y; + if (!tooltip->keyboard_mode_enabled) { /* don't pop up under the pointer */ @@ -1156,7 +1233,7 @@ gtk_tooltip_position (GtkTooltip *tooltip, y <= tooltip->last_y && tooltip->last_y < y + requisition.height) y = tooltip->last_y - requisition.height - 2; } - + gtk_window_move (GTK_WINDOW (tooltip->current_window), x, y); gtk_widget_show (GTK_WIDGET (tooltip->current_window)); }