Bug Summary

File:ctk/ctktooltip.c
Warning:line 837, column 24
2nd function call argument is an uninitialized value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name ctktooltip.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/ctk -resource-dir /usr/lib/llvm-16/lib/clang/16 -D HAVE_CONFIG_H -I . -I .. -D G_LOG_DOMAIN="Ctk" -D G_LOG_USE_STRUCTURED=1 -D CTK_VERSION="3.25.5" -D CTK_BINARY_VERSION="3.0.0" -D CTK_COMPILATION -D CTK_PRINT_BACKEND_ENABLE_UNSUPPORTED -D CTK_LIBDIR="/usr/lib" -D CTK_LOCALEDIR="/usr/share/locale" -D CTK_DATADIR="/usr/share" -D CTK_DATA_PREFIX="/usr" -D CTK_SYSCONFDIR="/usr/etc" -D CTK_HOST="x86_64-pc-linux-gnu" -D CTK_PRINT_BACKENDS="file,cups" -D X11_DATA_PREFIX="/usr" -D ISO_CODES_PREFIX="" -I .. -I ../ctk -I .. -I ../cdk -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -D G_ENABLE_DEBUG -D G_ENABLE_CONSISTENCY_CHECKS -D GLIB_MIN_REQUIRED_VERSION=GLIB_VERSION_2_66 -D GLIB_MAX_ALLOWED_VERSION=GLIB_VERSION_2_66 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/atk-1.0 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/pango-1.0 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -D PIC -internal-isystem /usr/lib/llvm-16/lib/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir=/rootdir/ctk -ferror-limit 19 -fvisibility=hidden -fgnuc-version=4.2.1 -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2024-09-19-171502-43637-1 -x c ctktooltip.c
1/* ctktooltip.c
2 *
3 * Copyright (C) 2006-2007 Imendio AB
4 * Contact: Kristian Rietveld <kris@imendio.com>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include "config.h"
21
22#include "ctktooltip.h"
23#include "ctktooltipprivate.h"
24
25#include <math.h>
26#include <string.h>
27
28#include "ctkintl.h"
29#include "ctkwindow.h"
30#include "ctkmain.h"
31#include "ctklabel.h"
32#include "ctkimage.h"
33#include "ctkbox.h"
34#include "ctksettings.h"
35#include "ctksizerequest.h"
36#include "ctkstylecontext.h"
37#include "ctktooltipwindowprivate.h"
38#include "ctkwindowprivate.h"
39#include "ctkwidgetprivate.h"
40#include "ctkaccessible.h"
41
42#ifdef CDK_WINDOWING_WAYLAND
43#include "wayland/cdkwayland.h"
44#endif
45
46
47/**
48 * SECTION:ctktooltip
49 * @Short_description: Add tips to your widgets
50 * @Title: CtkTooltip
51 *
52 * Basic tooltips can be realized simply by using ctk_widget_set_tooltip_text()
53 * or ctk_widget_set_tooltip_markup() without any explicit tooltip object.
54 *
55 * When you need a tooltip with a little more fancy contents, like adding an
56 * image, or you want the tooltip to have different contents per #CtkTreeView
57 * row or cell, you will have to do a little more work:
58 *
59 * - Set the #CtkWidget:has-tooltip property to %TRUE, this will make CTK+
60 * monitor the widget for motion and related events which are needed to
61 * determine when and where to show a tooltip.
62 *
63 * - Connect to the #CtkWidget::query-tooltip signal. This signal will be
64 * emitted when a tooltip is supposed to be shown. One of the arguments passed
65 * to the signal handler is a CtkTooltip object. This is the object that we
66 * are about to display as a tooltip, and can be manipulated in your callback
67 * using functions like ctk_tooltip_set_icon(). There are functions for setting
68 * the tooltip’s markup, setting an image from a named icon, or even putting in
69 * a custom widget.
70 *
71 * Return %TRUE from your query-tooltip handler. This causes the tooltip to be
72 * show. If you return %FALSE, it will not be shown.
73 *
74 * In the probably rare case where you want to have even more control over the
75 * tooltip that is about to be shown, you can set your own #CtkWindow which
76 * will be used as tooltip window. This works as follows:
77 *
78 * - Set #CtkWidget:has-tooltip and connect to #CtkWidget::query-tooltip as before.
79 * Use ctk_widget_set_tooltip_window() to set a #CtkWindow created by you as
80 * tooltip window.
81 *
82 * - In the #CtkWidget::query-tooltip callback you can access your window using
83 * ctk_widget_get_tooltip_window() and manipulate as you wish. The semantics of
84 * the return value are exactly as before, return %TRUE to show the window,
85 * %FALSE to not show it.
86 */
87
88
89#define HOVER_TIMEOUT500 500
90#define BROWSE_TIMEOUT60 60
91#define BROWSE_DISABLE_TIMEOUT500 500
92
93#define CTK_TOOLTIP_CLASS(klass)((((CtkTooltipClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((klass)), ((ctk_tooltip_get_type ()))))))
(G_TYPE_CHECK_CLASS_CAST ((klass), CTK_TYPE_TOOLTIP, CtkTooltipClass)(((CtkTooltipClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((klass)), ((ctk_tooltip_get_type ())))))
)
94#define CTK_IS_TOOLTIP_CLASS(klass)(((__extension__ ({ GTypeClass *__class = (GTypeClass*) ((klass
)); GType __t = ((ctk_tooltip_get_type ())); gboolean __r; if
(!__class) __r = (0); else if (__class->g_type == __t) __r
= (!(0)); else __r = g_type_check_class_is_a (__class, __t);
__r; }))))
(G_TYPE_CHECK_CLASS_TYPE ((klass), CTK_TYPE_TOOLTIP)((__extension__ ({ GTypeClass *__class = (GTypeClass*) ((klass
)); GType __t = ((ctk_tooltip_get_type ())); gboolean __r; if
(!__class) __r = (0); else if (__class->g_type == __t) __r
= (!(0)); else __r = g_type_check_class_is_a (__class, __t);
__r; })))
)
95#define CTK_TOOLTIP_GET_CLASS(obj)((((CtkTooltipClass*) (((GTypeInstance*) ((obj)))->g_class
))))
(G_TYPE_INSTANCE_GET_CLASS ((obj), CTK_TYPE_TOOLTIP, CtkTooltipClass)(((CtkTooltipClass*) (((GTypeInstance*) ((obj)))->g_class)
))
)
96
97typedef struct _CtkTooltipClass CtkTooltipClass;
98
99struct _CtkTooltip
100{
101 GObject parent_instance;
102
103 CtkWidget *window;
104 CtkWidget *box;
105 CtkWidget *image;
106 CtkWidget *label;
107 CtkWidget *custom_widget;
108
109 CtkWindow *current_window;
110 CtkWidget *keyboard_widget;
111
112 CtkWidget *tooltip_widget;
113
114 CdkWindow *last_window;
115
116 guint timeout_id;
117 guint browse_mode_timeout_id;
118
119 CdkRectangle tip_area;
120
121 guint browse_mode_enabled : 1;
122 guint keyboard_mode_enabled : 1;
123 guint tip_area_set : 1;
124 guint custom_was_reset : 1;
125};
126
127struct _CtkTooltipClass
128{
129 GObjectClass parent_class;
130};
131
132#define CTK_TOOLTIP_VISIBLE(tooltip)((tooltip)->current_window && ctk_widget_get_visible
(((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((tooltip)->current_window)), ((ctk_widget_get_type ()
))))))))
((tooltip)->current_window && ctk_widget_get_visible (CTK_WIDGET((tooltip)->current_window)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((tooltip)->current_window)), ((ctk_widget_get_type ()
))))))
))
133
134
135static void ctk_tooltip_class_init (CtkTooltipClass *klass);
136static void ctk_tooltip_init (CtkTooltip *tooltip);
137static void ctk_tooltip_dispose (GObject *object);
138
139static void ctk_tooltip_window_hide (CtkWidget *widget,
140 gpointer user_data);
141static void ctk_tooltip_display_closed (CdkDisplay *display,
142 gboolean was_error,
143 CtkTooltip *tooltip);
144static void ctk_tooltip_set_last_window (CtkTooltip *tooltip,
145 CdkWindow *window);
146
147static void ctk_tooltip_handle_event_internal (CdkEvent *event);
148
149static inline GQuark tooltip_quark (void)
150{
151 static GQuark quark;
152
153 if G_UNLIKELY (quark == 0)(quark == 0)
154 quark = g_quark_from_static_string ("cdk-display-current-tooltip");
155 return quark;
156}
157
158#define quark_current_tooltiptooltip_quark() tooltip_quark()
159
160G_DEFINE_TYPE (CtkTooltip, ctk_tooltip, G_TYPE_OBJECT)static void ctk_tooltip_init (CtkTooltip *self); static void ctk_tooltip_class_init
(CtkTooltipClass *klass); static GType ctk_tooltip_get_type_once
(void); static gpointer ctk_tooltip_parent_class = ((void*)0
); static gint CtkTooltip_private_offset; static void ctk_tooltip_class_intern_init
(gpointer klass) { ctk_tooltip_parent_class = g_type_class_peek_parent
(klass); if (CtkTooltip_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CtkTooltip_private_offset); ctk_tooltip_class_init
((CtkTooltipClass*) klass); } __attribute__ ((__unused__)) static
inline gpointer ctk_tooltip_get_instance_private (CtkTooltip
*self) { return (((gpointer) ((guint8*) (self) + (glong) (CtkTooltip_private_offset
)))); } GType ctk_tooltip_get_type (void) { static GType static_g_define_type_id
= 0; if ((__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); (void
) (0 ? (gpointer) * (&static_g_define_type_id) : ((void*)
0)); (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= ctk_tooltip_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType ctk_tooltip_get_type_once (void)
{ GType g_define_type_id = g_type_register_static_simple (((
GType) ((20) << (2))), g_intern_static_string ("CtkTooltip"
), sizeof (CtkTooltipClass), (GClassInitFunc)(void (*)(void))
ctk_tooltip_class_intern_init, sizeof (CtkTooltip), (GInstanceInitFunc
)(void (*)(void)) ctk_tooltip_init, (GTypeFlags) 0); { {{};} }
return g_define_type_id; }
;
161
162static void
163ctk_tooltip_class_init (CtkTooltipClass *klass)
164{
165 GObjectClass *object_class;
166
167 object_class = G_OBJECT_CLASS (klass)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((klass)), (((GType) ((20) << (2))))))))
;
168
169 object_class->dispose = ctk_tooltip_dispose;
170}
171
172static void
173ctk_tooltip_init (CtkTooltip *tooltip)
174{
175 tooltip->timeout_id = 0;
176 tooltip->browse_mode_timeout_id = 0;
177
178 tooltip->browse_mode_enabled = FALSE(0);
179 tooltip->keyboard_mode_enabled = FALSE(0);
180
181 tooltip->current_window = NULL((void*)0);
182 tooltip->keyboard_widget = NULL((void*)0);
183
184 tooltip->tooltip_widget = NULL((void*)0);
185
186 tooltip->last_window = NULL((void*)0);
187
188 tooltip->window = ctk_tooltip_window_new ();
189 g_signal_connect (tooltip->window, "hide",g_signal_connect_data ((tooltip->window), ("hide"), (((GCallback
) (ctk_tooltip_window_hide))), (tooltip), ((void*)0), (GConnectFlags
) 0)
190 G_CALLBACK (ctk_tooltip_window_hide),g_signal_connect_data ((tooltip->window), ("hide"), (((GCallback
) (ctk_tooltip_window_hide))), (tooltip), ((void*)0), (GConnectFlags
) 0)
191 tooltip)g_signal_connect_data ((tooltip->window), ("hide"), (((GCallback
) (ctk_tooltip_window_hide))), (tooltip), ((void*)0), (GConnectFlags
) 0)
;
192}
193
194static void
195ctk_tooltip_dispose (GObject *object)
196{
197 CtkTooltip *tooltip = CTK_TOOLTIP (object)((((CtkTooltip*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((ctk_tooltip_get_type ()))))))
;
198
199 if (tooltip->timeout_id)
200 {
201 g_source_remove (tooltip->timeout_id);
202 tooltip->timeout_id = 0;
203 }
204
205 if (tooltip->browse_mode_timeout_id)
206 {
207 g_source_remove (tooltip->browse_mode_timeout_id);
208 tooltip->browse_mode_timeout_id = 0;
209 }
210
211 ctk_tooltip_set_custom (tooltip, NULL((void*)0));
212 ctk_tooltip_set_last_window (tooltip, NULL((void*)0));
213
214 if (tooltip->window)
215 {
216 CdkDisplay *display;
217
218 display = ctk_widget_get_display (tooltip->window);
219 g_signal_handlers_disconnect_by_func (display,g_signal_handlers_disconnect_matched ((display), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (ctk_tooltip_display_closed), (tooltip))
220 ctk_tooltip_display_closed,g_signal_handlers_disconnect_matched ((display), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (ctk_tooltip_display_closed), (tooltip))
221 tooltip)g_signal_handlers_disconnect_matched ((display), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (ctk_tooltip_display_closed), (tooltip))
;
222 ctk_widget_destroy (tooltip->window);
223 tooltip->window = NULL((void*)0);
224 }
225
226 G_OBJECT_CLASS (ctk_tooltip_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_tooltip_parent_class)), (((GType) ((20) << (2)
)))))))
->dispose (object);
227}
228
229/* public API */
230
231/**
232 * ctk_tooltip_set_markup:
233 * @tooltip: a #CtkTooltip
234 * @markup: (allow-none): a markup string (see [Pango markup format][PangoMarkupFormat]) or %NULL
235 *
236 * Sets the text of the tooltip to be @markup, which is marked up
237 * with the [Pango text markup language][PangoMarkupFormat].
238 * If @markup is %NULL, the label will be hidden.
239 *
240 * Since: 2.12
241 */
242void
243ctk_tooltip_set_markup (CtkTooltip *tooltip,
244 const gchar *markup)
245{
246 g_return_if_fail (CTK_IS_TOOLTIP (tooltip))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tooltip)); GType __t = ((ctk_tooltip_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TOOLTIP (tooltip)"); return; } } while (0)
;
247
248 ctk_tooltip_window_set_label_markup (CTK_TOOLTIP_WINDOW (tooltip->window), markup);
249}
250
251/**
252 * ctk_tooltip_set_text:
253 * @tooltip: a #CtkTooltip
254 * @text: (allow-none): a text string or %NULL
255 *
256 * Sets the text of the tooltip to be @text. If @text is %NULL, the label
257 * will be hidden. See also ctk_tooltip_set_markup().
258 *
259 * Since: 2.12
260 */
261void
262ctk_tooltip_set_text (CtkTooltip *tooltip,
263 const gchar *text)
264{
265 g_return_if_fail (CTK_IS_TOOLTIP (tooltip))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tooltip)); GType __t = ((ctk_tooltip_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TOOLTIP (tooltip)"); return; } } while (0)
;
266
267 ctk_tooltip_window_set_label_text (CTK_TOOLTIP_WINDOW (tooltip->window), text);
268}
269
270/**
271 * ctk_tooltip_set_icon:
272 * @tooltip: a #CtkTooltip
273 * @pixbuf: (allow-none): a #GdkPixbuf, or %NULL
274 *
275 * Sets the icon of the tooltip (which is in front of the text) to be
276 * @pixbuf. If @pixbuf is %NULL, the image will be hidden.
277 *
278 * Since: 2.12
279 */
280void
281ctk_tooltip_set_icon (CtkTooltip *tooltip,
282 GdkPixbuf *pixbuf)
283{
284 g_return_if_fail (CTK_IS_TOOLTIP (tooltip))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tooltip)); GType __t = ((ctk_tooltip_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TOOLTIP (tooltip)"); return; } } while (0)
;
285 g_return_if_fail (pixbuf == NULL || GDK_IS_PIXBUF (pixbuf))do { if ((pixbuf == ((void*)0) || (((__extension__ ({ GTypeInstance
*__inst = (GTypeInstance*) ((pixbuf)); GType __t = ((gdk_pixbuf_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "pixbuf == NULL || GDK_IS_PIXBUF (pixbuf)"
); return; } } while (0)
;
286
287 ctk_tooltip_window_set_image_icon (CTK_TOOLTIP_WINDOW (tooltip->window), pixbuf);
288}
289
290/**
291 * ctk_tooltip_set_icon_from_stock:
292 * @tooltip: a #CtkTooltip
293 * @stock_id: (allow-none): a stock id, or %NULL
294 * @size: (type int): a stock icon size (#CtkIconSize)
295 *
296 * Sets the icon of the tooltip (which is in front of the text) to be
297 * the stock item indicated by @stock_id with the size indicated
298 * by @size. If @stock_id is %NULL, the image will be hidden.
299 *
300 * Since: 2.12
301 *
302 * Deprecated: 3.10: Use ctk_tooltip_set_icon_from_icon_name() instead.
303 */
304void
305ctk_tooltip_set_icon_from_stock (CtkTooltip *tooltip,
306 const gchar *stock_id,
307 CtkIconSize size)
308{
309 g_return_if_fail (CTK_IS_TOOLTIP (tooltip))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tooltip)); GType __t = ((ctk_tooltip_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TOOLTIP (tooltip)"); return; } } while (0)
;
310
311 ctk_tooltip_window_set_image_icon_from_stock (CTK_TOOLTIP_WINDOW (tooltip->window),
312 stock_id,
313 size);
314}
315
316/**
317 * ctk_tooltip_set_icon_from_icon_name:
318 * @tooltip: a #CtkTooltip
319 * @icon_name: (allow-none): an icon name, or %NULL
320 * @size: (type int): a stock icon size (#CtkIconSize)
321 *
322 * Sets the icon of the tooltip (which is in front of the text) to be
323 * the icon indicated by @icon_name with the size indicated
324 * by @size. If @icon_name is %NULL, the image will be hidden.
325 *
326 * Since: 2.14
327 */
328void
329ctk_tooltip_set_icon_from_icon_name (CtkTooltip *tooltip,
330 const gchar *icon_name,
331 CtkIconSize size)
332{
333 g_return_if_fail (CTK_IS_TOOLTIP (tooltip))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tooltip)); GType __t = ((ctk_tooltip_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TOOLTIP (tooltip)"); return; } } while (0)
;
334
335 ctk_tooltip_window_set_image_icon_from_name (CTK_TOOLTIP_WINDOW (tooltip->window),
336 icon_name,
337 size);
338}
339
340/**
341 * ctk_tooltip_set_icon_from_gicon:
342 * @tooltip: a #CtkTooltip
343 * @gicon: (allow-none): a #GIcon representing the icon, or %NULL
344 * @size: (type int): a stock icon size (#CtkIconSize)
345 *
346 * Sets the icon of the tooltip (which is in front of the text)
347 * to be the icon indicated by @gicon with the size indicated
348 * by @size. If @gicon is %NULL, the image will be hidden.
349 *
350 * Since: 2.20
351 */
352void
353ctk_tooltip_set_icon_from_gicon (CtkTooltip *tooltip,
354 GIcon *gicon,
355 CtkIconSize size)
356{
357 g_return_if_fail (CTK_IS_TOOLTIP (tooltip))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tooltip)); GType __t = ((ctk_tooltip_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TOOLTIP (tooltip)"); return; } } while (0)
;
358
359 ctk_tooltip_window_set_image_icon_from_gicon (CTK_TOOLTIP_WINDOW (tooltip->window),
360 gicon,
361 size);
362}
363
364/**
365 * ctk_tooltip_set_custom:
366 * @tooltip: a #CtkTooltip
367 * @custom_widget: (allow-none): a #CtkWidget, or %NULL to unset the old custom widget.
368 *
369 * Replaces the widget packed into the tooltip with
370 * @custom_widget. @custom_widget does not get destroyed when the tooltip goes
371 * away.
372 * By default a box with a #CtkImage and #CtkLabel is embedded in
373 * the tooltip, which can be configured using ctk_tooltip_set_markup()
374 * and ctk_tooltip_set_icon().
375
376 *
377 * Since: 2.12
378 */
379void
380ctk_tooltip_set_custom (CtkTooltip *tooltip,
381 CtkWidget *custom_widget)
382{
383 g_return_if_fail (CTK_IS_TOOLTIP (tooltip))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tooltip)); GType __t = ((ctk_tooltip_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TOOLTIP (tooltip)"); return; } } while (0)
;
384 g_return_if_fail (custom_widget == NULL || CTK_IS_WIDGET (custom_widget))do { if ((custom_widget == ((void*)0) || (((__extension__ ({ GTypeInstance
*__inst = (GTypeInstance*) ((custom_widget)); GType __t = ((
ctk_widget_get_type ())); gboolean __r; if (!__inst) __r = (0
); else if (__inst->g_class && __inst->g_class->
g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a
(__inst, __t); __r; })))))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "custom_widget == NULL || CTK_IS_WIDGET (custom_widget)"
); return; } } while (0)
;
385
386 /* The custom widget has been updated from the query-tooltip
387 * callback, so we do not want to reset the custom widget later on.
388 */
389 tooltip->custom_was_reset = TRUE(!(0));
390
391 ctk_tooltip_window_set_custom_widget (CTK_TOOLTIP_WINDOW (tooltip->window), custom_widget);
392}
393
394/**
395 * ctk_tooltip_set_tip_area:
396 * @tooltip: a #CtkTooltip
397 * @rect: a #CdkRectangle
398 *
399 * Sets the area of the widget, where the contents of this tooltip apply,
400 * to be @rect (in widget coordinates). This is especially useful for
401 * properly setting tooltips on #CtkTreeView rows and cells, #CtkIconViews,
402 * etc.
403 *
404 * For setting tooltips on #CtkTreeView, please refer to the convenience
405 * functions for this: ctk_tree_view_set_tooltip_row() and
406 * ctk_tree_view_set_tooltip_cell().
407 *
408 * Since: 2.12
409 */
410void
411ctk_tooltip_set_tip_area (CtkTooltip *tooltip,
412 const CdkRectangle *rect)
413{
414 g_return_if_fail (CTK_IS_TOOLTIP (tooltip))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tooltip)); GType __t = ((ctk_tooltip_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TOOLTIP (tooltip)"); return; } } while (0)
;
415
416 if (!rect)
417 tooltip->tip_area_set = FALSE(0);
418 else
419 {
420 tooltip->tip_area_set = TRUE(!(0));
421 tooltip->tip_area = *rect;
422 }
423}
424
425/**
426 * ctk_tooltip_trigger_tooltip_query:
427 * @display: a #CdkDisplay
428 *
429 * Triggers a new tooltip query on @display, in order to update the current
430 * visible tooltip, or to show/hide the current tooltip. This function is
431 * useful to call when, for example, the state of the widget changed by a
432 * key press.
433 *
434 * Since: 2.12
435 */
436void
437ctk_tooltip_trigger_tooltip_query (CdkDisplay *display)
438{
439 gint x, y;
440 CdkWindow *window;
441 CdkEvent event;
442 CdkDevice *device;
443
444 /* Trigger logic as if the mouse moved */
445 device = cdk_seat_get_pointer (cdk_display_get_default_seat (display));
446 window = cdk_device_get_window_at_position (device, &x, &y);
447 if (!window)
448 return;
449
450 event.type = CDK_MOTION_NOTIFY;
451 event.motion.window = window;
452 event.motion.x = x;
453 event.motion.y = y;
454 event.motion.is_hint = FALSE(0);
455
456 cdk_window_get_root_coords (window, x, y, &x, &y);
457 event.motion.x_root = x;
458 event.motion.y_root = y;
459
460 ctk_tooltip_handle_event_internal (&event);
461}
462
463/* private functions */
464
465static void
466ctk_tooltip_reset (CtkTooltip *tooltip)
467{
468 ctk_tooltip_set_markup (tooltip, NULL((void*)0));
469 ctk_tooltip_set_icon (tooltip, NULL((void*)0));
470 ctk_tooltip_set_tip_area (tooltip, NULL((void*)0));
471
472 /* See if the custom widget is again set from the query-tooltip
473 * callback.
474 */
475 tooltip->custom_was_reset = FALSE(0);
476}
477
478static void
479ctk_tooltip_window_hide (CtkWidget *widget G_GNUC_UNUSED__attribute__ ((__unused__)),
480 gpointer user_data)
481{
482 CtkTooltip *tooltip = CTK_TOOLTIP (user_data)((((CtkTooltip*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((user_data)), ((ctk_tooltip_get_type ()))))))
;
483
484 ctk_tooltip_set_custom (tooltip, NULL((void*)0));
485}
486
487/* event handling, etc */
488
489struct ChildLocation
490{
491 CtkWidget *child;
492 CtkWidget *container;
493
494 gint x;
495 gint y;
496};
497
498static void
499prepend_and_ref_widget (CtkWidget *widget,
500 gpointer data)
501{
502 GSList **slist_p = data;
503
504 *slist_p = g_slist_prepend (*slist_p, g_object_ref (widget)((__typeof__ (widget)) (g_object_ref) (widget)));
505}
506
507static void
508child_location_foreach (CtkWidget *child,
509 gpointer data)
510{
511 CtkAllocation child_allocation;
512 gint x, y;
513 struct ChildLocation *child_loc = data;
514
515 /* Ignore invisible widgets */
516 if (!ctk_widget_is_drawable (child))
517 return;
518
519 ctk_widget_get_allocation (child, &child_allocation);
520
521 x = 0;
522 y = 0;
523
524 /* (child_loc->x, child_loc->y) are relative to
525 * child_loc->container's allocation.
526 */
527
528 if (!child_loc->child &&
529 ctk_widget_translate_coordinates (child_loc->container, child,
530 child_loc->x, child_loc->y,
531 &x, &y))
532 {
533 /* (x, y) relative to child's allocation. */
534 if (x >= 0 && x < child_allocation.width
535 && y >= 0 && y < child_allocation.height)
536 {
537 if (CTK_IS_CONTAINER (child)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(child)); GType __t = ((ctk_container_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
538 {
539 struct ChildLocation tmp = { NULL((void*)0), NULL((void*)0), 0, 0 };
540 GSList *children = NULL((void*)0), *tmp_list;
541
542 /* Take (x, y) relative the child's allocation and
543 * recurse.
544 */
545 tmp.x = x;
546 tmp.y = y;
547 tmp.container = child;
548
549 ctk_container_forall (CTK_CONTAINER (child)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((child)), ((ctk_container_get_type ()))))))
,
550 prepend_and_ref_widget, &children);
551
552 for (tmp_list = children; tmp_list; tmp_list = tmp_list->next)
553 {
554 child_location_foreach (tmp_list->data, &tmp);
555 g_object_unref (tmp_list->data);
556 }
557
558 if (tmp.child)
559 child_loc->child = tmp.child;
560 else
561 child_loc->child = child;
562
563 g_slist_free (children);
564 }
565 else
566 child_loc->child = child;
567 }
568 }
569}
570
571/* Translates coordinates from dest_widget->window relative (src_x, src_y),
572 * to allocation relative (dest_x, dest_y) of dest_widget.
573 */
574static void
575window_to_alloc (CtkWidget *dest_widget,
576 gint src_x,
577 gint src_y,
578 gint *dest_x,
579 gint *dest_y)
580{
581 CtkAllocation allocation;
582
583 ctk_widget_get_allocation (dest_widget, &allocation);
584
585 /* Translate from window relative to allocation relative */
586 if (ctk_widget_get_has_window (dest_widget) &&
587 ctk_widget_get_parent (dest_widget))
588 {
589 gint wx, wy;
590 cdk_window_get_position (ctk_widget_get_window (dest_widget),
591 &wx, &wy);
592
593 /* Offset coordinates if widget->window is smaller than
594 * widget->allocation.
595 */
596 src_x += wx - allocation.x;
597 src_y += wy - allocation.y;
598 }
599 else
600 {
601 src_x -= allocation.x;
602 src_y -= allocation.y;
603 }
604
605 if (dest_x)
606 *dest_x = src_x;
607 if (dest_y)
608 *dest_y = src_y;
609}
610
611/* Translates coordinates from window relative (x, y) to
612 * allocation relative (x, y) of the returned widget.
613 */
614CtkWidget *
615_ctk_widget_find_at_coords (CdkWindow *window,
616 gint window_x,
617 gint window_y,
618 gint *widget_x,
619 gint *widget_y)
620{
621 CtkWidget *event_widget;
622 struct ChildLocation child_loc = { NULL((void*)0), NULL((void*)0), 0, 0 };
623
624 g_return_val_if_fail (CDK_IS_WINDOW (window), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((cdk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CDK_IS_WINDOW (window)"); return (((void*)0)); } } while
(0)
;
625
626 cdk_window_get_user_data (window, (void **)&event_widget);
627
628 if (!event_widget)
629 return NULL((void*)0);
630
631 /* Coordinates are relative to event window */
632 child_loc.x = window_x;
633 child_loc.y = window_y;
634
635 /* We go down the window hierarchy to the widget->window,
636 * coordinates stay relative to the current window.
637 * We end up with window == widget->window, coordinates relative to that.
638 */
639 while (window && window != ctk_widget_get_window (event_widget))
640 {
641 gdouble px, py;
642
643 cdk_window_coords_to_parent (window,
644 child_loc.x, child_loc.y,
645 &px, &py);
646 child_loc.x = px;
647 child_loc.y = py;
648
649 window = cdk_window_get_effective_parent (window);
650 }
651
652 /* Failing to find widget->window can happen for e.g. a detached handle box;
653 * chaining ::query-tooltip up to its parent probably makes little sense,
654 * and users better implement tooltips on handle_box->child.
655 * so we simply ignore the event for tooltips here.
656 */
657 if (!window)
658 return NULL((void*)0);
659
660 /* Convert the window relative coordinates to allocation
661 * relative coordinates.
662 */
663 window_to_alloc (event_widget,
664 child_loc.x, child_loc.y,
665 &child_loc.x, &child_loc.y);
666
667 if (CTK_IS_CONTAINER (event_widget)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(event_widget)); GType __t = ((ctk_container_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
668 {
669 CtkWidget *container = event_widget;
670
671 child_loc.container = event_widget;
672 child_loc.child = NULL((void*)0);
673
674 ctk_container_forall (CTK_CONTAINER (event_widget)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((event_widget)), ((ctk_container_get_type ()))))))
,
675 child_location_foreach, &child_loc);
676
677 /* Here we have a widget, with coordinates relative to
678 * child_loc.container's allocation.
679 */
680
681 if (child_loc.child)
682 event_widget = child_loc.child;
683 else if (child_loc.container)
684 event_widget = child_loc.container;
685
686 /* Translate to event_widget's allocation */
687 ctk_widget_translate_coordinates (container, event_widget,
688 child_loc.x, child_loc.y,
689 &child_loc.x, &child_loc.y);
690 }
691
692 /* We return (x, y) relative to the allocation of event_widget. */
693 if (widget_x)
694 *widget_x = child_loc.x;
695 if (widget_y)
696 *widget_y = child_loc.y;
697
698 return event_widget;
699}
700
701/* Ignores (x, y) on input, translates event coordinates to
702 * allocation relative (x, y) of the returned widget.
703 */
704static CtkWidget *
705find_topmost_widget_coords_from_event (CdkEvent *event,
706 gint *x,
707 gint *y)
708{
709 CtkAllocation allocation;
710 gint tx, ty;
711 gdouble dx, dy;
712 CtkWidget *tmp;
713
714 cdk_event_get_coords (event, &dx, &dy);
715
716 /* Returns coordinates relative to tmp's allocation. */
717 tmp = _ctk_widget_find_at_coords (event->any.window, dx, dy, &tx, &ty);
718
719 if (!tmp
4.1
'tmp' is null
)
5
Taking true branch
720 return NULL((void*)0);
721
722 /* Make sure the pointer can actually be on the widget returned. */
723 ctk_widget_get_allocation (tmp, &allocation);
724 allocation.x = 0;
725 allocation.y = 0;
726 if (CTK_IS_WINDOW (tmp)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(tmp)); GType __t = ((ctk_window_get_type ())); gboolean __r;
if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
727 {
728 CtkBorder border;
729 _ctk_window_get_shadow_width (CTK_WINDOW (tmp)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tmp)), ((ctk_window_get_type ()))))))
, &border);
730 allocation.x = border.left;
731 allocation.y = border.top;
732 allocation.width -= border.left + border.right;
733 allocation.height -= border.top + border.bottom;
734 }
735
736 if (tx < allocation.x || tx >= allocation.width ||
737 ty < allocation.y || ty >= allocation.height)
738 return NULL((void*)0);
739
740 if (x)
741 *x = tx;
742 if (y)
743 *y = ty;
744
745 return tmp;
746}
747
748static gint
749tooltip_browse_mode_expired (gpointer data)
750{
751 CtkTooltip *tooltip;
752 CdkDisplay *display;
753
754 tooltip = CTK_TOOLTIP (data)((((CtkTooltip*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((ctk_tooltip_get_type ()))))))
;
755
756 tooltip->browse_mode_enabled = FALSE(0);
757 tooltip->browse_mode_timeout_id = 0;
758
759 if (tooltip->timeout_id)
760 {
761 g_source_remove (tooltip->timeout_id);
762 tooltip->timeout_id = 0;
763 }
764
765 /* destroy tooltip */
766 display = ctk_widget_get_display (tooltip->window);
767 g_object_set_qdata (G_OBJECT (display)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((display)), (((GType) ((20) << (2))))))))
, quark_current_tooltiptooltip_quark(), NULL((void*)0));
768
769 return FALSE(0);
770}
771
772static void
773ctk_tooltip_display_closed (CdkDisplay *display,
774 gboolean was_error G_GNUC_UNUSED__attribute__ ((__unused__)),
775 CtkTooltip *tooltip)
776{
777 if (tooltip->timeout_id)
778 {
779 g_source_remove (tooltip->timeout_id);
780 tooltip->timeout_id = 0;
781 }
782
783 g_object_set_qdata (G_OBJECT (display)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((display)), (((GType) ((20) << (2))))))))
, quark_current_tooltiptooltip_quark(), NULL((void*)0));
784}
785
786static void
787ctk_tooltip_set_last_window (CtkTooltip *tooltip,
788 CdkWindow *window)
789{
790 CtkWidget *window_widget = NULL((void*)0);
791
792 if (tooltip->last_window == window)
793 return;
794
795 if (tooltip->last_window)
796 g_object_remove_weak_pointer (G_OBJECT (tooltip->last_window)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tooltip->last_window)), (((GType) ((20) << (2))
))))))
,
797 (gpointer *) &tooltip->last_window);
798
799 tooltip->last_window = window;
800
801 if (tooltip->last_window)
802 g_object_add_weak_pointer (G_OBJECT (tooltip->last_window)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tooltip->last_window)), (((GType) ((20) << (2))
))))))
,
803 (gpointer *) &tooltip->last_window);
804
805 if (window)
806 cdk_window_get_user_data (window, (gpointer *) &window_widget);
807
808 if (window_widget)
809 window_widget = ctk_widget_get_toplevel (window_widget);
810
811 if (window_widget &&
812 window_widget != tooltip->window &&
813 ctk_widget_is_toplevel (window_widget) &&
814 CTK_IS_WINDOW (window_widget)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(window_widget)); GType __t = ((ctk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
815 ctk_window_set_transient_for (CTK_WINDOW (tooltip->window)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tooltip->window)), ((ctk_window_get_type ()))))))
,
816 CTK_WINDOW (window_widget)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window_widget)), ((ctk_window_get_type ()))))))
);
817 else
818 ctk_window_set_transient_for (CTK_WINDOW (tooltip->window)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tooltip->window)), ((ctk_window_get_type ()))))))
, NULL((void*)0));
819}
820
821static gboolean
822ctk_tooltip_run_requery (CtkWidget **widget,
823 CtkTooltip *tooltip,
824 gint *x,
825 gint *y)
826{
827 gboolean has_tooltip = FALSE(0);
828 gboolean return_value = FALSE(0);
829
830 ctk_tooltip_reset (tooltip);
831
832 do
833 {
834 has_tooltip = ctk_widget_get_has_tooltip (*widget);
835
836 if (has_tooltip)
14
Assuming 'has_tooltip' is not equal to 0
15
Taking true branch
837 return_value = ctk_widget_query_tooltip (*widget, *x, *y, tooltip->keyboard_mode_enabled, tooltip);
16
2nd function call argument is an uninitialized value
838
839 if (!return_value)
840 {
841 CtkWidget *parent = ctk_widget_get_parent (*widget);
842
843 if (parent)
844 ctk_widget_translate_coordinates (*widget, parent, *x, *y, x, y);
845
846 *widget = parent;
847 }
848 else
849 break;
850 }
851 while (*widget);
852
853 /* If the custom widget was not reset in the query-tooltip
854 * callback, we clear it here.
855 */
856 if (!tooltip->custom_was_reset)
857 ctk_tooltip_set_custom (tooltip, NULL((void*)0));
858
859 return return_value;
860}
861
862static void
863ctk_tooltip_position (CtkTooltip *tooltip,
864 CdkDisplay *display,
865 CtkWidget *new_tooltip_widget,
866 CdkDevice *device)
867{
868 CdkScreen *screen;
869 CtkSettings *settings;
870 CdkRectangle anchor_rect;
871 CdkWindow *window;
872 CdkWindow *widget_window;
873 CdkWindow *effective_toplevel;
874 CtkWidget *toplevel;
875 int rect_anchor_dx = 0;
876 int cursor_size;
877 int anchor_rect_padding;
878
879 ctk_widget_realize (CTK_WIDGET (tooltip->current_window)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tooltip->current_window)), ((ctk_widget_get_type ()))
))))
);
880 window = _ctk_widget_get_window (CTK_WIDGET (tooltip->current_window)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tooltip->current_window)), ((ctk_widget_get_type ()))
))))
);
881
882 tooltip->tooltip_widget = new_tooltip_widget;
883
884 toplevel = _ctk_widget_get_toplevel (new_tooltip_widget);
885 ctk_widget_translate_coordinates (new_tooltip_widget, toplevel,
886 0, 0,
887 &anchor_rect.x, &anchor_rect.y);
888
889 anchor_rect.width = ctk_widget_get_allocated_width (new_tooltip_widget);
890 anchor_rect.height = ctk_widget_get_allocated_height (new_tooltip_widget);
891
892 screen = cdk_window_get_screen (window);
893 settings = ctk_settings_get_for_screen (screen);
894 g_object_get (settings,
895 "ctk-cursor-theme-size", &cursor_size,
896 NULL((void*)0));
897
898 if (cursor_size == 0)
899 cursor_size = cdk_display_get_default_cursor_size (display);
900
901 if (device)
902 anchor_rect_padding = MAX (4, cursor_size - 32)(((4) > (cursor_size - 32)) ? (4) : (cursor_size - 32));
903 else
904 anchor_rect_padding = 4;
905
906 anchor_rect.x -= anchor_rect_padding;
907 anchor_rect.y -= anchor_rect_padding;
908 anchor_rect.width += anchor_rect_padding * 2;
909 anchor_rect.height += anchor_rect_padding * 2;
910
911 if (device)
912 {
913 const int max_x_distance = 32;
914 /* Max 48x48 icon + default padding */
915 const int max_anchor_rect_height = 48 + 8;
916 int pointer_x, pointer_y;
917
918 /*
919 * For pointer position triggered tooltips, implement the following
920 * semantics:
921 *
922 * If the anchor rectangle is too tall (meaning if we'd be constrained
923 * and flip, it'd flip too far away), rely only on the pointer position
924 * to position the tooltip. The approximate pointer cursorrectangle is
925 * used as a anchor rectantgle.
926 *
927 * If the anchor rectangle isn't to tall, make sure the tooltip isn't too
928 * far away from the pointer position.
929 */
930 widget_window = _ctk_widget_get_window (new_tooltip_widget);
931 effective_toplevel = cdk_window_get_effective_toplevel (widget_window);
932 cdk_window_get_device_position (effective_toplevel,
933 device,
934 &pointer_x, &pointer_y, NULL((void*)0));
935
936 if (anchor_rect.height > max_anchor_rect_height)
937 {
938 anchor_rect.x = pointer_x - 4;
939 anchor_rect.y = pointer_y - 4;
940 anchor_rect.width = cursor_size;
941 anchor_rect.height = cursor_size;
942 }
943 else
944 {
945 int anchor_point_x;
946 int x_distance;
947
948 anchor_point_x = anchor_rect.x + anchor_rect.width / 2;
949 x_distance = pointer_x - anchor_point_x;
950
951 if (x_distance > max_x_distance)
952 rect_anchor_dx = x_distance - max_x_distance;
953 else if (x_distance < -max_x_distance)
954 rect_anchor_dx = x_distance + max_x_distance;
955 }
956 }
957
958 ctk_window_set_transient_for (CTK_WINDOW (tooltip->current_window)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tooltip->current_window)), ((ctk_window_get_type ()))
))))
,
959 CTK_WINDOW (toplevel)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((toplevel)), ((ctk_window_get_type ()))))))
);
960
961 cdk_window_move_to_rect (window,
962 &anchor_rect,
963 CDK_GRAVITY_SOUTH,
964 CDK_GRAVITY_NORTH,
965 CDK_ANCHOR_FLIP_Y | CDK_ANCHOR_SLIDE_X,
966 rect_anchor_dx, 0);
967 ctk_widget_show (CTK_WIDGET (tooltip->current_window)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tooltip->current_window)), ((ctk_widget_get_type ()))
))))
);
968}
969
970static void
971ctk_tooltip_show_tooltip (CdkDisplay *display)
972{
973 gint x, y;
974 CdkScreen *screen;
975 CdkDevice *device;
976 CdkWindow *window;
977 CtkWidget *tooltip_widget;
978 CtkTooltip *tooltip;
979 gboolean return_value = FALSE(0);
980
981 tooltip = g_object_get_qdata (G_OBJECT (display)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((display)), (((GType) ((20) << (2))))))))
, quark_current_tooltiptooltip_quark());
982
983 if (tooltip->keyboard_mode_enabled)
984 {
985 x = y = -1;
986 tooltip_widget = tooltip->keyboard_widget;
987 device = NULL((void*)0);
988 }
989 else
990 {
991 gint tx, ty;
992
993 window = tooltip->last_window;
994
995 if (!CDK_IS_WINDOW (window)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(window)); GType __t = ((cdk_window_get_type ())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
996 return;
997
998 device = cdk_seat_get_pointer (cdk_display_get_default_seat (display));
999
1000 cdk_window_get_device_position (window, device, &x, &y, NULL((void*)0));
1001
1002 cdk_window_get_root_coords (window, x, y, &tx, &ty);
1003
1004 tooltip_widget = _ctk_widget_find_at_coords (window, x, y, &x, &y);
1005 }
1006
1007 if (!tooltip_widget)
1008 return;
1009
1010 return_value = ctk_tooltip_run_requery (&tooltip_widget, tooltip, &x, &y);
1011 if (!return_value)
1012 return;
1013
1014 if (!tooltip->current_window)
1015 {
1016 if (ctk_widget_get_tooltip_window (tooltip_widget))
1017 tooltip->current_window = ctk_widget_get_tooltip_window (tooltip_widget);
1018 else
1019 tooltip->current_window = CTK_WINDOW (CTK_TOOLTIP (tooltip)->window)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((((((CtkTooltip*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tooltip)), ((ctk_tooltip_get_type ()))))))->window)),
((ctk_window_get_type ()))))))
;
1020 }
1021
1022 screen = ctk_widget_get_screen (tooltip_widget);
1023
1024 /* FIXME: should use tooltip->current_window iso tooltip->window */
1025 if (screen != ctk_widget_get_screen (tooltip->window))
1026 {
1027 g_signal_handlers_disconnect_by_func (display,g_signal_handlers_disconnect_matched ((display), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (ctk_tooltip_display_closed), (tooltip))
1028 ctk_tooltip_display_closed,g_signal_handlers_disconnect_matched ((display), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (ctk_tooltip_display_closed), (tooltip))
1029 tooltip)g_signal_handlers_disconnect_matched ((display), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (ctk_tooltip_display_closed), (tooltip))
;
1030
1031 ctk_window_set_screen (CTK_WINDOW (tooltip->window)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tooltip->window)), ((ctk_window_get_type ()))))))
, screen);
1032
1033 g_signal_connect (display, "closed",g_signal_connect_data ((display), ("closed"), (((GCallback) (
ctk_tooltip_display_closed))), (tooltip), ((void*)0), (GConnectFlags
) 0)
1034 G_CALLBACK (ctk_tooltip_display_closed), tooltip)g_signal_connect_data ((display), ("closed"), (((GCallback) (
ctk_tooltip_display_closed))), (tooltip), ((void*)0), (GConnectFlags
) 0)
;
1035 }
1036
1037 ctk_tooltip_position (tooltip, display, tooltip_widget, device);
1038
1039 /* Now a tooltip is visible again on the display, make sure browse
1040 * mode is enabled.
1041 */
1042 tooltip->browse_mode_enabled = TRUE(!(0));
1043 if (tooltip->browse_mode_timeout_id)
1044 {
1045 g_source_remove (tooltip->browse_mode_timeout_id);
1046 tooltip->browse_mode_timeout_id = 0;
1047 }
1048}
1049
1050static void
1051ctk_tooltip_hide_tooltip (CtkTooltip *tooltip)
1052{
1053 if (!tooltip)
1054 return;
1055
1056 if (tooltip->timeout_id)
1057 {
1058 g_source_remove (tooltip->timeout_id);
1059 tooltip->timeout_id = 0;
1060 }
1061
1062 if (!CTK_TOOLTIP_VISIBLE (tooltip)((tooltip)->current_window && ctk_widget_get_visible
(((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((tooltip)->current_window)), ((ctk_widget_get_type ()
))))))))
)
1063 return;
1064
1065 tooltip->tooltip_widget = NULL((void*)0);
1066
1067 if (!tooltip->keyboard_mode_enabled)
1068 {
1069 guint timeout = BROWSE_DISABLE_TIMEOUT500;
1070
1071 /* The tooltip is gone, after (by default, should be configurable) 500ms
1072 * we want to turn off browse mode
1073 */
1074 if (!tooltip->browse_mode_timeout_id)
1075 {
1076 tooltip->browse_mode_timeout_id =
1077 cdk_threads_add_timeout_full (0, timeout,
1078 tooltip_browse_mode_expired,
1079 g_object_ref (tooltip)((__typeof__ (tooltip)) (g_object_ref) (tooltip)),
1080 g_object_unref);
1081 g_source_set_name_by_id (tooltip->browse_mode_timeout_id, "[ctk+] tooltip_browse_mode_expired");
1082 }
1083 }
1084 else
1085 {
1086 if (tooltip->browse_mode_timeout_id)
1087 {
1088 g_source_remove (tooltip->browse_mode_timeout_id);
1089 tooltip->browse_mode_timeout_id = 0;
1090 }
1091 }
1092
1093 if (tooltip->current_window)
1094 {
1095 ctk_widget_hide (CTK_WIDGET (tooltip->current_window)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tooltip->current_window)), ((ctk_widget_get_type ()))
))))
);
1096 tooltip->current_window = NULL((void*)0);
1097 }
1098}
1099
1100static gint
1101tooltip_popup_timeout (gpointer data)
1102{
1103 CdkDisplay *display;
1104 CtkTooltip *tooltip;
1105
1106 display = CDK_DISPLAY (data)((((CdkDisplay*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((cdk_display_get_type ()))))))
;
1107 tooltip = g_object_get_qdata (G_OBJECT (display)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((display)), (((GType) ((20) << (2))))))))
, quark_current_tooltiptooltip_quark());
1108
1109 /* This usually does not happen. However, it does occur in language
1110 * bindings were reference counting of objects behaves differently.
1111 */
1112 if (!tooltip)
1113 return FALSE(0);
1114
1115 ctk_tooltip_show_tooltip (display);
1116
1117 tooltip->timeout_id = 0;
1118
1119 return FALSE(0);
1120}
1121
1122static void
1123ctk_tooltip_start_delay (CdkDisplay *display)
1124{
1125 guint timeout;
1126 CtkTooltip *tooltip;
1127
1128 tooltip = g_object_get_qdata (G_OBJECT (display)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((display)), (((GType) ((20) << (2))))))))
, quark_current_tooltiptooltip_quark());
1129
1130 if (!tooltip || CTK_TOOLTIP_VISIBLE (tooltip)((tooltip)->current_window && ctk_widget_get_visible
(((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((tooltip)->current_window)), ((ctk_widget_get_type ()
))))))))
)
1131 return;
1132
1133 if (tooltip->timeout_id)
1134 g_source_remove (tooltip->timeout_id);
1135
1136 if (tooltip->browse_mode_enabled)
1137 timeout = BROWSE_TIMEOUT60;
1138 else
1139 timeout = HOVER_TIMEOUT500;
1140
1141 tooltip->timeout_id = cdk_threads_add_timeout_full (0, timeout,
1142 tooltip_popup_timeout,
1143 g_object_ref (display)((__typeof__ (display)) (g_object_ref) (display)),
1144 g_object_unref);
1145 g_source_set_name_by_id (tooltip->timeout_id, "[ctk+] tooltip_popup_timeout");
1146}
1147
1148void
1149_ctk_tooltip_focus_in (CtkWidget *widget)
1150{
1151 gint x, y;
1152 gboolean return_value = FALSE(0);
1153 CdkDisplay *display;
1154 CtkTooltip *tooltip;
1155 CdkDevice *device;
1156
1157 /* Get current tooltip for this display */
1158 display = ctk_widget_get_display (widget);
1159 tooltip = g_object_get_qdata (G_OBJECT (display)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((display)), (((GType) ((20) << (2))))))))
, quark_current_tooltiptooltip_quark());
1160
1161 /* Check if keyboard mode is enabled at this moment */
1162 if (!tooltip || !tooltip->keyboard_mode_enabled)
1163 return;
1164
1165 device = ctk_get_current_event_device ();
1166
1167 if (device && cdk_device_get_source (device) == CDK_SOURCE_KEYBOARD)
1168 device = cdk_device_get_associated_device (device);
1169
1170 /* This function should be called by either a focus in event,
1171 * or a key binding. In either case there should be a device.
1172 */
1173 if (!device)
1174 return;
1175
1176 if (tooltip->keyboard_widget)
1177 g_object_unref (tooltip->keyboard_widget);
1178
1179 tooltip->keyboard_widget = g_object_ref (widget)((__typeof__ (widget)) (g_object_ref) (widget));
1180
1181 cdk_window_get_device_position (ctk_widget_get_window (widget),
1182 device, &x, &y, NULL((void*)0));
1183
1184 return_value = ctk_tooltip_run_requery (&widget, tooltip, &x, &y);
1185 if (!return_value)
1186 {
1187 ctk_tooltip_hide_tooltip (tooltip);
1188 return;
1189 }
1190
1191 if (!tooltip->current_window)
1192 {
1193 if (ctk_widget_get_tooltip_window (widget))
1194 tooltip->current_window = ctk_widget_get_tooltip_window (widget);
1195 else
1196 tooltip->current_window = CTK_WINDOW (CTK_TOOLTIP (tooltip)->window)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((((((CtkTooltip*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tooltip)), ((ctk_tooltip_get_type ()))))))->window)),
((ctk_window_get_type ()))))))
;
1197 }
1198
1199 ctk_tooltip_show_tooltip (display);
1200}
1201
1202void
1203_ctk_tooltip_focus_out (CtkWidget *widget)
1204{
1205 CdkDisplay *display;
1206 CtkTooltip *tooltip;
1207
1208 /* Get current tooltip for this display */
1209 display = ctk_widget_get_display (widget);
1210 tooltip = g_object_get_qdata (G_OBJECT (display)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((display)), (((GType) ((20) << (2))))))))
, quark_current_tooltiptooltip_quark());
1211
1212 if (!tooltip || !tooltip->keyboard_mode_enabled)
1213 return;
1214
1215 if (tooltip->keyboard_widget)
1216 {
1217 g_object_unref (tooltip->keyboard_widget);
1218 tooltip->keyboard_widget = NULL((void*)0);
1219 }
1220
1221 ctk_tooltip_hide_tooltip (tooltip);
1222}
1223
1224void
1225_ctk_tooltip_toggle_keyboard_mode (CtkWidget *widget)
1226{
1227 CdkDisplay *display;
1228 CtkTooltip *tooltip;
1229
1230 display = ctk_widget_get_display (widget);
1231 tooltip = g_object_get_qdata (G_OBJECT (display)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((display)), (((GType) ((20) << (2))))))))
, quark_current_tooltiptooltip_quark());
1232
1233 if (!tooltip)
1234 {
1235 tooltip = g_object_new (CTK_TYPE_TOOLTIP(ctk_tooltip_get_type ()), NULL((void*)0));
1236 g_object_set_qdata_full (G_OBJECT (display)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((display)), (((GType) ((20) << (2))))))))
,
1237 quark_current_tooltiptooltip_quark(),
1238 tooltip,
1239 g_object_unref);
1240 g_signal_connect (display, "closed",g_signal_connect_data ((display), ("closed"), (((GCallback) (
ctk_tooltip_display_closed))), (tooltip), ((void*)0), (GConnectFlags
) 0)
1241 G_CALLBACK (ctk_tooltip_display_closed),g_signal_connect_data ((display), ("closed"), (((GCallback) (
ctk_tooltip_display_closed))), (tooltip), ((void*)0), (GConnectFlags
) 0)
1242 tooltip)g_signal_connect_data ((display), ("closed"), (((GCallback) (
ctk_tooltip_display_closed))), (tooltip), ((void*)0), (GConnectFlags
) 0)
;
1243 }
1244
1245 tooltip->keyboard_mode_enabled ^= 1;
1246
1247 if (tooltip->keyboard_mode_enabled)
1248 {
1249 tooltip->keyboard_widget = g_object_ref (widget)((__typeof__ (widget)) (g_object_ref) (widget));
1250 _ctk_tooltip_focus_in (widget);
1251 }
1252 else
1253 {
1254 if (tooltip->keyboard_widget)
1255 {
1256 g_object_unref (tooltip->keyboard_widget);
1257 tooltip->keyboard_widget = NULL((void*)0);
1258 }
1259
1260 ctk_tooltip_hide_tooltip (tooltip);
1261 }
1262}
1263
1264void
1265_ctk_tooltip_hide (CtkWidget *widget)
1266{
1267 CdkDisplay *display;
1268 CtkTooltip *tooltip;
1269
1270 display = ctk_widget_get_display (widget);
1271 tooltip = g_object_get_qdata (G_OBJECT (display)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((display)), (((GType) ((20) << (2))))))))
, quark_current_tooltiptooltip_quark());
1272
1273 if (!tooltip || !CTK_TOOLTIP_VISIBLE (tooltip)((tooltip)->current_window && ctk_widget_get_visible
(((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((tooltip)->current_window)), ((ctk_widget_get_type ()
))))))))
|| !tooltip->tooltip_widget)
1274 return;
1275
1276 if (widget == tooltip->tooltip_widget)
1277 ctk_tooltip_hide_tooltip (tooltip);
1278}
1279
1280void
1281_ctk_tooltip_hide_in_display (CdkDisplay *display)
1282{
1283 CtkTooltip *tooltip;
1284
1285 if (!display)
1286 return;
1287
1288 tooltip = g_object_get_qdata (G_OBJECT (display)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((display)), (((GType) ((20) << (2))))))))
, quark_current_tooltiptooltip_quark());
1289
1290 if (!tooltip || !CTK_TOOLTIP_VISIBLE (tooltip)((tooltip)->current_window && ctk_widget_get_visible
(((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((tooltip)->current_window)), ((ctk_widget_get_type ()
))))))))
)
1291 return;
1292
1293 ctk_tooltip_hide_tooltip (tooltip);
1294}
1295
1296static gboolean
1297tooltips_enabled (CdkEvent *event)
1298{
1299 CdkDevice *source_device;
1300 CdkInputSource source;
1301
1302 source_device = cdk_event_get_source_device (event);
1303
1304 if (!source_device)
1305 return FALSE(0);
1306
1307 source = cdk_device_get_source (source_device);
1308
1309 if (source != CDK_SOURCE_TOUCHSCREEN)
1310 return TRUE(!(0));
1311
1312 return FALSE(0);
1313}
1314
1315void
1316_ctk_tooltip_handle_event (CdkEvent *event)
1317{
1318 if (!tooltips_enabled (event))
1
Taking false branch
1319 return;
1320
1321 ctk_tooltip_handle_event_internal (event);
2
Calling 'ctk_tooltip_handle_event_internal'
1322}
1323
1324static void
1325ctk_tooltip_handle_event_internal (CdkEvent *event)
1326{
1327 gint x, y;
3
'x' declared without an initial value
1328 CtkWidget *has_tooltip_widget;
1329 CdkDisplay *display;
1330 CtkTooltip *current_tooltip;
1331
1332 /* Returns coordinates relative to has_tooltip_widget's allocation. */
1333 has_tooltip_widget = find_topmost_widget_coords_from_event (event, &x, &y);
4
Calling 'find_topmost_widget_coords_from_event'
6
Returning from 'find_topmost_widget_coords_from_event'
1334 display = cdk_window_get_display (event->any.window);
1335 current_tooltip = g_object_get_qdata (G_OBJECT (display)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((display)), (((GType) ((20) << (2))))))))
, quark_current_tooltiptooltip_quark());
1336
1337 if (current_tooltip)
7
Assuming 'current_tooltip' is non-null
8
Taking true branch
1338 {
1339 ctk_tooltip_set_last_window (current_tooltip, event->any.window);
1340 }
1341
1342 if (current_tooltip
8.1
'current_tooltip' is non-null
&& current_tooltip->keyboard_mode_enabled)
9
Assuming field 'keyboard_mode_enabled' is not equal to 0
10
Taking true branch
1343 {
1344 gboolean return_value;
1345
1346 has_tooltip_widget = current_tooltip->keyboard_widget;
1347 if (!has_tooltip_widget)
11
Assuming 'has_tooltip_widget' is non-null
12
Taking false branch
1348 return;
1349
1350 return_value = ctk_tooltip_run_requery (&has_tooltip_widget,
13
Calling 'ctk_tooltip_run_requery'
1351 current_tooltip,
1352 &x, &y);
1353
1354 if (!return_value)
1355 ctk_tooltip_hide_tooltip (current_tooltip);
1356 else
1357 ctk_tooltip_start_delay (display);
1358
1359 return;
1360 }
1361
1362 /* Always poll for a next motion event */
1363 cdk_event_request_motions (&event->motion);
1364
1365 /* Hide the tooltip when there's no new tooltip widget */
1366 if (!has_tooltip_widget)
1367 {
1368 if (current_tooltip)
1369 ctk_tooltip_hide_tooltip (current_tooltip);
1370
1371 return;
1372 }
1373
1374 switch (event->type)
1375 {
1376 case CDK_BUTTON_PRESS:
1377 case CDK_2BUTTON_PRESS:
1378 case CDK_3BUTTON_PRESS:
1379 case CDK_KEY_PRESS:
1380 case CDK_DRAG_ENTER:
1381 case CDK_GRAB_BROKEN:
1382 case CDK_SCROLL:
1383 ctk_tooltip_hide_tooltip (current_tooltip);
1384 break;
1385
1386 case CDK_MOTION_NOTIFY:
1387 case CDK_ENTER_NOTIFY:
1388 case CDK_LEAVE_NOTIFY:
1389 if (current_tooltip)
1390 {
1391 gboolean tip_area_set;
1392 CdkRectangle tip_area;
1393 gboolean hide_tooltip;
1394
1395 tip_area_set = current_tooltip->tip_area_set;
1396 tip_area = current_tooltip->tip_area;
1397
1398 ctk_tooltip_run_requery (&has_tooltip_widget,
1399 current_tooltip,
1400 &x, &y);
1401
1402 /* Leave notify should override the query function */
1403 hide_tooltip = (event->type == CDK_LEAVE_NOTIFY);
1404
1405 /* Is the pointer above another widget now? */
1406 if (CTK_TOOLTIP_VISIBLE (current_tooltip)((current_tooltip)->current_window && ctk_widget_get_visible
(((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((current_tooltip)->current_window)), ((ctk_widget_get_type
()))))))))
)
1407 hide_tooltip |= has_tooltip_widget != current_tooltip->tooltip_widget;
1408
1409 /* Did the pointer move out of the previous "context area"? */
1410 if (tip_area_set)
1411 hide_tooltip |= (x <= tip_area.x
1412 || x >= tip_area.x + tip_area.width
1413 || y <= tip_area.y
1414 || y >= tip_area.y + tip_area.height);
1415
1416 if (hide_tooltip)
1417 ctk_tooltip_hide_tooltip (current_tooltip);
1418 else
1419 ctk_tooltip_start_delay (display);
1420 }
1421 else
1422 {
1423 /* Need a new tooltip for this display */
1424 current_tooltip = g_object_new (CTK_TYPE_TOOLTIP(ctk_tooltip_get_type ()), NULL((void*)0));
1425 g_object_set_qdata_full (G_OBJECT (display)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((display)), (((GType) ((20) << (2))))))))
,
1426 quark_current_tooltiptooltip_quark(),
1427 current_tooltip,
1428 g_object_unref);
1429 g_signal_connect (display, "closed",g_signal_connect_data ((display), ("closed"), (((GCallback) (
ctk_tooltip_display_closed))), (current_tooltip), ((void*)0),
(GConnectFlags) 0)
1430 G_CALLBACK (ctk_tooltip_display_closed),g_signal_connect_data ((display), ("closed"), (((GCallback) (
ctk_tooltip_display_closed))), (current_tooltip), ((void*)0),
(GConnectFlags) 0)
1431 current_tooltip)g_signal_connect_data ((display), ("closed"), (((GCallback) (
ctk_tooltip_display_closed))), (current_tooltip), ((void*)0),
(GConnectFlags) 0)
;
1432
1433 ctk_tooltip_set_last_window (current_tooltip, event->any.window);
1434
1435 ctk_tooltip_start_delay (display);
1436 }
1437 break;
1438
1439 default:
1440 break;
1441 }
1442}