1 /** @file
2 * Collection of shorthands to deal with GDK events.
3 */
4 /* Authors:
5 * Krzysztof KosiĆski <tweenk.pl@gmail.com>
6 *
7 * Copyright (C) 2009 Authors
8 * Released under GNU GPL, read the file 'COPYING' for more information
9 */
11 #include <cstring>
12 #include <gdk/gdk.h>
13 #include <gdk/gdkkeysyms.h>
14 #include "display/sp-canvas.h"
15 #include "ui/tool/event-utils.h"
17 namespace Inkscape {
18 namespace UI {
21 guint shortcut_key(GdkEventKey const &event)
22 {
23 guint shortcut_key = 0;
24 gdk_keymap_translate_keyboard_state(
25 gdk_keymap_get_for_display(gdk_display_get_default()),
26 event.hardware_keycode,
27 (GdkModifierType) event.state,
28 0 /*event->key.group*/,
29 &shortcut_key, NULL, NULL, NULL);
30 return shortcut_key;
31 }
33 unsigned combine_key_events(guint keyval, gint mask)
34 {
35 GdkEvent *event_next;
36 gint i = 0;
38 event_next = gdk_event_get();
39 // while the next event is also a key notify with the same keyval and mask,
40 while (event_next && (event_next->type == GDK_KEY_PRESS || event_next->type == GDK_KEY_RELEASE)
41 && event_next->key.keyval == keyval
42 && (!mask || event_next->key.state & mask)) {
43 if (event_next->type == GDK_KEY_PRESS)
44 i ++;
45 // kill it
46 gdk_event_free(event_next);
47 // get next
48 event_next = gdk_event_get();
49 }
50 // otherwise, put it back onto the queue
51 if (event_next) gdk_event_put(event_next);
53 return i;
54 }
56 unsigned combine_motion_events(SPCanvas *canvas, GdkEventMotion &event, gint mask)
57 {
58 GdkEvent *event_next;
59 gint i = 0;
60 event.x -= canvas->x0;
61 event.y -= canvas->y0;
63 event_next = gdk_event_get();
64 // while the next event is also a motion notify
65 while (event_next && event_next->type == GDK_MOTION_NOTIFY
66 && (!mask || event_next->motion.state & mask))
67 {
68 if (event_next->motion.device == event.device) {
69 GdkEventMotion &next = event_next->motion;
70 event.send_event = next.send_event;
71 event.time = next.time;
72 event.x = next.x;
73 event.y = next.y;
74 event.state = next.state;
75 event.is_hint = next.is_hint;
76 event.x_root = next.x_root;
77 event.y_root = next.y_root;
78 if (event.axes && next.axes) {
79 memcpy(event.axes, next.axes, event.device->num_axes);
80 }
81 }
83 // kill it
84 gdk_event_free(event_next);
85 event_next = gdk_event_get();
86 i++;
87 }
88 // otherwise, put it back onto the queue
89 if (event_next)
90 gdk_event_put(event_next);
91 event.x += canvas->x0;
92 event.y += canvas->y0;
94 return i;
95 }
97 /** Returns the modifier state valid after this event. Use this when you process events
98 * that change the modifier state. Currently handles only Shift, Ctrl, Alt. */
99 unsigned state_after_event(GdkEvent *event)
100 {
101 unsigned state = 0;
102 switch (event->type) {
103 case GDK_KEY_PRESS:
104 state = event->key.state;
105 switch(shortcut_key(event->key)) {
106 case GDK_Shift_L:
107 case GDK_Shift_R:
108 state |= GDK_SHIFT_MASK;
109 break;
110 case GDK_Control_L:
111 case GDK_Control_R:
112 state |= GDK_CONTROL_MASK;
113 break;
114 case GDK_Alt_L:
115 case GDK_Alt_R:
116 state |= GDK_MOD1_MASK;
117 break;
118 default: break;
119 }
120 break;
121 case GDK_KEY_RELEASE:
122 state = event->key.state;
123 switch(shortcut_key(event->key)) {
124 case GDK_Shift_L:
125 case GDK_Shift_R:
126 state &= ~GDK_SHIFT_MASK;
127 break;
128 case GDK_Control_L:
129 case GDK_Control_R:
130 state &= ~GDK_CONTROL_MASK;
131 break;
132 case GDK_Alt_L:
133 case GDK_Alt_R:
134 state &= ~GDK_MOD1_MASK;
135 break;
136 default: break;
137 }
138 break;
139 default: break;
140 }
141 return state;
142 }
144 } // namespace UI
145 } // namespace Inkscape
147 /*
148 Local Variables:
149 mode:c++
150 c-file-style:"stroustrup"
151 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
152 indent-tabs-mode:nil
153 fill-column:99
154 End:
155 */
156 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :