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 | |
23 | static void |
24 | target_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 | |
33 | GtkPointerFocus * |
34 | gtk_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 | |
54 | GtkPointerFocus * |
55 | gtk_pointer_focus_ref (GtkPointerFocus *focus) |
56 | { |
57 | focus->ref_count++; |
58 | return focus; |
59 | } |
60 | |
61 | void |
62 | gtk_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 | |
74 | void |
75 | gtk_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 | |
90 | GtkWidget * |
91 | gtk_pointer_focus_get_target (GtkPointerFocus *focus) |
92 | { |
93 | return focus->target; |
94 | } |
95 | |
96 | void |
97 | gtk_pointer_focus_set_implicit_grab (GtkPointerFocus *focus, |
98 | GtkWidget *grab_widget) |
99 | { |
100 | focus->grab_widget = grab_widget; |
101 | } |
102 | |
103 | GtkWidget * |
104 | gtk_pointer_focus_get_implicit_grab (GtkPointerFocus *focus) |
105 | { |
106 | return focus->grab_widget; |
107 | } |
108 | |
109 | void |
110 | gtk_pointer_focus_set_coordinates (GtkPointerFocus *focus, |
111 | double x, |
112 | double y) |
113 | { |
114 | focus->x = x; |
115 | focus->y = y; |
116 | } |
117 | |
118 | GtkWidget * |
119 | gtk_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 | |
133 | void |
134 | gtk_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 | |