forked from AuroraMiddleware/gtk
Merge branch 'tooltip-redo' into 'master'
Tooltip redo See merge request GNOME/gtk!1271
This commit is contained in:
commit
53a634e23e
@ -893,6 +893,16 @@
|
|||||||
radioitem as proxy.
|
radioitem as proxy.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<title>Stop using custom tooltip windows</title>
|
||||||
|
<para>
|
||||||
|
Tooltips no longer use GtkWindows in GTK 4, and it is no longer
|
||||||
|
possible to provide a custom window for tooltips. Replacing the content
|
||||||
|
of the tooltip with a custom widget is still possible, with
|
||||||
|
gtk_tooltip_set_custom().
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
</chapter>
|
</chapter>
|
||||||
|
196
gtk/gtktooltip.c
196
gtk/gtktooltip.c
@ -87,6 +87,13 @@
|
|||||||
#define GTK_IS_TOOLTIP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_TOOLTIP))
|
#define GTK_IS_TOOLTIP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_TOOLTIP))
|
||||||
#define GTK_TOOLTIP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_TOOLTIP, GtkTooltipClass))
|
#define GTK_TOOLTIP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_TOOLTIP, GtkTooltipClass))
|
||||||
|
|
||||||
|
/* We keep a single GtkTooltip object per display. The tooltip object
|
||||||
|
* owns a GtkTooltipWindow widget, which is using a popup surface, similar
|
||||||
|
* to what a GtkPopover does. It gets reparented to the right native widget
|
||||||
|
* whenever a tooltip is to be shown. The tooltip object keeps a weak
|
||||||
|
* ref on the native in order to remove the tooltip window when the
|
||||||
|
* native goes away.
|
||||||
|
*/
|
||||||
typedef struct _GtkTooltipClass GtkTooltipClass;
|
typedef struct _GtkTooltipClass GtkTooltipClass;
|
||||||
|
|
||||||
struct _GtkTooltip
|
struct _GtkTooltip
|
||||||
@ -95,11 +102,9 @@ struct _GtkTooltip
|
|||||||
|
|
||||||
GtkWidget *window;
|
GtkWidget *window;
|
||||||
|
|
||||||
GtkWindow *current_window;
|
|
||||||
|
|
||||||
GtkWidget *tooltip_widget;
|
GtkWidget *tooltip_widget;
|
||||||
|
|
||||||
GdkSurface *last_surface;
|
GtkWidget *native;
|
||||||
|
|
||||||
guint timeout_id;
|
guint timeout_id;
|
||||||
guint browse_mode_timeout_id;
|
guint browse_mode_timeout_id;
|
||||||
@ -116,7 +121,7 @@ struct _GtkTooltipClass
|
|||||||
GObjectClass parent_class;
|
GObjectClass parent_class;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define GTK_TOOLTIP_VISIBLE(tooltip) ((tooltip)->current_window && gtk_widget_get_visible (GTK_WIDGET((tooltip)->current_window)))
|
#define GTK_TOOLTIP_VISIBLE(tooltip) ((tooltip)->window && gtk_widget_get_visible (GTK_WIDGET((tooltip)->window)))
|
||||||
|
|
||||||
static void gtk_tooltip_dispose (GObject *object);
|
static void gtk_tooltip_dispose (GObject *object);
|
||||||
|
|
||||||
@ -125,7 +130,7 @@ static void gtk_tooltip_window_hide (GtkWidget *widget,
|
|||||||
static void gtk_tooltip_display_closed (GdkDisplay *display,
|
static void gtk_tooltip_display_closed (GdkDisplay *display,
|
||||||
gboolean was_error,
|
gboolean was_error,
|
||||||
GtkTooltip *tooltip);
|
GtkTooltip *tooltip);
|
||||||
static void gtk_tooltip_set_last_surface (GtkTooltip *tooltip,
|
static void gtk_tooltip_set_surface (GtkTooltip *tooltip,
|
||||||
GdkSurface *surface);
|
GdkSurface *surface);
|
||||||
|
|
||||||
static void gtk_tooltip_handle_event_internal (GdkEventType event_type,
|
static void gtk_tooltip_handle_event_internal (GdkEventType event_type,
|
||||||
@ -134,16 +139,7 @@ static void gtk_tooltip_handle_event_internal (GdkEventType event_type,
|
|||||||
gdouble dx,
|
gdouble dx,
|
||||||
gdouble dy);
|
gdouble dy);
|
||||||
|
|
||||||
static inline GQuark tooltip_quark (void)
|
static GQuark quark_current_tooltip;
|
||||||
{
|
|
||||||
static GQuark quark;
|
|
||||||
|
|
||||||
if G_UNLIKELY (quark == 0)
|
|
||||||
quark = g_quark_from_static_string ("gdk-display-current-tooltip");
|
|
||||||
return quark;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define quark_current_tooltip tooltip_quark()
|
|
||||||
|
|
||||||
G_DEFINE_TYPE (GtkTooltip, gtk_tooltip, G_TYPE_OBJECT);
|
G_DEFINE_TYPE (GtkTooltip, gtk_tooltip, G_TYPE_OBJECT);
|
||||||
|
|
||||||
@ -152,6 +148,8 @@ gtk_tooltip_class_init (GtkTooltipClass *klass)
|
|||||||
{
|
{
|
||||||
GObjectClass *object_class;
|
GObjectClass *object_class;
|
||||||
|
|
||||||
|
quark_current_tooltip = g_quark_from_static_string ("gdk-display-current-tooltip");
|
||||||
|
|
||||||
object_class = G_OBJECT_CLASS (klass);
|
object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
object_class->dispose = gtk_tooltip_dispose;
|
object_class->dispose = gtk_tooltip_dispose;
|
||||||
@ -165,13 +163,12 @@ gtk_tooltip_init (GtkTooltip *tooltip)
|
|||||||
|
|
||||||
tooltip->browse_mode_enabled = FALSE;
|
tooltip->browse_mode_enabled = FALSE;
|
||||||
|
|
||||||
tooltip->current_window = NULL;
|
|
||||||
|
|
||||||
tooltip->tooltip_widget = NULL;
|
tooltip->tooltip_widget = NULL;
|
||||||
|
|
||||||
tooltip->last_surface = NULL;
|
tooltip->native = NULL;
|
||||||
|
|
||||||
tooltip->window = gtk_tooltip_window_new ();
|
tooltip->window = gtk_tooltip_window_new ();
|
||||||
|
g_object_ref_sink (tooltip->window);
|
||||||
g_signal_connect (tooltip->window, "hide",
|
g_signal_connect (tooltip->window, "hide",
|
||||||
G_CALLBACK (gtk_tooltip_window_hide),
|
G_CALLBACK (gtk_tooltip_window_hide),
|
||||||
tooltip);
|
tooltip);
|
||||||
@ -195,7 +192,7 @@ gtk_tooltip_dispose (GObject *object)
|
|||||||
}
|
}
|
||||||
|
|
||||||
gtk_tooltip_set_custom (tooltip, NULL);
|
gtk_tooltip_set_custom (tooltip, NULL);
|
||||||
gtk_tooltip_set_last_surface (tooltip, NULL);
|
gtk_tooltip_set_surface (tooltip, NULL);
|
||||||
|
|
||||||
if (tooltip->window)
|
if (tooltip->window)
|
||||||
{
|
{
|
||||||
@ -205,8 +202,8 @@ gtk_tooltip_dispose (GObject *object)
|
|||||||
g_signal_handlers_disconnect_by_func (display,
|
g_signal_handlers_disconnect_by_func (display,
|
||||||
gtk_tooltip_display_closed,
|
gtk_tooltip_display_closed,
|
||||||
tooltip);
|
tooltip);
|
||||||
gtk_widget_destroy (tooltip->window);
|
gtk_tooltip_window_set_relative_to (GTK_TOOLTIP_WINDOW (tooltip->window), NULL);
|
||||||
tooltip->window = NULL;
|
g_clear_object (&tooltip->window);
|
||||||
}
|
}
|
||||||
|
|
||||||
G_OBJECT_CLASS (gtk_tooltip_parent_class)->dispose (object);
|
G_OBJECT_CLASS (gtk_tooltip_parent_class)->dispose (object);
|
||||||
@ -476,37 +473,40 @@ gtk_tooltip_display_closed (GdkDisplay *display,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gtk_tooltip_set_last_surface (GtkTooltip *tooltip,
|
native_weak_notify (gpointer data, GObject *former_object)
|
||||||
GdkSurface *surface)
|
|
||||||
{
|
{
|
||||||
GtkWidget *window_widget = NULL;
|
GtkTooltip *tooltip = data;
|
||||||
|
|
||||||
if (tooltip->last_surface == surface)
|
gtk_tooltip_window_set_relative_to (GTK_TOOLTIP_WINDOW (tooltip->window), NULL);
|
||||||
return;
|
tooltip->native = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (tooltip->last_surface)
|
static void
|
||||||
g_object_remove_weak_pointer (G_OBJECT (tooltip->last_surface),
|
gtk_tooltip_set_surface (GtkTooltip *tooltip,
|
||||||
(gpointer *) &tooltip->last_surface);
|
GdkSurface *surface)
|
||||||
|
{
|
||||||
tooltip->last_surface = surface;
|
GtkWidget *native;
|
||||||
|
|
||||||
if (tooltip->last_surface)
|
|
||||||
g_object_add_weak_pointer (G_OBJECT (tooltip->last_surface),
|
|
||||||
(gpointer *) &tooltip->last_surface);
|
|
||||||
|
|
||||||
if (surface)
|
if (surface)
|
||||||
window_widget = gtk_native_get_for_surface (surface);
|
native = gtk_native_get_for_surface (surface);
|
||||||
|
|
||||||
if (window_widget)
|
|
||||||
window_widget = GTK_WIDGET (gtk_widget_get_root (window_widget));
|
|
||||||
|
|
||||||
if (window_widget &&
|
|
||||||
window_widget != tooltip->window &&
|
|
||||||
GTK_IS_WINDOW (window_widget))
|
|
||||||
gtk_window_set_transient_for (GTK_WINDOW (tooltip->window),
|
|
||||||
GTK_WINDOW (window_widget));
|
|
||||||
else
|
else
|
||||||
gtk_window_set_transient_for (GTK_WINDOW (tooltip->window), NULL);
|
native = NULL;
|
||||||
|
|
||||||
|
if (tooltip->native == native)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (tooltip->native)
|
||||||
|
g_object_weak_unref (G_OBJECT (tooltip->native), native_weak_notify, tooltip);
|
||||||
|
|
||||||
|
tooltip->native = native;
|
||||||
|
|
||||||
|
if (tooltip->native)
|
||||||
|
g_object_weak_ref (G_OBJECT (tooltip->native), native_weak_notify, tooltip);
|
||||||
|
|
||||||
|
if (native)
|
||||||
|
gtk_tooltip_window_set_relative_to (GTK_TOOLTIP_WINDOW (tooltip->window), native);
|
||||||
|
else
|
||||||
|
gtk_tooltip_window_set_relative_to (GTK_TOOLTIP_WINDOW (tooltip->window), NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -567,19 +567,17 @@ gtk_tooltip_position (GtkTooltip *tooltip,
|
|||||||
GtkSettings *settings;
|
GtkSettings *settings;
|
||||||
graphene_rect_t anchor_bounds;
|
graphene_rect_t anchor_bounds;
|
||||||
GdkRectangle anchor_rect;
|
GdkRectangle anchor_rect;
|
||||||
GdkSurface *surface;
|
|
||||||
GdkSurface *effective_toplevel;
|
GdkSurface *effective_toplevel;
|
||||||
GtkWidget *toplevel;
|
GtkWidget *toplevel;
|
||||||
int rect_anchor_dx = 0;
|
int rect_anchor_dx = 0;
|
||||||
int cursor_size;
|
int cursor_size;
|
||||||
int anchor_rect_padding;
|
int anchor_rect_padding;
|
||||||
|
|
||||||
gtk_widget_realize (GTK_WIDGET (tooltip->current_window));
|
gtk_widget_realize (GTK_WIDGET (tooltip->window));
|
||||||
surface = gtk_native_get_surface (GTK_NATIVE (tooltip->current_window));
|
|
||||||
|
|
||||||
tooltip->tooltip_widget = new_tooltip_widget;
|
tooltip->tooltip_widget = new_tooltip_widget;
|
||||||
|
|
||||||
toplevel = GTK_WIDGET (gtk_widget_get_root (new_tooltip_widget));
|
toplevel = GTK_WIDGET (gtk_widget_get_native (new_tooltip_widget));
|
||||||
if (gtk_widget_compute_bounds (new_tooltip_widget, toplevel, &anchor_bounds))
|
if (gtk_widget_compute_bounds (new_tooltip_widget, toplevel, &anchor_bounds))
|
||||||
{
|
{
|
||||||
anchor_rect = (GdkRectangle) {
|
anchor_rect = (GdkRectangle) {
|
||||||
@ -657,16 +655,12 @@ gtk_tooltip_position (GtkTooltip *tooltip,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gtk_window_set_transient_for (GTK_WINDOW (tooltip->current_window),
|
gtk_tooltip_window_position (GTK_TOOLTIP_WINDOW (tooltip->window),
|
||||||
GTK_WINDOW (toplevel));
|
&anchor_rect,
|
||||||
|
GDK_GRAVITY_SOUTH,
|
||||||
gdk_surface_move_to_rect (surface,
|
GDK_GRAVITY_NORTH,
|
||||||
&anchor_rect,
|
GDK_ANCHOR_FLIP_Y | GDK_ANCHOR_SLIDE_X,
|
||||||
GDK_GRAVITY_SOUTH,
|
rect_anchor_dx, 0);
|
||||||
GDK_GRAVITY_NORTH,
|
|
||||||
GDK_ANCHOR_FLIP_Y | GDK_ANCHOR_SLIDE_X,
|
|
||||||
rect_anchor_dx, 0);
|
|
||||||
gtk_widget_show (GTK_WIDGET (tooltip->current_window));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -682,20 +676,18 @@ gtk_tooltip_show_tooltip (GdkDisplay *display)
|
|||||||
|
|
||||||
tooltip = g_object_get_qdata (G_OBJECT (display), quark_current_tooltip);
|
tooltip = g_object_get_qdata (G_OBJECT (display), quark_current_tooltip);
|
||||||
|
|
||||||
{
|
if (!tooltip->native)
|
||||||
surface = tooltip->last_surface;
|
return;
|
||||||
|
|
||||||
if (!GDK_IS_SURFACE (surface))
|
surface = gtk_native_get_surface (GTK_NATIVE (tooltip->native));
|
||||||
return;
|
|
||||||
|
|
||||||
device = gdk_seat_get_pointer (gdk_display_get_default_seat (display));
|
device = gdk_seat_get_pointer (gdk_display_get_default_seat (display));
|
||||||
|
|
||||||
gdk_surface_get_device_position (surface, device, &px, &py, NULL);
|
gdk_surface_get_device_position (surface, device, &px, &py, NULL);
|
||||||
x = round (px);
|
x = round (px);
|
||||||
y = round (py);
|
y = round (py);
|
||||||
|
|
||||||
tooltip_widget = _gtk_widget_find_at_coords (surface, x, y, &x, &y);
|
tooltip_widget = _gtk_widget_find_at_coords (surface, x, y, &x, &y);
|
||||||
}
|
|
||||||
|
|
||||||
if (!tooltip_widget)
|
if (!tooltip_widget)
|
||||||
return;
|
return;
|
||||||
@ -704,15 +696,7 @@ gtk_tooltip_show_tooltip (GdkDisplay *display)
|
|||||||
if (!return_value)
|
if (!return_value)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!tooltip->current_window)
|
/* FIXME: should use tooltip->window iso tooltip->window */
|
||||||
{
|
|
||||||
if (gtk_widget_get_tooltip_window (tooltip_widget))
|
|
||||||
tooltip->current_window = gtk_widget_get_tooltip_window (tooltip_widget);
|
|
||||||
else
|
|
||||||
tooltip->current_window = GTK_WINDOW (GTK_TOOLTIP (tooltip)->window);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FIXME: should use tooltip->current_window iso tooltip->window */
|
|
||||||
if (display != gtk_widget_get_display (tooltip->window))
|
if (display != gtk_widget_get_display (tooltip->window))
|
||||||
{
|
{
|
||||||
g_signal_handlers_disconnect_by_func (display,
|
g_signal_handlers_disconnect_by_func (display,
|
||||||
@ -727,6 +711,8 @@ gtk_tooltip_show_tooltip (GdkDisplay *display)
|
|||||||
|
|
||||||
gtk_tooltip_position (tooltip, display, tooltip_widget, device);
|
gtk_tooltip_position (tooltip, display, tooltip_widget, device);
|
||||||
|
|
||||||
|
gtk_widget_show (GTK_WIDGET (tooltip->window));
|
||||||
|
|
||||||
/* Now a tooltip is visible again on the display, make sure browse
|
/* Now a tooltip is visible again on the display, make sure browse
|
||||||
* mode is enabled.
|
* mode is enabled.
|
||||||
*/
|
*/
|
||||||
@ -770,11 +756,8 @@ gtk_tooltip_hide_tooltip (GtkTooltip *tooltip)
|
|||||||
g_source_set_name_by_id (tooltip->browse_mode_timeout_id, "[gtk] tooltip_browse_mode_expired");
|
g_source_set_name_by_id (tooltip->browse_mode_timeout_id, "[gtk] tooltip_browse_mode_expired");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tooltip->current_window)
|
if (tooltip->window)
|
||||||
{
|
gtk_widget_hide (tooltip->window);
|
||||||
gtk_widget_hide (GTK_WIDGET (tooltip->current_window));
|
|
||||||
tooltip->current_window = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gint
|
static gint
|
||||||
@ -834,7 +817,7 @@ _gtk_tooltip_hide (GtkWidget *widget)
|
|||||||
display = gtk_widget_get_display (widget);
|
display = gtk_widget_get_display (widget);
|
||||||
tooltip = g_object_get_qdata (G_OBJECT (display), quark_current_tooltip);
|
tooltip = g_object_get_qdata (G_OBJECT (display), quark_current_tooltip);
|
||||||
|
|
||||||
if (!tooltip || !GTK_TOOLTIP_VISIBLE (tooltip) || !tooltip->tooltip_widget)
|
if (!tooltip || !tooltip->window || !tooltip->tooltip_widget)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (widget == tooltip->tooltip_widget)
|
if (widget == tooltip->tooltip_widget)
|
||||||
@ -916,19 +899,19 @@ gtk_tooltip_handle_event_internal (GdkEventType event_type,
|
|||||||
{
|
{
|
||||||
int x = dx, y = dy;
|
int x = dx, y = dy;
|
||||||
GdkDisplay *display;
|
GdkDisplay *display;
|
||||||
GtkTooltip *current_tooltip;
|
GtkTooltip *tooltip;
|
||||||
|
|
||||||
display = gdk_surface_get_display (surface);
|
display = gdk_surface_get_display (surface);
|
||||||
current_tooltip = g_object_get_qdata (G_OBJECT (display), quark_current_tooltip);
|
tooltip = g_object_get_qdata (G_OBJECT (display), quark_current_tooltip);
|
||||||
|
|
||||||
if (current_tooltip)
|
if (tooltip)
|
||||||
gtk_tooltip_set_last_surface (current_tooltip, surface);
|
gtk_tooltip_set_surface (tooltip, surface);
|
||||||
|
|
||||||
/* Hide the tooltip when there's no new tooltip widget */
|
/* Hide the tooltip when there's no new tooltip widget */
|
||||||
if (!target_widget)
|
if (!target_widget)
|
||||||
{
|
{
|
||||||
if (current_tooltip)
|
if (tooltip)
|
||||||
gtk_tooltip_hide_tooltip (current_tooltip);
|
gtk_tooltip_hide_tooltip (tooltip);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -940,54 +923,49 @@ gtk_tooltip_handle_event_internal (GdkEventType event_type,
|
|||||||
case GDK_DRAG_ENTER:
|
case GDK_DRAG_ENTER:
|
||||||
case GDK_GRAB_BROKEN:
|
case GDK_GRAB_BROKEN:
|
||||||
case GDK_SCROLL:
|
case GDK_SCROLL:
|
||||||
gtk_tooltip_hide_tooltip (current_tooltip);
|
gtk_tooltip_hide_tooltip (tooltip);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GDK_MOTION_NOTIFY:
|
case GDK_MOTION_NOTIFY:
|
||||||
case GDK_ENTER_NOTIFY:
|
case GDK_ENTER_NOTIFY:
|
||||||
case GDK_LEAVE_NOTIFY:
|
case GDK_LEAVE_NOTIFY:
|
||||||
if (current_tooltip)
|
if (tooltip)
|
||||||
{
|
{
|
||||||
gboolean tip_area_set;
|
gboolean tip_area_set;
|
||||||
GdkRectangle tip_area;
|
GdkRectangle tip_area;
|
||||||
gboolean hide_tooltip;
|
gboolean hide_tooltip;
|
||||||
|
|
||||||
tip_area_set = current_tooltip->tip_area_set;
|
tip_area_set = tooltip->tip_area_set;
|
||||||
tip_area = current_tooltip->tip_area;
|
tip_area = tooltip->tip_area;
|
||||||
|
|
||||||
gtk_tooltip_run_requery (&target_widget,
|
gtk_tooltip_run_requery (&target_widget, tooltip, &x, &y);
|
||||||
current_tooltip,
|
|
||||||
&x, &y);
|
|
||||||
|
|
||||||
/* Leave notify should override the query function */
|
/* Leave notify should override the query function */
|
||||||
hide_tooltip = (event_type == GDK_LEAVE_NOTIFY);
|
hide_tooltip = (event_type == GDK_LEAVE_NOTIFY);
|
||||||
|
|
||||||
/* Is the pointer above another widget now? */
|
/* Is the pointer above another widget now? */
|
||||||
if (GTK_TOOLTIP_VISIBLE (current_tooltip))
|
if (GTK_TOOLTIP_VISIBLE (tooltip))
|
||||||
hide_tooltip |= target_widget != current_tooltip->tooltip_widget;
|
hide_tooltip |= target_widget != tooltip->tooltip_widget;
|
||||||
|
|
||||||
/* Did the pointer move out of the previous "context area"? */
|
/* Did the pointer move out of the previous "context area"? */
|
||||||
if (tip_area_set)
|
if (tip_area_set)
|
||||||
hide_tooltip |= !gdk_rectangle_contains_point (&tip_area, x, y);
|
hide_tooltip |= !gdk_rectangle_contains_point (&tip_area, x, y);
|
||||||
|
|
||||||
if (hide_tooltip)
|
if (hide_tooltip)
|
||||||
gtk_tooltip_hide_tooltip (current_tooltip);
|
gtk_tooltip_hide_tooltip (tooltip);
|
||||||
else
|
else
|
||||||
gtk_tooltip_start_delay (display);
|
gtk_tooltip_start_delay (display);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Need a new tooltip for this display */
|
/* Need a new tooltip for this display */
|
||||||
current_tooltip = g_object_new (GTK_TYPE_TOOLTIP, NULL);
|
tooltip = g_object_new (GTK_TYPE_TOOLTIP, NULL);
|
||||||
g_object_set_qdata_full (G_OBJECT (display),
|
g_object_set_qdata_full (G_OBJECT (display), quark_current_tooltip,
|
||||||
quark_current_tooltip,
|
tooltip, g_object_unref);
|
||||||
current_tooltip,
|
|
||||||
g_object_unref);
|
|
||||||
g_signal_connect (display, "closed",
|
g_signal_connect (display, "closed",
|
||||||
G_CALLBACK (gtk_tooltip_display_closed),
|
G_CALLBACK (gtk_tooltip_display_closed), tooltip);
|
||||||
current_tooltip);
|
|
||||||
|
|
||||||
gtk_tooltip_set_last_surface (current_tooltip, surface);
|
gtk_tooltip_set_surface (tooltip, surface);
|
||||||
|
|
||||||
gtk_tooltip_start_delay (display);
|
gtk_tooltip_start_delay (display);
|
||||||
}
|
}
|
||||||
|
@ -38,11 +38,27 @@
|
|||||||
#include "gtksizerequest.h"
|
#include "gtksizerequest.h"
|
||||||
#include "gtkwindowprivate.h"
|
#include "gtkwindowprivate.h"
|
||||||
#include "gtkwidgetprivate.h"
|
#include "gtkwidgetprivate.h"
|
||||||
|
#include "gtknative.h"
|
||||||
|
#include "gtkstylecontext.h"
|
||||||
|
#include "gtkcssnodeprivate.h"
|
||||||
|
|
||||||
struct _GtkTooltipWindow
|
struct _GtkTooltipWindow
|
||||||
{
|
{
|
||||||
GtkWindow parent_type;
|
GtkWindow parent_type;
|
||||||
|
|
||||||
|
GdkSurface *surface;
|
||||||
|
GskRenderer *renderer;
|
||||||
|
|
||||||
|
GdkSurfaceState state;
|
||||||
|
GtkWidget *relative_to;
|
||||||
|
GdkRectangle rect;
|
||||||
|
GdkGravity rect_anchor;
|
||||||
|
GdkGravity surface_anchor;
|
||||||
|
GdkAnchorHints anchor_hints;
|
||||||
|
int dx;
|
||||||
|
int dy;
|
||||||
|
guint surface_transform_changed_cb;
|
||||||
|
|
||||||
GtkWidget *box;
|
GtkWidget *box;
|
||||||
GtkWidget *image;
|
GtkWidget *image;
|
||||||
GtkWidget *label;
|
GtkWidget *label;
|
||||||
@ -54,13 +70,349 @@ struct _GtkTooltipWindowClass
|
|||||||
GtkWindowClass parent_class;
|
GtkWindowClass parent_class;
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE (GtkTooltipWindow, gtk_tooltip_window, GTK_TYPE_WINDOW)
|
static void gtk_tooltip_window_native_init (GtkNativeInterface *iface);
|
||||||
|
|
||||||
|
G_DEFINE_TYPE_WITH_CODE (GtkTooltipWindow, gtk_tooltip_window, GTK_TYPE_BIN,
|
||||||
|
G_IMPLEMENT_INTERFACE (GTK_TYPE_NATIVE,
|
||||||
|
gtk_tooltip_window_native_init))
|
||||||
|
|
||||||
|
|
||||||
|
static GdkSurface *
|
||||||
|
gtk_tooltip_window_native_get_surface (GtkNative *native)
|
||||||
|
{
|
||||||
|
GtkTooltipWindow *window = GTK_TOOLTIP_WINDOW (native);
|
||||||
|
|
||||||
|
return window->surface;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GskRenderer *
|
||||||
|
gtk_tooltip_window_native_get_renderer (GtkNative *native)
|
||||||
|
{
|
||||||
|
GtkTooltipWindow *window = GTK_TOOLTIP_WINDOW (native);
|
||||||
|
|
||||||
|
return window->renderer;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_tooltip_window_native_get_surface_transform (GtkNative *native,
|
||||||
|
int *x,
|
||||||
|
int *y)
|
||||||
|
{
|
||||||
|
GtkStyleContext *context;
|
||||||
|
GtkBorder margin, border, padding;
|
||||||
|
|
||||||
|
context = gtk_widget_get_style_context (GTK_WIDGET (native));
|
||||||
|
gtk_style_context_get_margin (context, &margin);
|
||||||
|
gtk_style_context_get_border (context, &border);
|
||||||
|
gtk_style_context_get_padding (context, &padding);
|
||||||
|
|
||||||
|
*x = margin.left + border.left + padding.left;
|
||||||
|
*y = margin.top + border.top + padding.top;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
move_to_rect (GtkTooltipWindow *window)
|
||||||
|
{
|
||||||
|
gdk_surface_move_to_rect (window->surface,
|
||||||
|
&window->rect,
|
||||||
|
window->rect_anchor,
|
||||||
|
window->surface_anchor,
|
||||||
|
window->anchor_hints,
|
||||||
|
window->dx,
|
||||||
|
window->dy);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_tooltip_window_move_resize (GtkTooltipWindow *window)
|
||||||
|
{
|
||||||
|
GtkRequisition req;
|
||||||
|
|
||||||
|
if (window->surface)
|
||||||
|
{
|
||||||
|
gtk_widget_get_preferred_size (GTK_WIDGET (window), NULL, &req);
|
||||||
|
gdk_surface_resize (window->surface, req.width, req.height);
|
||||||
|
move_to_rect (window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_tooltip_window_native_check_resize (GtkNative *native)
|
||||||
|
{
|
||||||
|
GtkTooltipWindow *window = GTK_TOOLTIP_WINDOW (native);
|
||||||
|
GtkWidget *widget = GTK_WIDGET (native);
|
||||||
|
|
||||||
|
if (!_gtk_widget_get_alloc_needed (widget))
|
||||||
|
gtk_widget_ensure_allocate (widget);
|
||||||
|
else if (gtk_widget_get_visible (widget))
|
||||||
|
{
|
||||||
|
gtk_tooltip_window_move_resize (window);
|
||||||
|
if (window->surface)
|
||||||
|
gtk_widget_allocate (GTK_WIDGET (window),
|
||||||
|
gdk_surface_get_width (window->surface),
|
||||||
|
gdk_surface_get_height (window->surface),
|
||||||
|
-1, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_tooltip_window_native_init (GtkNativeInterface *iface)
|
||||||
|
{
|
||||||
|
iface->get_surface = gtk_tooltip_window_native_get_surface;
|
||||||
|
iface->get_renderer = gtk_tooltip_window_native_get_renderer;
|
||||||
|
iface->get_surface_transform = gtk_tooltip_window_native_get_surface_transform;
|
||||||
|
iface->check_resize = gtk_tooltip_window_native_check_resize;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
surface_state_changed (GtkWidget *widget)
|
||||||
|
{
|
||||||
|
GtkTooltipWindow *window = GTK_TOOLTIP_WINDOW (widget);
|
||||||
|
GdkSurfaceState new_surface_state;
|
||||||
|
GdkSurfaceState changed_mask;
|
||||||
|
|
||||||
|
new_surface_state = gdk_surface_get_state (window->surface);
|
||||||
|
changed_mask = new_surface_state ^ window->state;
|
||||||
|
window->state = new_surface_state;
|
||||||
|
|
||||||
|
if (changed_mask & GDK_SURFACE_STATE_WITHDRAWN)
|
||||||
|
{
|
||||||
|
if (window->state & GDK_SURFACE_STATE_WITHDRAWN)
|
||||||
|
gtk_widget_hide (widget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
surface_size_changed (GtkWidget *widget,
|
||||||
|
guint width,
|
||||||
|
guint height)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
surface_render (GdkSurface *surface,
|
||||||
|
cairo_region_t *region,
|
||||||
|
GtkWidget *widget)
|
||||||
|
{
|
||||||
|
gtk_widget_render (widget, surface, region);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
surface_event (GdkSurface *surface,
|
||||||
|
GdkEvent *event,
|
||||||
|
GtkWidget *widget)
|
||||||
|
{
|
||||||
|
gtk_main_do_event (event);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
surface_moved_to_rect (GdkSurface *surface,
|
||||||
|
GdkRectangle *flipped_rect,
|
||||||
|
GdkRectangle *final_rect,
|
||||||
|
gboolean flipped_x,
|
||||||
|
gboolean flipped_y,
|
||||||
|
GtkWidget *widget)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_tooltip_window_realize (GtkWidget *widget)
|
||||||
|
{
|
||||||
|
GtkTooltipWindow *window = GTK_TOOLTIP_WINDOW (widget);
|
||||||
|
GdkDisplay *display;
|
||||||
|
GdkSurface *parent;
|
||||||
|
|
||||||
|
display = gtk_widget_get_display (window->relative_to);
|
||||||
|
|
||||||
|
parent = gtk_native_get_surface (gtk_widget_get_native (window->relative_to));
|
||||||
|
window->surface = gdk_surface_new_popup (display, parent, FALSE);
|
||||||
|
|
||||||
|
gdk_surface_set_widget (window->surface, widget);
|
||||||
|
|
||||||
|
g_signal_connect_swapped (window->surface, "notify::state", G_CALLBACK (surface_state_changed), widget);
|
||||||
|
g_signal_connect_swapped (window->surface, "size-changed", G_CALLBACK (surface_size_changed), widget);
|
||||||
|
g_signal_connect (window->surface, "render", G_CALLBACK (surface_render), widget);
|
||||||
|
g_signal_connect (window->surface, "event", G_CALLBACK (surface_event), widget);
|
||||||
|
g_signal_connect (window->surface, "moved-to-rect", G_CALLBACK (surface_moved_to_rect), widget);
|
||||||
|
|
||||||
|
GTK_WIDGET_CLASS (gtk_tooltip_window_parent_class)->realize (widget);
|
||||||
|
|
||||||
|
window->renderer = gsk_renderer_new_for_surface (window->surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_tooltip_window_unrealize (GtkWidget *widget)
|
||||||
|
{
|
||||||
|
GtkTooltipWindow *window = GTK_TOOLTIP_WINDOW (widget);
|
||||||
|
|
||||||
|
GTK_WIDGET_CLASS (gtk_tooltip_window_parent_class)->unrealize (widget);
|
||||||
|
|
||||||
|
gsk_renderer_unrealize (window->renderer);
|
||||||
|
g_clear_object (&window->renderer);
|
||||||
|
|
||||||
|
g_signal_handlers_disconnect_by_func (window->surface, surface_state_changed, widget);
|
||||||
|
g_signal_handlers_disconnect_by_func (window->surface, surface_size_changed, widget);
|
||||||
|
g_signal_handlers_disconnect_by_func (window->surface, surface_render, widget);
|
||||||
|
g_signal_handlers_disconnect_by_func (window->surface, surface_event, widget);
|
||||||
|
g_signal_handlers_disconnect_by_func (window->surface, surface_moved_to_rect, widget);
|
||||||
|
gdk_surface_set_widget (window->surface, NULL);
|
||||||
|
gdk_surface_destroy (window->surface);
|
||||||
|
g_clear_object (&window->surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
unset_surface_transform_changed_cb (gpointer data)
|
||||||
|
{
|
||||||
|
GtkTooltipWindow *window = GTK_TOOLTIP_WINDOW (data);
|
||||||
|
|
||||||
|
window->surface_transform_changed_cb = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
surface_transform_changed_cb (GtkWidget *widget,
|
||||||
|
const graphene_matrix_t *transform,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GtkTooltipWindow *window = GTK_TOOLTIP_WINDOW (widget);
|
||||||
|
|
||||||
|
move_to_rect (window);
|
||||||
|
|
||||||
|
return G_SOURCE_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_tooltip_window_map (GtkWidget *widget)
|
||||||
|
{
|
||||||
|
GtkTooltipWindow *window = GTK_TOOLTIP_WINDOW (widget);
|
||||||
|
GtkWidget *child;
|
||||||
|
|
||||||
|
gdk_surface_show (window->surface);
|
||||||
|
move_to_rect (window);
|
||||||
|
|
||||||
|
window->surface_transform_changed_cb =
|
||||||
|
gtk_widget_add_surface_transform_changed_callback (window->relative_to,
|
||||||
|
surface_transform_changed_cb,
|
||||||
|
window,
|
||||||
|
unset_surface_transform_changed_cb);
|
||||||
|
|
||||||
|
GTK_WIDGET_CLASS (gtk_tooltip_window_parent_class)->map (widget);
|
||||||
|
|
||||||
|
child = gtk_bin_get_child (GTK_BIN (widget));
|
||||||
|
if (child != NULL && gtk_widget_get_visible (child))
|
||||||
|
gtk_widget_map (child);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_tooltip_window_unmap (GtkWidget *widget)
|
||||||
|
{
|
||||||
|
GtkTooltipWindow *window = GTK_TOOLTIP_WINDOW (widget);
|
||||||
|
GtkWidget *child;
|
||||||
|
|
||||||
|
gtk_widget_remove_surface_transform_changed_callback (window->relative_to,
|
||||||
|
window->surface_transform_changed_cb);
|
||||||
|
window->surface_transform_changed_cb = 0;
|
||||||
|
|
||||||
|
GTK_WIDGET_CLASS (gtk_tooltip_window_parent_class)->unmap (widget);
|
||||||
|
gdk_surface_hide (window->surface);
|
||||||
|
|
||||||
|
child = gtk_bin_get_child (GTK_BIN (widget));
|
||||||
|
if (child != NULL)
|
||||||
|
gtk_widget_unmap (child);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_tooltip_window_measure (GtkWidget *widget,
|
||||||
|
GtkOrientation orientation,
|
||||||
|
int for_size,
|
||||||
|
int *minimum,
|
||||||
|
int *natural,
|
||||||
|
int *minimum_baseline,
|
||||||
|
int *natural_baseline)
|
||||||
|
{
|
||||||
|
GtkWidget *child;
|
||||||
|
|
||||||
|
child = gtk_bin_get_child (GTK_BIN (widget));
|
||||||
|
|
||||||
|
if (child)
|
||||||
|
gtk_widget_measure (child,
|
||||||
|
orientation, for_size,
|
||||||
|
minimum, natural,
|
||||||
|
minimum_baseline, natural_baseline);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_tooltip_window_size_allocate (GtkWidget *widget,
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
int baseline)
|
||||||
|
{
|
||||||
|
GtkTooltipWindow *window = GTK_TOOLTIP_WINDOW (widget);
|
||||||
|
GtkWidget *child;
|
||||||
|
|
||||||
|
gtk_tooltip_window_move_resize (window);
|
||||||
|
|
||||||
|
child = gtk_bin_get_child (GTK_BIN (window));
|
||||||
|
|
||||||
|
if (child)
|
||||||
|
gtk_widget_allocate (child, width, height, baseline, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_tooltip_window_show (GtkWidget *widget)
|
||||||
|
{
|
||||||
|
_gtk_widget_set_visible_flag (widget, TRUE);
|
||||||
|
gtk_css_node_validate (gtk_widget_get_css_node (widget));
|
||||||
|
gtk_widget_realize (widget);
|
||||||
|
gtk_tooltip_window_native_check_resize (GTK_NATIVE (widget));
|
||||||
|
gtk_widget_map (widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_tooltip_window_hide (GtkWidget *widget)
|
||||||
|
{
|
||||||
|
_gtk_widget_set_visible_flag (widget, FALSE);
|
||||||
|
gtk_widget_unmap (widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void size_changed (GtkWidget *widget,
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
int baseline,
|
||||||
|
GtkTooltipWindow *window);
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_tooltip_window_dispose (GObject *object)
|
||||||
|
{
|
||||||
|
GtkTooltipWindow *window = GTK_TOOLTIP_WINDOW (object);
|
||||||
|
|
||||||
|
if (window->relative_to)
|
||||||
|
{
|
||||||
|
g_signal_handlers_disconnect_by_func (window->relative_to, size_changed, window);
|
||||||
|
gtk_widget_unparent (GTK_WIDGET (window));
|
||||||
|
}
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gtk_tooltip_window_parent_class)->dispose (object);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gtk_tooltip_window_class_init (GtkTooltipWindowClass *klass)
|
gtk_tooltip_window_class_init (GtkTooltipWindowClass *klass)
|
||||||
{
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->dispose = gtk_tooltip_window_dispose;
|
||||||
|
widget_class->realize = gtk_tooltip_window_realize;
|
||||||
|
widget_class->unrealize = gtk_tooltip_window_unrealize;
|
||||||
|
widget_class->map = gtk_tooltip_window_map;
|
||||||
|
widget_class->unmap = gtk_tooltip_window_unmap;
|
||||||
|
widget_class->measure = gtk_tooltip_window_measure;
|
||||||
|
widget_class->size_allocate = gtk_tooltip_window_size_allocate;
|
||||||
|
widget_class->show = gtk_tooltip_window_show;
|
||||||
|
widget_class->hide = gtk_tooltip_window_hide;
|
||||||
|
|
||||||
gtk_widget_class_set_css_name (widget_class, I_("tooltip"));
|
gtk_widget_class_set_css_name (widget_class, I_("tooltip"));
|
||||||
gtk_widget_class_set_accessible_role (widget_class, ATK_ROLE_TOOL_TIP);
|
gtk_widget_class_set_accessible_role (widget_class, ATK_ROLE_TOOL_TIP);
|
||||||
gtk_widget_class_set_template_from_resource (widget_class, "/org/gtk/libgtk/ui/gtktooltipwindow.ui");
|
gtk_widget_class_set_template_from_resource (widget_class, "/org/gtk/libgtk/ui/gtktooltipwindow.ui");
|
||||||
@ -68,24 +420,20 @@ gtk_tooltip_window_class_init (GtkTooltipWindowClass *klass)
|
|||||||
gtk_widget_class_bind_template_child (widget_class, GtkTooltipWindow, box);
|
gtk_widget_class_bind_template_child (widget_class, GtkTooltipWindow, box);
|
||||||
gtk_widget_class_bind_template_child (widget_class, GtkTooltipWindow, image);
|
gtk_widget_class_bind_template_child (widget_class, GtkTooltipWindow, image);
|
||||||
gtk_widget_class_bind_template_child (widget_class, GtkTooltipWindow, label);
|
gtk_widget_class_bind_template_child (widget_class, GtkTooltipWindow, label);
|
||||||
|
|
||||||
|
gtk_widget_class_set_css_name (widget_class, "tooltip");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gtk_tooltip_window_init (GtkTooltipWindow *self)
|
gtk_tooltip_window_init (GtkTooltipWindow *self)
|
||||||
{
|
{
|
||||||
GtkWindow *window = GTK_WINDOW (self);
|
|
||||||
|
|
||||||
gtk_widget_init_template (GTK_WIDGET (self));
|
gtk_widget_init_template (GTK_WIDGET (self));
|
||||||
|
|
||||||
_gtk_window_request_csd (window);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GtkWidget *
|
GtkWidget *
|
||||||
gtk_tooltip_window_new (void)
|
gtk_tooltip_window_new (void)
|
||||||
{
|
{
|
||||||
return g_object_new (GTK_TYPE_TOOLTIP_WINDOW,
|
return g_object_new (GTK_TYPE_TOOLTIP_WINDOW, NULL);
|
||||||
"type", GTK_WINDOW_POPUP,
|
|
||||||
NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -191,5 +539,65 @@ gtk_tooltip_window_set_custom_widget (GtkTooltipWindow *window,
|
|||||||
|
|
||||||
gtk_container_add (GTK_CONTAINER (window->box), custom_widget);
|
gtk_container_add (GTK_CONTAINER (window->box), custom_widget);
|
||||||
gtk_widget_show (custom_widget);
|
gtk_widget_show (custom_widget);
|
||||||
|
gtk_widget_hide (window->image);
|
||||||
|
gtk_widget_hide (window->label);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
size_changed (GtkWidget *widget,
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
int baseline,
|
||||||
|
GtkTooltipWindow *window)
|
||||||
|
{
|
||||||
|
gtk_native_check_resize (GTK_NATIVE (window));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gtk_tooltip_window_set_relative_to (GtkTooltipWindow *window,
|
||||||
|
GtkWidget *relative_to)
|
||||||
|
{
|
||||||
|
if (window->relative_to == relative_to)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_object_ref (window);
|
||||||
|
|
||||||
|
if (window->relative_to)
|
||||||
|
{
|
||||||
|
g_signal_handlers_disconnect_by_func (window->relative_to, size_changed, window);
|
||||||
|
gtk_widget_unparent (GTK_WIDGET (window));
|
||||||
|
}
|
||||||
|
|
||||||
|
window->relative_to = relative_to;
|
||||||
|
|
||||||
|
if (window->relative_to)
|
||||||
|
{
|
||||||
|
g_signal_connect (window->relative_to, "size-allocate", G_CALLBACK (size_changed), window);
|
||||||
|
gtk_css_node_set_parent (gtk_widget_get_css_node (GTK_WIDGET (window)),
|
||||||
|
gtk_widget_get_css_node (relative_to));
|
||||||
|
gtk_widget_set_parent (GTK_WIDGET (window), relative_to);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_unref (window);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gtk_tooltip_window_position (GtkTooltipWindow *window,
|
||||||
|
GdkRectangle *rect,
|
||||||
|
GdkGravity rect_anchor,
|
||||||
|
GdkGravity surface_anchor,
|
||||||
|
GdkAnchorHints anchor_hints,
|
||||||
|
int dx,
|
||||||
|
int dy)
|
||||||
|
{
|
||||||
|
window->rect = *rect;
|
||||||
|
window->rect_anchor = rect_anchor;
|
||||||
|
window->surface_anchor = surface_anchor;
|
||||||
|
window->anchor_hints = anchor_hints;
|
||||||
|
window->dx = dx;
|
||||||
|
window->dy = dy;
|
||||||
|
|
||||||
|
move_to_rect (window);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -49,6 +49,15 @@ void gtk_tooltip_window_set_image_icon_from_gicon (GtkTooltipWindo
|
|||||||
GIcon *gicon);
|
GIcon *gicon);
|
||||||
void gtk_tooltip_window_set_custom_widget (GtkTooltipWindow *window,
|
void gtk_tooltip_window_set_custom_widget (GtkTooltipWindow *window,
|
||||||
GtkWidget *custom_widget);
|
GtkWidget *custom_widget);
|
||||||
|
void gtk_tooltip_window_set_relative_to (GtkTooltipWindow *window,
|
||||||
|
GtkWidget *relative_to);
|
||||||
|
void gtk_tooltip_window_position (GtkTooltipWindow *window,
|
||||||
|
GdkRectangle *rect,
|
||||||
|
GdkGravity rect_anchor,
|
||||||
|
GdkGravity surface_anchor,
|
||||||
|
GdkAnchorHints anchor_hints,
|
||||||
|
int dx,
|
||||||
|
int dy);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
@ -726,7 +726,6 @@ static GQuark quark_input_shape_info = 0;
|
|||||||
static GQuark quark_pango_context = 0;
|
static GQuark quark_pango_context = 0;
|
||||||
static GQuark quark_mnemonic_labels = 0;
|
static GQuark quark_mnemonic_labels = 0;
|
||||||
static GQuark quark_tooltip_markup = 0;
|
static GQuark quark_tooltip_markup = 0;
|
||||||
static GQuark quark_tooltip_window = 0;
|
|
||||||
static GQuark quark_size_groups = 0;
|
static GQuark quark_size_groups = 0;
|
||||||
static GQuark quark_auto_children = 0;
|
static GQuark quark_auto_children = 0;
|
||||||
static GQuark quark_widget_path = 0;
|
static GQuark quark_widget_path = 0;
|
||||||
@ -885,7 +884,6 @@ gtk_widget_class_init (GtkWidgetClass *klass)
|
|||||||
quark_pango_context = g_quark_from_static_string ("gtk-pango-context");
|
quark_pango_context = g_quark_from_static_string ("gtk-pango-context");
|
||||||
quark_mnemonic_labels = g_quark_from_static_string ("gtk-mnemonic-labels");
|
quark_mnemonic_labels = g_quark_from_static_string ("gtk-mnemonic-labels");
|
||||||
quark_tooltip_markup = g_quark_from_static_string ("gtk-tooltip-markup");
|
quark_tooltip_markup = g_quark_from_static_string ("gtk-tooltip-markup");
|
||||||
quark_tooltip_window = g_quark_from_static_string ("gtk-tooltip-window");
|
|
||||||
quark_size_groups = g_quark_from_static_string ("gtk-widget-size-groups");
|
quark_size_groups = g_quark_from_static_string ("gtk-widget-size-groups");
|
||||||
quark_auto_children = g_quark_from_static_string ("gtk-widget-auto-children");
|
quark_auto_children = g_quark_from_static_string ("gtk-widget-auto-children");
|
||||||
quark_widget_path = g_quark_from_static_string ("gtk-widget-path");
|
quark_widget_path = g_quark_from_static_string ("gtk-widget-path");
|
||||||
@ -2157,10 +2155,8 @@ gtk_widget_set_property (GObject *object,
|
|||||||
|
|
||||||
switch (prop_id)
|
switch (prop_id)
|
||||||
{
|
{
|
||||||
gboolean tmp;
|
|
||||||
gchar *tooltip_markup;
|
gchar *tooltip_markup;
|
||||||
const gchar *tooltip_text;
|
const gchar *tooltip_text;
|
||||||
GtkWindow *tooltip_window;
|
|
||||||
|
|
||||||
case PROP_NAME:
|
case PROP_NAME:
|
||||||
gtk_widget_set_name (widget, g_value_get_string (value));
|
gtk_widget_set_name (widget, g_value_get_string (value));
|
||||||
@ -2204,7 +2200,6 @@ gtk_widget_set_property (GObject *object,
|
|||||||
gtk_widget_set_has_tooltip (widget, g_value_get_boolean (value));
|
gtk_widget_set_has_tooltip (widget, g_value_get_boolean (value));
|
||||||
break;
|
break;
|
||||||
case PROP_TOOLTIP_MARKUP:
|
case PROP_TOOLTIP_MARKUP:
|
||||||
tooltip_window = g_object_get_qdata (object, quark_tooltip_window);
|
|
||||||
tooltip_markup = g_value_dup_string (value);
|
tooltip_markup = g_value_dup_string (value);
|
||||||
|
|
||||||
/* Treat an empty string as a NULL string,
|
/* Treat an empty string as a NULL string,
|
||||||
@ -2219,14 +2214,11 @@ gtk_widget_set_property (GObject *object,
|
|||||||
g_object_set_qdata_full (object, quark_tooltip_markup,
|
g_object_set_qdata_full (object, quark_tooltip_markup,
|
||||||
tooltip_markup, g_free);
|
tooltip_markup, g_free);
|
||||||
|
|
||||||
tmp = (tooltip_window != NULL || tooltip_markup != NULL);
|
gtk_widget_set_has_tooltip (widget, tooltip_markup != NULL);
|
||||||
gtk_widget_set_has_tooltip (widget, tmp);
|
|
||||||
if (_gtk_widget_get_visible (widget))
|
if (_gtk_widget_get_visible (widget))
|
||||||
gtk_widget_trigger_tooltip_query (widget);
|
gtk_widget_trigger_tooltip_query (widget);
|
||||||
break;
|
break;
|
||||||
case PROP_TOOLTIP_TEXT:
|
case PROP_TOOLTIP_TEXT:
|
||||||
tooltip_window = g_object_get_qdata (object, quark_tooltip_window);
|
|
||||||
|
|
||||||
tooltip_text = g_value_get_string (value);
|
tooltip_text = g_value_get_string (value);
|
||||||
|
|
||||||
/* Treat an empty string as a NULL string,
|
/* Treat an empty string as a NULL string,
|
||||||
@ -2240,8 +2232,7 @@ gtk_widget_set_property (GObject *object,
|
|||||||
g_object_set_qdata_full (object, quark_tooltip_markup,
|
g_object_set_qdata_full (object, quark_tooltip_markup,
|
||||||
tooltip_markup, g_free);
|
tooltip_markup, g_free);
|
||||||
|
|
||||||
tmp = (tooltip_window != NULL || tooltip_markup != NULL);
|
gtk_widget_set_has_tooltip (widget, tooltip_markup != NULL);
|
||||||
gtk_widget_set_has_tooltip (widget, tmp);
|
|
||||||
if (_gtk_widget_get_visible (widget))
|
if (_gtk_widget_get_visible (widget))
|
||||||
gtk_widget_trigger_tooltip_query (widget);
|
gtk_widget_trigger_tooltip_query (widget);
|
||||||
break;
|
break;
|
||||||
@ -10649,60 +10640,6 @@ gtk_widget_remove_mnemonic_label (GtkWidget *widget,
|
|||||||
new_list, (GDestroyNotify) g_slist_free);
|
new_list, (GDestroyNotify) g_slist_free);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* gtk_widget_set_tooltip_window:
|
|
||||||
* @widget: a #GtkWidget
|
|
||||||
* @custom_window: (allow-none): a #GtkWindow, or %NULL
|
|
||||||
*
|
|
||||||
* Replaces the default window used for displaying
|
|
||||||
* tooltips with @custom_window. GTK+ will take care of showing and
|
|
||||||
* hiding @custom_window at the right moment, to behave likewise as
|
|
||||||
* the default tooltip window. If @custom_window is %NULL, the default
|
|
||||||
* tooltip window will be used.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
gtk_widget_set_tooltip_window (GtkWidget *widget,
|
|
||||||
GtkWindow *custom_window)
|
|
||||||
{
|
|
||||||
gboolean has_tooltip;
|
|
||||||
gchar *tooltip_markup;
|
|
||||||
|
|
||||||
g_return_if_fail (GTK_IS_WIDGET (widget));
|
|
||||||
g_return_if_fail (custom_window == NULL || GTK_IS_WINDOW (custom_window));
|
|
||||||
|
|
||||||
tooltip_markup = g_object_get_qdata (G_OBJECT (widget), quark_tooltip_markup);
|
|
||||||
|
|
||||||
if (custom_window)
|
|
||||||
g_object_ref (custom_window);
|
|
||||||
|
|
||||||
g_object_set_qdata_full (G_OBJECT (widget), quark_tooltip_window,
|
|
||||||
custom_window, g_object_unref);
|
|
||||||
|
|
||||||
has_tooltip = (custom_window != NULL || tooltip_markup != NULL);
|
|
||||||
gtk_widget_set_has_tooltip (widget, has_tooltip);
|
|
||||||
|
|
||||||
if (has_tooltip && _gtk_widget_get_visible (widget))
|
|
||||||
gtk_widget_trigger_tooltip_query (widget);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* gtk_widget_get_tooltip_window:
|
|
||||||
* @widget: a #GtkWidget
|
|
||||||
*
|
|
||||||
* Returns the #GtkWindow of the current tooltip. This can be the
|
|
||||||
* GtkWindow created by default, or the custom tooltip window set
|
|
||||||
* using gtk_widget_set_tooltip_window().
|
|
||||||
*
|
|
||||||
* Returns: (transfer none): The #GtkWindow of the current tooltip.
|
|
||||||
*/
|
|
||||||
GtkWindow *
|
|
||||||
gtk_widget_get_tooltip_window (GtkWidget *widget)
|
|
||||||
{
|
|
||||||
g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
|
|
||||||
|
|
||||||
return g_object_get_qdata (G_OBJECT (widget), quark_tooltip_window);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gtk_widget_trigger_tooltip_query:
|
* gtk_widget_trigger_tooltip_query:
|
||||||
* @widget: a #GtkWidget
|
* @widget: a #GtkWidget
|
||||||
|
@ -778,11 +778,6 @@ GDK_AVAILABLE_IN_ALL
|
|||||||
void gtk_widget_remove_mnemonic_label (GtkWidget *widget,
|
void gtk_widget_remove_mnemonic_label (GtkWidget *widget,
|
||||||
GtkWidget *label);
|
GtkWidget *label);
|
||||||
|
|
||||||
GDK_AVAILABLE_IN_ALL
|
|
||||||
void gtk_widget_set_tooltip_window (GtkWidget *widget,
|
|
||||||
GtkWindow *custom_window);
|
|
||||||
GDK_AVAILABLE_IN_ALL
|
|
||||||
GtkWindow *gtk_widget_get_tooltip_window (GtkWidget *widget);
|
|
||||||
GDK_AVAILABLE_IN_ALL
|
GDK_AVAILABLE_IN_ALL
|
||||||
void gtk_widget_trigger_tooltip_query (GtkWidget *widget);
|
void gtk_widget_trigger_tooltip_query (GtkWidget *widget);
|
||||||
GDK_AVAILABLE_IN_ALL
|
GDK_AVAILABLE_IN_ALL
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<interface domain="gtk40">
|
<interface domain="gtk40">
|
||||||
<template class="GtkTooltipWindow" parent="GtkWindow">
|
<template class="GtkTooltipWindow" parent="GtkBin">
|
||||||
<property name="resizable">0</property>
|
<style>
|
||||||
<property name="type-hint">tooltip</property>
|
<class name="background"/>
|
||||||
|
</style>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkBox" id="box">
|
<object class="GtkBox" id="box">
|
||||||
<property name="spacing">6</property>
|
<property name="spacing">6</property>
|
||||||
|
@ -69,17 +69,6 @@ query_tooltip_cb (GtkWidget *widget,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
|
||||||
query_tooltip_custom_cb (GtkWidget *widget,
|
|
||||||
gint x,
|
|
||||||
gint y,
|
|
||||||
gboolean keyboard_tip,
|
|
||||||
GtkTooltip *tooltip,
|
|
||||||
gpointer data)
|
|
||||||
{
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
query_tooltip_text_view_cb (GtkWidget *widget,
|
query_tooltip_text_view_cb (GtkWidget *widget,
|
||||||
gint x,
|
gint x,
|
||||||
@ -278,11 +267,10 @@ main (int argc, char *argv[])
|
|||||||
GtkWidget *box;
|
GtkWidget *box;
|
||||||
GtkWidget *drawing_area;
|
GtkWidget *drawing_area;
|
||||||
GtkWidget *button;
|
GtkWidget *button;
|
||||||
GtkWidget *label;
|
|
||||||
GtkWidget *tooltip;
|
GtkWidget *tooltip;
|
||||||
|
GtkWidget *popover;
|
||||||
GtkWidget *tooltip_window;
|
GtkWidget *box2;
|
||||||
GtkWidget *tooltip_button;
|
GtkWidget *custom;
|
||||||
|
|
||||||
GtkWidget *tree_view;
|
GtkWidget *tree_view;
|
||||||
GtkTreeViewColumn *column;
|
GtkTreeViewColumn *column;
|
||||||
@ -352,25 +340,6 @@ main (int argc, char *argv[])
|
|||||||
g_assert (g_str_equal ("<b>Another</b> Label tooltip", markup));
|
g_assert (g_str_equal ("<b>Another</b> Label tooltip", markup));
|
||||||
g_free (text); g_free (markup);
|
g_free (text); g_free (markup);
|
||||||
|
|
||||||
/* Another one, with a custom tooltip window */
|
|
||||||
button = gtk_check_button_new_with_label ("This one has a custom tooltip window!");
|
|
||||||
gtk_container_add (GTK_CONTAINER (box), button);
|
|
||||||
|
|
||||||
tooltip_window = gtk_window_new (GTK_WINDOW_POPUP);
|
|
||||||
tooltip_button = gtk_label_new ("blaat!");
|
|
||||||
gtk_container_add (GTK_CONTAINER (tooltip_window), tooltip_button);
|
|
||||||
gtk_widget_show (tooltip_button);
|
|
||||||
|
|
||||||
gtk_widget_set_tooltip_window (button, GTK_WINDOW (tooltip_window));
|
|
||||||
gtk_window_set_type_hint (GTK_WINDOW (tooltip_window),
|
|
||||||
GDK_SURFACE_TYPE_HINT_TOOLTIP);
|
|
||||||
gtk_window_set_transient_for (GTK_WINDOW (tooltip_window),
|
|
||||||
GTK_WINDOW (window));
|
|
||||||
|
|
||||||
g_signal_connect (button, "query-tooltip",
|
|
||||||
G_CALLBACK (query_tooltip_custom_cb), NULL);
|
|
||||||
g_object_set (button, "has-tooltip", TRUE, NULL);
|
|
||||||
|
|
||||||
/* An insensitive button */
|
/* An insensitive button */
|
||||||
button = gtk_button_new_with_label ("This one is insensitive");
|
button = gtk_button_new_with_label ("This one is insensitive");
|
||||||
gtk_widget_set_sensitive (button, FALSE);
|
gtk_widget_set_sensitive (button, FALSE);
|
||||||
@ -435,21 +404,34 @@ main (int argc, char *argv[])
|
|||||||
G_CALLBACK (query_tooltip_drawing_area_cb), NULL);
|
G_CALLBACK (query_tooltip_drawing_area_cb), NULL);
|
||||||
gtk_container_add (GTK_CONTAINER (box), drawing_area);
|
gtk_container_add (GTK_CONTAINER (box), drawing_area);
|
||||||
|
|
||||||
button = gtk_label_new ("Custom tooltip I");
|
button = gtk_menu_button_new ();
|
||||||
label = gtk_label_new ("See, custom");
|
gtk_widget_set_halign (button, GTK_ALIGN_CENTER);
|
||||||
g_object_ref_sink (label);
|
gtk_menu_button_set_label (GTK_MENU_BUTTON (button), "Custom tooltip I");
|
||||||
g_object_set (button, "has-tooltip", TRUE, NULL);
|
|
||||||
g_signal_connect (button, "query-tooltip",
|
|
||||||
G_CALLBACK (query_tooltip_label_cb), label);
|
|
||||||
gtk_container_add (GTK_CONTAINER (box), button);
|
gtk_container_add (GTK_CONTAINER (box), button);
|
||||||
|
popover = gtk_popover_new (NULL);
|
||||||
|
gtk_menu_button_set_popover (GTK_MENU_BUTTON (button), popover);
|
||||||
|
box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||||||
|
gtk_container_add (GTK_CONTAINER (popover), box2);
|
||||||
|
|
||||||
|
button = gtk_label_new ("Hidden here");
|
||||||
|
custom = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
|
||||||
|
gtk_container_add (GTK_CONTAINER (custom), gtk_label_new ("See, custom"));
|
||||||
|
gtk_container_add (GTK_CONTAINER (custom), g_object_new (GTK_TYPE_SPINNER, "active", TRUE, NULL));
|
||||||
|
g_object_ref_sink (custom);
|
||||||
|
g_object_set (button, "has-tooltip", TRUE, NULL);
|
||||||
|
gtk_container_add (GTK_CONTAINER (box2), button);
|
||||||
|
g_signal_connect (button, "query-tooltip",
|
||||||
|
G_CALLBACK (query_tooltip_label_cb), custom);
|
||||||
|
|
||||||
button = gtk_label_new ("Custom tooltip II");
|
button = gtk_label_new ("Custom tooltip II");
|
||||||
label = gtk_label_new ("See, custom, too");
|
custom = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
|
||||||
g_object_ref_sink (label);
|
gtk_container_add (GTK_CONTAINER (custom), gtk_label_new ("See, custom too"));
|
||||||
|
gtk_container_add (GTK_CONTAINER (custom), g_object_new (GTK_TYPE_SPINNER, "active", TRUE, NULL));
|
||||||
|
g_object_ref_sink (custom);
|
||||||
g_object_set (button, "has-tooltip", TRUE, NULL);
|
g_object_set (button, "has-tooltip", TRUE, NULL);
|
||||||
gtk_container_add (GTK_CONTAINER (box), button);
|
|
||||||
g_signal_connect (button, "query-tooltip",
|
g_signal_connect (button, "query-tooltip",
|
||||||
G_CALLBACK (query_tooltip_label_cb), label);
|
G_CALLBACK (query_tooltip_label_cb), custom);
|
||||||
|
gtk_container_add (GTK_CONTAINER (box), button);
|
||||||
|
|
||||||
/* Done! */
|
/* Done! */
|
||||||
gtk_widget_show (window);
|
gtk_widget_show (window);
|
||||||
|
Loading…
Reference in New Issue
Block a user