Fix frequently ocurring typos :)
[claws.git] / src / plugins / notification / gtkhotkey / gtk-hotkey-x11-listener.c
1 /*
2  * This file is part of GtkHotkey.
3  * Copyright Mikkel Kamstrup Erlandsen, March, 2008
4  *
5  *   GtkHotkey is free software: you can redistribute it and/or modify
6  *   it under the terms of the GNU Lesser General Public License as published by
7  *   the Free Software Foundation, either version 3 of the License, or
8  *   (at your option) any later version.
9  *
10  *   GtkHotkey is distributed in the hope that it will be useful,
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *   GNU Lesser General Public License for more details.
14  *
15  *   You should have received a copy of the GNU Lesser General Public License
16  *   along with GtkHotkey.  If not, see <http://www.gnu.org/licenses/>.
17  */
18  
19 #include "gtk-hotkey-error.h"
20 #include "gtk-hotkey-x11-listener.h"
21 #include "gtk-hotkey-listener.h"
22 #include "gtk-hotkey-info.h"
23 #include "x11/tomboykeybinder.h"
24
25 struct _GtkHotkeyX11ListenerPrivate {
26         GList   *hotkeys;
27 };
28
29 enum  {
30         GTK_HOTKEY_X11_LISTENER_DUMMY_PROPERTY
31 };
32 static gboolean gtk_hotkey_x11_listener_real_bind_hotkey        (GtkHotkeyListener  *base,
33                                                                                                                          GtkHotkeyInfo          *hotkey,
34                                                                                                                          GError                         **error);
35
36 static gboolean gtk_hotkey_x11_listener_real_unbind_hotkey  (GtkHotkeyListener  *base,
37                                                                                                                          GtkHotkeyInfo          *hotkey,
38                                                                                                                          GError                         **error);
39
40 static void             hotkey_activated_cb                                                             (char                           *signature,
41                                                                                                                                  gpointer                       user_data);
42
43 static GtkHotkeyInfo*
44                                 find_hotkey_from_key_id                                                 (GtkHotkeyX11Listener   *self,
45                                                                                                                                  const gchar                    *key_id);
46
47 static gpointer gtk_hotkey_x11_listener_parent_class = NULL;
48
49
50 /**
51  * SECTION:gtk-hotkey-x11-listener
52  * @short_description: Implementation of #GtkHotkeyListener for a standard X11
53  *                     environment
54  * @see_also: #GtkHotkeyRegistry, #GtkHotkeyInfo
55  *
56  * This implementation of a #GtkHotkeyListener should work in any X11
57  * environment.
58  **/    
59
60 static gboolean
61 gtk_hotkey_x11_listener_real_bind_hotkey (GtkHotkeyListener *base,
62                                                                                           GtkHotkeyInfo         *hotkey,
63                                                                                           GError                        **error)
64 {
65         GtkHotkeyX11Listener    *self;
66         
67         g_return_val_if_fail (GTK_HOTKEY_IS_X11_LISTENER(base), FALSE);
68         g_return_val_if_fail (GTK_HOTKEY_IS_INFO (hotkey), FALSE);
69         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
70         
71         self = GTK_HOTKEY_X11_LISTENER (base);
72         
73         if (find_hotkey_from_key_id(self, 
74                                                                 gtk_hotkey_info_get_key_id (hotkey))) {
75                 g_warning ("Hotkey '%s' already registered. Ignoring register request.",
76                                    gtk_hotkey_info_get_key_id (hotkey));
77                 return FALSE;
78         }
79         
80         if (tomboy_keybinder_bind (gtk_hotkey_info_get_signature(hotkey),
81                                                            hotkey_activated_cb,
82                                                            self)) {
83                 self->priv->hotkeys = g_list_prepend (self->priv->hotkeys, hotkey);
84                 g_object_ref (hotkey);
85                 return TRUE;
86         }
87         
88         /* Bugger, we failed to bind */
89         g_set_error (error, GTK_HOTKEY_LISTENER_ERROR,
90                                  GTK_HOTKEY_LISTENER_ERROR_BIND,
91                                  "Failed to register hotkey '%s' with signature '%s'",
92                                  gtk_hotkey_info_get_key_id (hotkey),
93                                  gtk_hotkey_info_get_signature (hotkey));
94         
95         return FALSE;
96 }
97
98
99 static gboolean
100 gtk_hotkey_x11_listener_real_unbind_hotkey (GtkHotkeyListener   *base,
101                                                                                                 GtkHotkeyInfo           *hotkey,
102                                                                                                 GError                          **error)
103 {
104         GtkHotkeyX11Listener    *self;
105         GtkHotkeyInfo                   *saved_hk;
106         const gchar                             *signature;
107         
108         g_return_val_if_fail (GTK_HOTKEY_IS_X11_LISTENER (base), FALSE);
109         g_return_val_if_fail (GTK_HOTKEY_IS_INFO (hotkey), FALSE);
110         
111         self = GTK_HOTKEY_X11_LISTENER (base);
112         signature = gtk_hotkey_info_get_signature (hotkey);
113         saved_hk = find_hotkey_from_key_id (self, gtk_hotkey_info_get_key_id(hotkey));
114         
115         if (!saved_hk) {
116                 g_set_error (error, GTK_HOTKEY_LISTENER_ERROR,
117                                          GTK_HOTKEY_LISTENER_ERROR_UNBIND,
118                                          "Failed to unregister hotkey '%s' with signature '%s'. "
119                                          "No hotkey with that signature is known",
120                                          gtk_hotkey_info_get_key_id (hotkey),
121                                          signature);
122                 return FALSE;
123         }
124         
125         /* Remove actual keybinding */
126         tomboy_keybinder_unbind (signature, hotkey_activated_cb);
127         
128         /* Clean up refs */
129         self->priv->hotkeys = g_list_remove (self->priv->hotkeys, saved_hk);
130         g_object_unref (saved_hk);
131         
132         /* Clean up signal handler */
133         gulong handler = g_signal_handler_find (self,
134                                                                                         G_SIGNAL_MATCH_DATA | G_SIGNAL_MATCH_FUNC,
135                                                                                         0, 0, NULL, gtk_hotkey_info_activated,
136                                                                                         hotkey);
137         if (handler != 0) {
138                 g_signal_handler_disconnect (self, handler);
139         }
140         
141         return TRUE;
142                                                                                         
143 }
144
145 static void
146 hotkey_activated_cb     (char              *signature,
147                                          gpointer               user_data)
148 {
149         GtkHotkeyX11Listener    *self;
150         GtkHotkeyInfo                   *hotkey;
151         GList                                   *iter;
152         guint                                   event_time;
153         
154         g_return_if_fail (GTK_HOTKEY_IS_X11_LISTENER(user_data));
155         g_return_if_fail (signature != NULL);
156         
157         self = GTK_HOTKEY_X11_LISTENER(user_data);
158         event_time = tomboy_keybinder_get_current_event_time ();
159         
160         /* Trigger signals for hotkeys with matching signature */
161         for (iter = self->priv->hotkeys; iter; iter = iter->next) {
162                 hotkey = GTK_HOTKEY_INFO (iter->data);          
163                 if (g_str_equal (signature, gtk_hotkey_info_get_signature (hotkey))) {
164                                 gtk_hotkey_listener_activated (GTK_HOTKEY_LISTENER(self),
165                                                                                            hotkey, event_time);
166                                 gtk_hotkey_info_activated (hotkey, event_time);
167                 }
168         }
169         
170 }
171
172 static GtkHotkeyInfo*
173 find_hotkey_from_key_id (GtkHotkeyX11Listener   *self,
174                                                  const gchar                    *key_id)
175 {
176         GList                   *iter;
177         GtkHotkeyInfo   *hotkey;
178         
179         g_return_val_if_fail (GTK_HOTKEY_IS_X11_LISTENER(self), NULL);
180         g_return_val_if_fail (key_id != NULL, NULL);
181         
182         for (iter = self->priv->hotkeys; iter; iter = iter->next) {
183                 hotkey = GTK_HOTKEY_INFO (iter->data);
184                 
185                 if (g_str_equal (gtk_hotkey_info_get_key_id(hotkey), key_id))
186                         return hotkey;
187         }
188         
189         return NULL;
190 }
191
192 static void
193 gtk_hotkey_x11_listener_class_init (GtkHotkeyX11ListenerClass * klass)
194 {
195         gtk_hotkey_x11_listener_parent_class = g_type_class_peek_parent (klass);
196         
197         GTK_HOTKEY_LISTENER_CLASS (klass)->bind_hotkey =
198                                                                 gtk_hotkey_x11_listener_real_bind_hotkey;
199         GTK_HOTKEY_LISTENER_CLASS (klass)->unbind_hotkey =
200                                                                 gtk_hotkey_x11_listener_real_unbind_hotkey;
201         
202         /* Initialize the tomboy keybinder */
203         tomboy_keybinder_init ();
204 }
205
206
207 static void
208 gtk_hotkey_x11_listener_init (GtkHotkeyX11Listener * self)
209 {
210         self->priv = g_new0 (GtkHotkeyX11ListenerPrivate, 1);
211 }
212
213 static void
214 gtk_hotkey_x11_listener_finalize (GtkHotkeyX11Listener * self)
215 {
216         g_free(self->priv);
217 }
218
219 GType
220 gtk_hotkey_x11_listener_get_type (void)
221 {
222         static GType gtk_hotkey_x11_listener_type_id = 0;
223         
224         if (G_UNLIKELY (gtk_hotkey_x11_listener_type_id == 0)) {
225                 static const GTypeInfo g_define_type_info = {
226                         sizeof (GtkHotkeyX11ListenerClass),
227                         (GBaseInitFunc) NULL,
228                         (GBaseFinalizeFunc) gtk_hotkey_x11_listener_finalize,
229                         (GClassInitFunc) gtk_hotkey_x11_listener_class_init,
230                         (GClassFinalizeFunc) NULL,
231                         NULL,
232                         sizeof (GtkHotkeyX11Listener),
233                         0,
234                         (GInstanceInitFunc) gtk_hotkey_x11_listener_init
235                 };
236                 
237                 gtk_hotkey_x11_listener_type_id = g_type_register_static (GTK_HOTKEY_TYPE_LISTENER, "GtkHotkeyX11Listener", &g_define_type_info, 0);
238         }
239         return gtk_hotkey_x11_listener_type_id;
240 }