1 /* GIMP - The GNU Image Manipulation Program
2 * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
3 *
4 * gimpcontrollerwheel.c
5 * Copyright (C) 2004-2015 Michael Natterer <mitch@gimp.org>
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21 #include "config.h"
22
23 #include <gegl.h>
24 #undef GDK_MULTIHEAD_SAFE /* for gdk_keymap_get_default() */
25 #include <gtk/gtk.h>
26
27 #include "libgimpwidgets/gimpwidgets.h"
28
29 #include "widgets-types.h"
30
31 #include "gimpcontrollerwheel.h"
32 #include "gimphelp-ids.h"
33 #include "gimpwidgets-utils.h"
34
35 #include "gimp-intl.h"
36
37
38 typedef struct _WheelEvent WheelEvent;
39
40 struct _WheelEvent
41 {
42 const GdkScrollDirection direction;
43 const gchar *modifier_string;
44 GdkModifierType modifiers;
45 const gchar *name;
46 const gchar *blurb;
47 };
48
49
50 static void gimp_controller_wheel_constructed (GObject *object);
51
52 static gint gimp_controller_wheel_get_n_events (GimpController *controller);
53 static const gchar * gimp_controller_wheel_get_event_name (GimpController *controller,
54 gint event_id);
55 static const gchar * gimp_controller_wheel_get_event_blurb (GimpController *controller,
56 gint event_id);
57
58
59 G_DEFINE_TYPE (GimpControllerWheel, gimp_controller_wheel,
60 GIMP_TYPE_CONTROLLER)
61
62 #define parent_class gimp_controller_wheel_parent_class
63
64
65 static WheelEvent wheel_events[] =
66 {
67 { GDK_SCROLL_UP, NULL, 0,
68 "scroll-up",
69 N_("Scroll Up") },
70 { GDK_SCROLL_UP, "<Shift>", 0,
71 "scroll-up-shift",
72 N_("Scroll Up") },
73 { GDK_SCROLL_UP, "<Primary>", 0,
74 "scroll-up-primary",
75 N_("Scroll Up") },
76 { GDK_SCROLL_UP, "<Alt>", 0,
77 "scroll-up-alt",
78 N_("Scroll Up") },
79 { GDK_SCROLL_UP, "<Shift><Primary>", 0,
80 "scroll-up-shift-primary",
81 N_("Scroll Up") },
82 { GDK_SCROLL_UP, "<Shift><Alt>", 0,
83 "scroll-up-shift-alt",
84 N_("Scroll Up") },
85 { GDK_SCROLL_UP, "<Primary><Alt>", 0,
86 "scroll-up-primary-alt",
87 N_("Scroll Up") },
88 { GDK_SCROLL_UP, "<Shift><Primary><Alt>", 0,
89 "scroll-up-shift-primary-alt",
90 N_("Scroll Up") },
91
92 { GDK_SCROLL_DOWN, NULL, 0,
93 "scroll-down",
94 N_("Scroll Down") },
95 { GDK_SCROLL_DOWN, "<Shift>", 0,
96 "scroll-down-shift",
97 N_("Scroll Down") },
98 { GDK_SCROLL_DOWN, "<Primary>", 0,
99 "scroll-down-primary",
100 N_("Scroll Down") },
101 { GDK_SCROLL_DOWN, "<Alt>", 0,
102 "scroll-down-alt",
103 N_("Scroll Down") },
104 { GDK_SCROLL_DOWN, "<Shift><Primary>", 0,
105 "scroll-down-shift-primary",
106 N_("Scroll Down") },
107 { GDK_SCROLL_DOWN, "<Shift><Alt>", 0,
108 "scroll-down-shift-alt",
109 N_("Scroll Down") },
110 { GDK_SCROLL_DOWN, "<Primary><Alt>", 0,
111 "scroll-down-primary-alt",
112 N_("Scroll Down") },
113 { GDK_SCROLL_DOWN, "<Shift><Primary><Alt>", 0,
114 "scroll-down-shift-primary-alt",
115 N_("Scroll Down") },
116
117 { GDK_SCROLL_LEFT, NULL, 0,
118 "scroll-left",
119 N_("Scroll Left") },
120 { GDK_SCROLL_LEFT, "<Shift>", 0,
121 "scroll-left-shift",
122 N_("Scroll Left") },
123 { GDK_SCROLL_LEFT, "<Primary>", 0,
124 "scroll-left-primary",
125 N_("Scroll Left") },
126 { GDK_SCROLL_LEFT, "<Alt>", 0,
127 "scroll-left-alt",
128 N_("Scroll Left") },
129 { GDK_SCROLL_LEFT, "<Shift><Primary>", 0,
130 "scroll-left-shift-primary",
131 N_("Scroll Left") },
132 { GDK_SCROLL_LEFT, "<Shift><Alt>", 0,
133 "scroll-left-shift-alt",
134 N_("Scroll Left") },
135 { GDK_SCROLL_LEFT, "<Primary><Alt>", 0,
136 "scroll-left-primary-alt",
137 N_("Scroll Left") },
138 { GDK_SCROLL_LEFT, "<Shift><Primary><Alt>", 0,
139 "scroll-left-shift-primary-alt",
140 N_("Scroll Left") },
141
142 { GDK_SCROLL_RIGHT, NULL, 0,
143 "scroll-right",
144 N_("Scroll Right") },
145 { GDK_SCROLL_RIGHT, "<Shift>", 0,
146 "scroll-right-shift",
147 N_("Scroll Right") },
148 { GDK_SCROLL_RIGHT, "<Primary>", 0,
149 "scroll-right-primary",
150 N_("Scroll Right") },
151 { GDK_SCROLL_RIGHT, "<Alt>", 0,
152 "scroll-right-alt",
153 N_("Scroll Right") },
154 { GDK_SCROLL_RIGHT, "<Shift><Primary>", 0,
155 "scroll-right-shift-primary",
156 N_("Scroll Right") },
157 { GDK_SCROLL_RIGHT, "<Shift><Alt>", 0,
158 "scroll-right-shift-alt",
159 N_("Scroll Right") },
160 { GDK_SCROLL_RIGHT, "<Primary><Alt>", 0,
161 "scroll-right-primary-alt",
162 N_("Scroll Right") },
163 { GDK_SCROLL_RIGHT, "<Shift><Primary><Alt>", 0,
164 "scroll-right-shift-primary-alt",
165 N_("Scroll Right") }
166 };
167
168
169 static void
gimp_controller_wheel_class_init(GimpControllerWheelClass * klass)170 gimp_controller_wheel_class_init (GimpControllerWheelClass *klass)
171 {
172 GObjectClass *object_class = G_OBJECT_CLASS (klass);
173 GimpControllerClass *controller_class = GIMP_CONTROLLER_CLASS (klass);
174
175 object_class->constructed = gimp_controller_wheel_constructed;
176
177 controller_class->name = _("Mouse Wheel");
178 controller_class->help_id = GIMP_HELP_CONTROLLER_WHEEL;
179 controller_class->icon_name = GIMP_ICON_CONTROLLER_WHEEL;
180
181 controller_class->get_n_events = gimp_controller_wheel_get_n_events;
182 controller_class->get_event_name = gimp_controller_wheel_get_event_name;
183 controller_class->get_event_blurb = gimp_controller_wheel_get_event_blurb;
184 }
185
186 static void
gimp_controller_wheel_init(GimpControllerWheel * wheel)187 gimp_controller_wheel_init (GimpControllerWheel *wheel)
188 {
189 static gboolean events_initialized = FALSE;
190
191 if (! events_initialized)
192 {
193 GdkKeymap *keymap = gdk_keymap_get_default ();
194 gint i;
195
196 for (i = 0; i < G_N_ELEMENTS (wheel_events); i++)
197 {
198 WheelEvent *wevent = &wheel_events[i];
199
200 if (wevent->modifier_string)
201 {
202 gtk_accelerator_parse (wevent->modifier_string, NULL,
203 &wevent->modifiers);
204 gdk_keymap_map_virtual_modifiers (keymap, &wevent->modifiers);
205 }
206
207 if (wevent->modifiers != 0)
208 {
209 wevent->blurb =
210 g_strdup_printf ("%s (%s)", gettext (wevent->blurb),
211 gimp_get_mod_string (wevent->modifiers));
212 }
213 else
214 {
215 wevent->blurb = gettext (wevent->blurb);
216 }
217 }
218
219 events_initialized = TRUE;
220 }
221 }
222
223 static void
gimp_controller_wheel_constructed(GObject * object)224 gimp_controller_wheel_constructed (GObject *object)
225 {
226 G_OBJECT_CLASS (parent_class)->constructed (object);
227
228 g_object_set (object,
229 "name", _("Mouse Wheel Events"),
230 "state", _("Ready"),
231 NULL);
232 }
233
234 static gint
gimp_controller_wheel_get_n_events(GimpController * controller)235 gimp_controller_wheel_get_n_events (GimpController *controller)
236 {
237 return G_N_ELEMENTS (wheel_events);
238 }
239
240 static const gchar *
gimp_controller_wheel_get_event_name(GimpController * controller,gint event_id)241 gimp_controller_wheel_get_event_name (GimpController *controller,
242 gint event_id)
243 {
244 if (event_id < 0 || event_id >= G_N_ELEMENTS (wheel_events))
245 return NULL;
246
247 return wheel_events[event_id].name;
248 }
249
250 static const gchar *
gimp_controller_wheel_get_event_blurb(GimpController * controller,gint event_id)251 gimp_controller_wheel_get_event_blurb (GimpController *controller,
252 gint event_id)
253 {
254 if (event_id < 0 || event_id >= G_N_ELEMENTS (wheel_events))
255 return NULL;
256
257 return wheel_events[event_id].blurb;
258 }
259
260 gboolean
gimp_controller_wheel_scroll(GimpControllerWheel * wheel,const GdkEventScroll * sevent)261 gimp_controller_wheel_scroll (GimpControllerWheel *wheel,
262 const GdkEventScroll *sevent)
263 {
264 gint i;
265
266 g_return_val_if_fail (GIMP_IS_CONTROLLER_WHEEL (wheel), FALSE);
267 g_return_val_if_fail (sevent != NULL, FALSE);
268
269 /* start with the last event because the last ones in the
270 * up,down,left,right groups have the most keyboard modifiers
271 */
272 for (i = G_N_ELEMENTS (wheel_events) - 1; i >= 0; i--)
273 {
274 if (wheel_events[i].direction == sevent->direction &&
275 (wheel_events[i].modifiers & sevent->state) ==
276 wheel_events[i].modifiers)
277 {
278 GimpControllerEvent controller_event;
279 GimpControllerEventTrigger *trigger;
280
281 trigger = (GimpControllerEventTrigger *) &controller_event;
282
283 trigger->type = GIMP_CONTROLLER_EVENT_TRIGGER;
284 trigger->source = GIMP_CONTROLLER (wheel);
285 trigger->event_id = i;
286
287 return gimp_controller_event (GIMP_CONTROLLER (wheel),
288 &controller_event);
289 }
290 }
291
292 return FALSE;
293 }
294