1/* GTK - The GIMP Toolkit
2 * Copyright (C) 2017 - Red Hat Inc.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "config.h"
19
20#include "gtkpointerfocusprivate.h"
21#include "gtkprivate.h"
22
23static void
24target_destroyed (gpointer data,
25 GObject *object_location)
26{
27 GtkPointerFocus *focus = data;
28
29 focus->target = NULL;
30 gtk_pointer_focus_repick_target (focus);
31}
32
33GtkPointerFocus *
34gtk_pointer_focus_new (GtkWindow *toplevel,
35 GtkWidget *widget,
36 GdkDevice *device,
37 GdkEventSequence *sequence,
38 double x,
39 double y)
40{
41 GtkPointerFocus *focus;
42
43 focus = g_new0 (GtkPointerFocus, 1);
44 focus->ref_count = 1;
45 focus->toplevel = toplevel;
46 focus->device = device;
47 focus->sequence = sequence;
48 gtk_pointer_focus_set_target (focus, target: widget);
49 gtk_pointer_focus_set_coordinates (focus, x, y);
50
51 return focus;
52}
53
54GtkPointerFocus *
55gtk_pointer_focus_ref (GtkPointerFocus *focus)
56{
57 focus->ref_count++;
58 return focus;
59}
60
61void
62gtk_pointer_focus_unref (GtkPointerFocus *focus)
63{
64 focus->ref_count--;
65
66 if (focus->ref_count == 0)
67 {
68 gtk_pointer_focus_set_target (focus, NULL);
69 gtk_pointer_focus_set_implicit_grab (focus, NULL);
70 g_free (mem: focus);
71 }
72}
73
74void
75gtk_pointer_focus_set_target (GtkPointerFocus *focus,
76 GtkWidget *target)
77{
78 if (focus->target == target)
79 return;
80
81 if (focus->target)
82 g_object_weak_unref (G_OBJECT (focus->target), notify: target_destroyed, data: focus);
83
84 focus->target = target;
85
86 if (focus->target)
87 g_object_weak_ref (G_OBJECT (focus->target), notify: target_destroyed, data: focus);
88}
89
90GtkWidget *
91gtk_pointer_focus_get_target (GtkPointerFocus *focus)
92{
93 return focus->target;
94}
95
96void
97gtk_pointer_focus_set_implicit_grab (GtkPointerFocus *focus,
98 GtkWidget *grab_widget)
99{
100 focus->grab_widget = grab_widget;
101}
102
103GtkWidget *
104gtk_pointer_focus_get_implicit_grab (GtkPointerFocus *focus)
105{
106 return focus->grab_widget;
107}
108
109void
110gtk_pointer_focus_set_coordinates (GtkPointerFocus *focus,
111 double x,
112 double y)
113{
114 focus->x = x;
115 focus->y = y;
116}
117
118GtkWidget *
119gtk_pointer_focus_get_effective_target (GtkPointerFocus *focus)
120{
121 GtkWidget *target;
122
123 target = focus->target;
124
125 if (focus->grab_widget &&
126 focus->grab_widget != target &&
127 !gtk_widget_is_ancestor (widget: target, ancestor: focus->grab_widget))
128 target = focus->grab_widget;
129
130 return target;
131}
132
133void
134gtk_pointer_focus_repick_target (GtkPointerFocus *focus)
135{
136 GtkWidget *target;
137
138 target = gtk_widget_pick (GTK_WIDGET (focus->toplevel), x: focus->x, y: focus->y, flags: GTK_PICK_DEFAULT);
139 if (target == NULL)
140 target = GTK_WIDGET (focus->toplevel);
141 gtk_pointer_focus_set_target (focus, target);
142}
143

source code of gtk/gtk/gtkpointerfocus.c