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