summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2018-08-15 22:01:20 +0000
committerMatthias Clasen <mclasen@redhat.com>2018-08-15 22:01:20 +0000
commit677627346d0fe14dc75a0f4fc5d4a734d24c6872 (patch)
tree38c3ef541cd80570e0fccd9651c50618c1b8fda0
parent436c8802a23e1cbd2fa0bd1ef4641e850979a5fa (diff)
parent14d22cb3233efbd7e9f8f6244179eccc2cc8beb8 (diff)
downloadgtk+-677627346d0fe14dc75a0f4fc5d4a734d24c6872.tar.gz
Merge branch 'wip/tooltip-move-to-rect' into 'gtk-3-24'
Make tooltips use gdk_window_move_to_rect() See merge request GNOME/gtk!293
-rw-r--r--gdk/wayland/gdkwindow-wayland.c16
-rw-r--r--gtk/gtktooltip.c280
-rw-r--r--gtk/gtktooltipwindow.c1
3 files changed, 93 insertions, 204 deletions
diff --git a/gdk/wayland/gdkwindow-wayland.c b/gdk/wayland/gdkwindow-wayland.c
index d54e46c5bc..5f162770a0 100644
--- a/gdk/wayland/gdkwindow-wayland.c
+++ b/gdk/wayland/gdkwindow-wayland.c
@@ -1896,6 +1896,8 @@ gdk_wayland_window_handle_configure_popup (GdkWindow *window,
&flipped_x,
&flipped_y);
+ impl->position_method = POSITION_METHOD_MOVE_TO_RECT;
+
g_signal_emit_by_name (window,
"moved-to-rect",
&flipped_rect,
@@ -2825,6 +2827,9 @@ should_map_as_popup (GdkWindow *window)
break;
}
+ if (impl->position_method == POSITION_METHOD_MOVE_TO_RECT)
+ return TRUE;
+
return FALSE;
}
@@ -3819,6 +3824,7 @@ gdk_wayland_window_set_transient_for (GdkWindow *window,
GdkWaylandDisplay *display_wayland =
GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
GdkWindow *previous_parent;
+ gboolean was_subsurface = FALSE;
g_assert (parent == NULL ||
gdk_window_get_display (window) == gdk_window_get_display (parent));
@@ -3832,7 +3838,10 @@ gdk_wayland_window_set_transient_for (GdkWindow *window,
unset_transient_for_exported (window);
if (impl->display_server.wl_subsurface)
- unmap_subsurface (window);
+ {
+ was_subsurface = TRUE;
+ unmap_subsurface (window);
+ }
previous_parent = impl->transient_for;
impl->transient_for = parent;
@@ -3845,9 +3854,10 @@ gdk_wayland_window_set_transient_for (GdkWindow *window,
display_wayland->orphan_dialogs =
g_list_remove (display_wayland->orphan_dialogs, window);
}
+
gdk_wayland_window_sync_parent (window, NULL);
- if (should_map_as_subsurface (window) &&
- parent && gdk_window_is_visible (window))
+
+ if (was_subsurface && parent)
gdk_wayland_window_create_subsurface (window);
}
diff --git a/gtk/gtktooltip.c b/gtk/gtktooltip.c
index 84ed9fdeed..f9156624ed 100644
--- a/gtk/gtktooltip.c
+++ b/gtk/gtktooltip.c
@@ -114,8 +114,6 @@ struct _GtkTooltip
GtkWidget *tooltip_widget;
- gdouble last_x;
- gdouble last_y;
GdkWindow *last_window;
guint timeout_id;
@@ -865,223 +863,107 @@ gtk_tooltip_run_requery (GtkWidget **widget,
}
static void
-get_bounding_box (GtkWidget *widget,
- GdkRectangle *bounds)
-{
- GtkAllocation allocation;
- GtkBorder border = { 0, };
- GdkWindow *window;
- gint x, y;
- gint w, h;
- gint x1, y1;
- gint x2, y2;
- gint x3, y3;
- gint x4, y4;
-
- window = gtk_widget_get_parent_window (widget);
- if (window == NULL)
- window = gtk_widget_get_window (widget);
-
- gtk_widget_get_allocation (widget, &allocation);
- if (GTK_IS_WINDOW (widget))
- _gtk_window_get_shadow_width (GTK_WINDOW (widget), &border);
- x = allocation.x + border.left;
- y = allocation.y + border.right;
- w = allocation.width - border.left - border.right;
- h = allocation.height - border.top - border.bottom;
-
- gdk_window_get_root_coords (window, x, y, &x1, &y1);
- gdk_window_get_root_coords (window, x + w, y, &x2, &y2);
- gdk_window_get_root_coords (window, x, y + h, &x3, &y3);
- gdk_window_get_root_coords (window, x + w, y + h, &x4, &y4);
-
-#define MIN4(a,b,c,d) MIN(MIN(a,b),MIN(c,d))
-#define MAX4(a,b,c,d) MAX(MAX(a,b),MAX(c,d))
-
- bounds->x = floor (MIN4 (x1, x2, x3, x4));
- bounds->y = floor (MIN4 (y1, y2, y3, y4));
- bounds->width = ceil (MAX4 (x1, x2, x3, x4)) - bounds->x;
- bounds->height = ceil (MAX4 (y1, y2, y3, y4)) - bounds->y;
-}
-
-static void
gtk_tooltip_position (GtkTooltip *tooltip,
GdkDisplay *display,
- GtkWidget *new_tooltip_widget)
+ GtkWidget *new_tooltip_widget,
+ GdkDevice *device)
{
- gint x, y, width, height;
- GdkMonitor *monitor;
- GdkRectangle workarea;
- guint cursor_size;
- GdkRectangle bounds;
- GtkBorder border;
-
-#define MAX_DISTANCE 32
+ GdkScreen *screen;
+ GtkSettings *settings;
+ GdkRectangle anchor_rect;
+ GdkWindow *window;
+ GdkWindow *widget_window;
+ GdkWindow *effective_toplevel;
+ GtkWidget *toplevel;
+ int rect_anchor_dx = 0;
+ int cursor_size;
+ int anchor_rect_padding;
gtk_widget_realize (GTK_WIDGET (tooltip->current_window));
- gtk_widget_set_visible (GTK_WIDGET (tooltip->current_window), TRUE);
+ window = _gtk_widget_get_window (GTK_WIDGET (tooltip->current_window));
tooltip->tooltip_widget = new_tooltip_widget;
- _gtk_window_get_shadow_width (GTK_WINDOW (tooltip->current_window), &border);
-
- width = gtk_widget_get_allocated_width (GTK_WIDGET (tooltip->current_window)) - border.left - border.right;
- height = gtk_widget_get_allocated_height (GTK_WIDGET (tooltip->current_window)) - border.top - border.bottom;
-
- monitor = gdk_display_get_monitor_at_point (display, tooltip->last_x, tooltip->last_y);
- gdk_monitor_get_workarea (monitor, &workarea);
+ toplevel = _gtk_widget_get_toplevel (new_tooltip_widget);
+ gtk_widget_translate_coordinates (new_tooltip_widget, toplevel,
+ 0, 0,
+ &anchor_rect.x, &anchor_rect.y);
- get_bounding_box (new_tooltip_widget, &bounds);
+ anchor_rect.width = gtk_widget_get_allocated_width (new_tooltip_widget);
+ anchor_rect.height = gtk_widget_get_allocated_height (new_tooltip_widget);
- /* Position the tooltip */
-
- cursor_size = gdk_display_get_default_cursor_size (display);
-
- /* Try below */
- x = bounds.x + bounds.width / 2 - width / 2;
- y = bounds.y + bounds.height + 4;
-
- if (y + height <= workarea.y + workarea.height)
- {
- if (tooltip->keyboard_mode_enabled)
- goto found;
+ screen = gdk_window_get_screen (window);
+ settings = gtk_settings_get_for_screen (screen);
+ g_object_get (settings,
+ "gtk-cursor-theme-size", &cursor_size,
+ NULL);
- 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 + width < tooltip->last_x - MAX_DISTANCE)
- x = tooltip->last_x - MAX_DISTANCE - width;
-
- goto found;
- }
- }
+ if (device)
+ anchor_rect_padding = MAX (4, cursor_size - 32);
+ else
+ anchor_rect_padding = 4;
- /* Try above */
- x = bounds.x + bounds.width / 2 - width / 2;
- y = bounds.y - height - 4;
+ anchor_rect.x -= anchor_rect_padding;
+ anchor_rect.y -= anchor_rect_padding;
+ anchor_rect.width += anchor_rect_padding * 2;
+ anchor_rect.height += anchor_rect_padding * 2;
- if (y >= workarea.y)
+ if (device)
{
- if (tooltip->keyboard_mode_enabled)
- goto found;
+ const int max_x_distance = 32;
+ /* Max 48x48 icon + default padding */
+ const int max_anchor_rect_height = 48 + 8;
+ int pointer_x, pointer_y;
+
+ /*
+ * For pointer position triggered tooltips, implement the following
+ * semantics:
+ *
+ * If the anchor rectangle is too tall (meaning if we'd be constrained
+ * and flip, it'd flip too far away), rely only on the pointer position
+ * to position the tooltip. The approximate pointer cursorrectangle is
+ * used as a anchor rectantgle.
+ *
+ * If the anchor rectangle isn't to tall, make sure the tooltip isn't too
+ * far away from the pointer position.
+ */
+ widget_window = _gtk_widget_get_window (new_tooltip_widget);
+ effective_toplevel = gdk_window_get_effective_toplevel (widget_window);
+ gdk_window_get_device_position (effective_toplevel,
+ device,
+ &pointer_x, &pointer_y, NULL);
- if (y + height >= tooltip->last_y - MAX_DISTANCE)
+ if (anchor_rect.height > max_anchor_rect_height)
{
- if (tooltip->last_x + cursor_size + MAX_DISTANCE < x)
- x = tooltip->last_x + cursor_size + MAX_DISTANCE;
- else if (x + width < tooltip->last_x - MAX_DISTANCE)
- x = tooltip->last_x - MAX_DISTANCE - width;
-
- goto found;
+ anchor_rect.x = pointer_x - 4;
+ anchor_rect.y = pointer_y - 4;
+ anchor_rect.width = cursor_size;
+ anchor_rect.height = cursor_size;
}
- }
-
- /* Try right FIXME: flip on rtl ? */
- x = bounds.x + bounds.width + 4;
- y = bounds.y + bounds.height / 2 - height / 2;
-
- if (x + width <= workarea.x + workarea.width)
- {
- if (tooltip->keyboard_mode_enabled)
- goto found;
-
- if (x <= tooltip->last_x + cursor_size + MAX_DISTANCE)
+ else
{
- if (tooltip->last_y + cursor_size + MAX_DISTANCE < y)
- y = tooltip->last_y + cursor_size + MAX_DISTANCE;
- else if (y + height < tooltip->last_y - MAX_DISTANCE)
- y = tooltip->last_y - MAX_DISTANCE - height;
-
- goto found;
- }
- }
+ int anchor_point_x;
+ int x_distance;
- /* Try left FIXME: flip on rtl ? */
- x = bounds.x - width - 4;
- y = bounds.y + bounds.height / 2 - height / 2;
+ anchor_point_x = anchor_rect.x + anchor_rect.width / 2;
+ x_distance = pointer_x - anchor_point_x;
- if (x >= workarea.x)
- {
- if (tooltip->keyboard_mode_enabled)
- goto found;
-
- if (x + 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 + height < tooltip->last_y - MAX_DISTANCE)
- y = tooltip->last_y - MAX_DISTANCE - height;
-
- goto found;
+ if (x_distance > max_x_distance)
+ rect_anchor_dx = x_distance - max_x_distance;
+ else if (x_distance < -max_x_distance)
+ rect_anchor_dx = x_distance + max_x_distance;
}
}
- /* Fallback */
- if (tooltip->keyboard_mode_enabled)
- {
- x = bounds.x + bounds.width / 2 - 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 (x + width > workarea.x + workarea.width)
- x -= x - (workarea.x + workarea.width) + width;
- else if (x < workarea.x)
- x = workarea.x;
-
- if (y + height > workarea.y + workarea.height)
- y -= y - (workarea.y + workarea.height) + height;
- else if (y < workarea.y)
- y = workarea.y;
-
- if (!tooltip->keyboard_mode_enabled)
- {
- /* don't pop up under the pointer */
- if (x <= tooltip->last_x && tooltip->last_x < x + width &&
- y <= tooltip->last_y && tooltip->last_y < y + height)
- y = tooltip->last_y - height - 2;
- }
+ gtk_window_set_transient_for (GTK_WINDOW (tooltip->current_window),
+ GTK_WINDOW (toplevel));
-#ifdef GDK_WINDOWING_WAYLAND
- /* set the transient parent on the tooltip when running with the Wayland
- * backend to allow correct positioning of the tooltip windows
- */
- if (GDK_IS_WAYLAND_DISPLAY (display))
- {
- GtkWidget *toplevel;
-
- toplevel = gtk_widget_get_toplevel (tooltip->tooltip_widget);
- if (GTK_IS_WINDOW (toplevel))
- gtk_window_set_transient_for (GTK_WINDOW (tooltip->current_window),
- GTK_WINDOW (toplevel));
- }
-#endif
-#ifdef GDK_WINDOWING_MIR
- /* Set the transient parent on the tooltip when running with the Mir
- * backend to allow correct positioning of the tooltip windows */
- if (GDK_IS_MIR_DISPLAY (display))
- {
- GtkWidget *toplevel;
-
- toplevel = gtk_widget_get_toplevel (tooltip->tooltip_widget);
- if (GTK_IS_WINDOW (toplevel))
- gtk_window_set_transient_for (GTK_WINDOW (tooltip->current_window),
- GTK_WINDOW (toplevel));
- }
-#endif
-
- x -= border.left;
- y -= border.top;
-
- gtk_window_move (GTK_WINDOW (tooltip->current_window), x, y);
+ gdk_window_move_to_rect (window,
+ &anchor_rect,
+ GDK_GRAVITY_SOUTH,
+ GDK_GRAVITY_NORTH,
+ GDK_ANCHOR_FLIP_Y | GDK_ANCHOR_SLIDE_X,
+ rect_anchor_dx, 0);
gtk_widget_show (GTK_WIDGET (tooltip->current_window));
}
@@ -1090,7 +972,7 @@ gtk_tooltip_show_tooltip (GdkDisplay *display)
{
gint x, y;
GdkScreen *screen;
-
+ GdkDevice *device;
GdkWindow *window;
GtkWidget *tooltip_widget;
GtkTooltip *tooltip;
@@ -1102,10 +984,10 @@ gtk_tooltip_show_tooltip (GdkDisplay *display)
{
x = y = -1;
tooltip_widget = tooltip->keyboard_widget;
+ device = NULL;
}
else
{
- GdkDevice *device;
gint tx, ty;
window = tooltip->last_window;
@@ -1118,8 +1000,6 @@ gtk_tooltip_show_tooltip (GdkDisplay *display)
gdk_window_get_device_position (window, device, &x, &y, NULL);
gdk_window_get_root_coords (window, x, y, &tx, &ty);
- tooltip->last_x = tx;
- tooltip->last_y = ty;
tooltip_widget = _gtk_widget_find_at_coords (window, x, y, &x, &y);
}
@@ -1154,7 +1034,7 @@ gtk_tooltip_show_tooltip (GdkDisplay *display)
G_CALLBACK (gtk_tooltip_display_closed), tooltip);
}
- gtk_tooltip_position (tooltip, display, tooltip_widget);
+ gtk_tooltip_position (tooltip, display, tooltip_widget, device);
/* Now a tooltip is visible again on the display, make sure browse
* mode is enabled.
diff --git a/gtk/gtktooltipwindow.c b/gtk/gtktooltipwindow.c
index 4c9d51715a..a88a64fbd9 100644
--- a/gtk/gtktooltipwindow.c
+++ b/gtk/gtktooltipwindow.c
@@ -79,7 +79,6 @@ gtk_tooltip_window_init (GtkTooltipWindow *self)
gtk_widget_init_template (GTK_WIDGET (self));
- gtk_window_set_use_subsurface (window, TRUE);
_gtk_window_request_csd (window);
}