mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-18 17:30:10 +00:00
Bug 615162 - Fix tooltips on offscreen widgets
Fix the "widget under pointer" logic and keyboard tooltip positioning to do the right thing on offscreen widgets.
This commit is contained in:
parent
fdf936b5ad
commit
ece97b2359
@ -20,6 +20,10 @@
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "gtktooltip.h"
|
||||
#include "gtkintl.h"
|
||||
#include "gtkwindow.h"
|
||||
@ -31,8 +35,6 @@
|
||||
|
||||
#include "gtkalias.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#undef DEBUG_TOOLTIP
|
||||
|
||||
|
||||
@ -472,9 +474,9 @@ gtk_tooltip_trigger_tooltip_query (GdkDisplay *display)
|
||||
event.motion.y = y;
|
||||
event.motion.is_hint = FALSE;
|
||||
|
||||
gdk_window_get_origin (window, &x, &y);
|
||||
event.motion.x_root = event.motion.x + x;
|
||||
event.motion.y_root = event.motion.y + y;
|
||||
gdk_window_get_root_coords (window, x, y, &x, &y);
|
||||
event.motion.x_root = x;
|
||||
event.motion.y_root = y;
|
||||
|
||||
_gtk_tooltip_handle_event (&event);
|
||||
}
|
||||
@ -674,13 +676,15 @@ find_widget_under_pointer (GdkWindow *window,
|
||||
*/
|
||||
while (window && window != event_widget->window)
|
||||
{
|
||||
gint px, py;
|
||||
gdouble px, py;
|
||||
|
||||
gdk_window_get_position (window, &px, &py);
|
||||
child_loc.x += px;
|
||||
child_loc.y += py;
|
||||
gdk_window_coords_to_parent (window,
|
||||
child_loc.x, child_loc.y,
|
||||
&px, &py);
|
||||
child_loc.x = px;
|
||||
child_loc.y = py;
|
||||
|
||||
window = gdk_window_get_parent (window);
|
||||
window = gdk_window_get_effective_parent (window);
|
||||
}
|
||||
|
||||
/* Failing to find widget->window can happen for e.g. a detached handle box;
|
||||
@ -859,6 +863,39 @@ gtk_tooltip_run_requery (GtkWidget **widget,
|
||||
return return_value;
|
||||
}
|
||||
|
||||
static void
|
||||
get_bounding_box (GtkWidget *widget,
|
||||
GdkRectangle *bounds)
|
||||
{
|
||||
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);
|
||||
|
||||
x = widget->allocation.x;
|
||||
y = widget->allocation.y;
|
||||
w = widget->allocation.width;
|
||||
h = widget->allocation.height;
|
||||
|
||||
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,
|
||||
@ -873,18 +910,15 @@ gtk_tooltip_position (GtkTooltip *tooltip,
|
||||
/* FIXME: should we swap this when RTL is enabled? */
|
||||
if (tooltip->keyboard_mode_enabled)
|
||||
{
|
||||
gdk_window_get_origin (new_tooltip_widget->window, &x, &y);
|
||||
if (!gtk_widget_get_has_window (new_tooltip_widget))
|
||||
{
|
||||
x += new_tooltip_widget->allocation.x;
|
||||
y += new_tooltip_widget->allocation.y;
|
||||
}
|
||||
GdkRectangle bounds;
|
||||
|
||||
get_bounding_box (new_tooltip_widget, &bounds);
|
||||
|
||||
/* For keyboard mode we position the tooltip below the widget,
|
||||
* right of the center of the widget.
|
||||
*/
|
||||
x += new_tooltip_widget->allocation.width / 2;
|
||||
y += new_tooltip_widget->allocation.height + 4;
|
||||
x = bounds.x + bounds.width / 2;
|
||||
y = bounds.y + bounds.height + 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -960,14 +994,18 @@ gtk_tooltip_show_tooltip (GdkDisplay *display)
|
||||
}
|
||||
else
|
||||
{
|
||||
gint tx, ty;
|
||||
|
||||
window = tooltip->last_window;
|
||||
|
||||
if (!GDK_IS_WINDOW (window))
|
||||
return;
|
||||
|
||||
gdk_window_get_origin (window, &x, &y);
|
||||
x = tooltip->last_x - x;
|
||||
y = tooltip->last_y - y;
|
||||
gdk_window_get_pointer (window, &x, &y, NULL);
|
||||
|
||||
gdk_window_get_root_coords (window, x, y, &tx, &ty);
|
||||
tooltip->last_x = tx;
|
||||
tooltip->last_y = ty;
|
||||
|
||||
pointer_widget = tooltip_widget = find_widget_under_pointer (window,
|
||||
&x, &y);
|
||||
@ -1290,9 +1328,6 @@ _gtk_tooltip_handle_event (GdkEvent *event)
|
||||
if (current_tooltip)
|
||||
{
|
||||
gtk_tooltip_set_last_window (current_tooltip, event->any.window);
|
||||
gdk_event_get_root_coords (event,
|
||||
¤t_tooltip->last_x,
|
||||
¤t_tooltip->last_y);
|
||||
}
|
||||
|
||||
if (current_tooltip && current_tooltip->keyboard_mode_enabled)
|
||||
@ -1398,9 +1433,6 @@ _gtk_tooltip_handle_event (GdkEvent *event)
|
||||
current_tooltip);
|
||||
|
||||
gtk_tooltip_set_last_window (current_tooltip, event->any.window);
|
||||
gdk_event_get_root_coords (event,
|
||||
¤t_tooltip->last_x,
|
||||
¤t_tooltip->last_y);
|
||||
|
||||
gtk_tooltip_start_delay (display);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user