f091aeaaf4c0be9abf9409e44d76bf8907dceef9
[claws.git] / src / plugins / notification / gtkhotkey / gtk-hotkey-info.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-info.h"
20 #include "gtk-hotkey-error.h"
21 #include "gtk-hotkey-listener.h"
22
23 struct _GtkHotkeyInfoPrivate {
24         gchar           *app_id;
25         gchar           *key_id;
26         GAppInfo        *app_info;
27         gchar           *signature;
28         gchar           *description;
29         GtkHotkeyListener       *listener;
30 };
31 #define GTK_HOTKEY_INFO_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_HOTKEY_TYPE_INFO, GtkHotkeyInfoPrivate))
32
33 enum  {
34         GTK_HOTKEY_INFO_DUMMY_PROPERTY,
35         GTK_HOTKEY_INFO_BOUND,
36         GTK_HOTKEY_INFO_APPLICATION_ID,
37         GTK_HOTKEY_INFO_KEY_ID,
38         GTK_HOTKEY_INFO_APP_INFO,
39         GTK_HOTKEY_INFO_SIGNATURE,
40         GTK_HOTKEY_INFO_DESCRIPTION,
41 };
42
43 enum {
44         ACTIVATED,
45         
46         LAST_SIGNAL
47 };
48
49 guint                           info_signals[LAST_SIGNAL] = { 0 };
50
51 static gpointer         gtk_hotkey_info_parent_class = NULL;
52
53 static void                     gtk_hotkey_info_finalize (GObject * obj);
54
55 /**
56  * SECTION:gtk-hotkey-info
57  * @short_description: Primary representation of a hotkey
58  * @see_also: #GtkHotkeyRegistry
59  *
60  * #GtkHotkeyInfo is the primary object around which the GtkHotkey library
61  * revolves.
62  *
63  * Hotkeys are stored and managed via a #GtkHotkeyRegistry, while the actual
64  * binding and listening for key-presses is done by a #GtkHotkeyListener.
65  **/
66
67
68 /**
69  * gtk_hotkey_info_bind:
70  * @self: The hotkey to bind
71  * @error: Place to return a #GError, or %NULL to ignore
72  *
73  * Register the hotkey with the system. The #GtkHotkeyInfo::activated signal
74  * will now be emitted when the user presses the keyboard combination
75  * matching the hotkey's signature.
76  *
77  * Returns: %TRUE on success, and %FALSE on error in which case @error
78  *          is also set
79  **/
80 gboolean
81 gtk_hotkey_info_bind (GtkHotkeyInfo* self, GError **error)
82 {
83         gboolean result;
84         
85         g_return_val_if_fail (GTK_HOTKEY_IS_INFO (self), FALSE);
86         
87         if (gtk_hotkey_info_is_bound(self)) {
88                 g_set_error (error, GTK_HOTKEY_LISTENER_ERROR,
89                                          GTK_HOTKEY_LISTENER_ERROR_BIND,
90                                          "Can not bind hotkey '%s' with signature '%s'. "
91                                          "It is already bound",
92                                          gtk_hotkey_info_get_key_id(self),
93                                          gtk_hotkey_info_get_signature(self));
94                 return FALSE;
95         }
96         
97         if (!self->priv->listener)
98                 self->priv->listener = gtk_hotkey_listener_get_default ();
99         
100         g_return_val_if_fail (GTK_HOTKEY_IS_LISTENER(self->priv->listener), FALSE);
101         
102         result = gtk_hotkey_listener_bind_hotkey (self->priv->listener, self, error);
103         if (!result) {
104                 g_object_unref (self->priv->listener);
105                 self->priv->listener = NULL;
106         }
107         
108         if (result)
109                 g_object_notify (G_OBJECT(self), "bound");
110         
111         return result;
112 }
113
114 /**
115  * gtk_hotkey_info_unbind
116  * @self: The hotkey to unbind
117  * @error: Place to return a #GError, or %NULL to ignore
118  * @returns: %TRUE on success, and %FALSE on error in which case @error
119  *          is also set
120  *
121  * Remove the hotkey binding from the system. The #GtkHotkeyInfo::activated
122  * signal will no longer be emitted when the hotkey is pressed.
123  */
124 gboolean
125 gtk_hotkey_info_unbind (GtkHotkeyInfo* self, GError **error)
126 {       
127         gboolean result;
128         
129         g_return_val_if_fail (GTK_HOTKEY_IS_INFO (self), FALSE);
130         
131         if (!gtk_hotkey_info_is_bound(self)) {
132                 g_set_error (error, GTK_HOTKEY_LISTENER_ERROR,
133                                          GTK_HOTKEY_LISTENER_ERROR_UNBIND,
134                                          "Can not unbind hotkey '%s' with signature '%s'."
135                                          "It is not bound",
136                                          gtk_hotkey_info_get_key_id(self),
137                                          gtk_hotkey_info_get_signature(self));
138                 return FALSE;
139         }
140         
141         g_return_val_if_fail (GTK_HOTKEY_IS_LISTENER(self->priv->listener), FALSE);
142         
143         result = gtk_hotkey_listener_unbind_hotkey (self->priv->listener, self,
144                                                                                                 error);
145         
146         g_object_unref (self->priv->listener);
147         self->priv->listener = NULL;
148         
149         if (result)
150                 g_object_notify (G_OBJECT(self), "bound");
151         
152         return result;
153 }
154
155 /**
156  * gtk_hotkey_info_is_bound
157  * @self: The hotkey to inspect
158  * @returns: %TRUE if gtk_hotkey_info_bind() has been called and returned %TRUE
159  *           on this hotkey
160  *
161  * Check whether the hotkey has been successfully bound to a #GtkHotkeyListener.
162  */
163 gboolean
164 gtk_hotkey_info_is_bound (GtkHotkeyInfo* self)
165 {       
166         return (self->priv->listener != NULL);
167 }
168
169 /**
170  * gtk_hotkey_info_get_application_id
171  * @self:
172  *
173  * Get the unique system identifier for the hotkey. See 
174  * #GtkHotkeyInfo:application-id for details.
175  */
176 const gchar*
177 gtk_hotkey_info_get_application_id (GtkHotkeyInfo* self)
178 {
179         g_return_val_if_fail (GTK_HOTKEY_IS_INFO (self), NULL);
180         return self->priv->app_id;
181 }
182
183 /**
184  * gtk_hotkey_info_get_key_id
185  * @self:
186  *
187  * Get the identifier the owning application use to identify this hotkey.
188  * See #GtkHotkeyInfo:key-id for details.
189  */
190 const gchar*
191 gtk_hotkey_info_get_key_id (GtkHotkeyInfo* self)
192 {
193         g_return_val_if_fail (GTK_HOTKEY_IS_INFO (self), NULL);
194         return self->priv->key_id;
195 }
196
197 /**
198  * gtk_hotkey_info_get_app_info
199  * @self:
200  *
201  * Not to be confused with the value of the #GtkHotkeyInfo:application-id
202  * property. The hotkey can be associated with an installed desktop application
203  * via a #GAppInfo. This is not mandatory and this method returns %NULL
204  * if no desktop application has been associated with this hotkey.
205  *
206  * See the #GtkHotkeyInfo:app-info property for details.
207  */
208 GAppInfo*
209 gtk_hotkey_info_get_app_info (GtkHotkeyInfo* self)
210 {
211         g_return_val_if_fail (GTK_HOTKEY_IS_INFO (self), NULL);
212         return self->priv->app_info;
213 }
214
215 /**
216  * gtk_hotkey_info_get_signature
217  * @self:
218  *
219  * Get the keyboard signature of the hotkey. This could for example be
220  * '&lt;Alt&gt;F3' or '&lt;Control&gt;&lt;Shift&gt;G'.
221  */
222 const gchar*
223 gtk_hotkey_info_get_signature (GtkHotkeyInfo* self)
224 {
225         g_return_val_if_fail (GTK_HOTKEY_IS_INFO (self), NULL);
226         return self->priv->signature;
227 }
228
229 /**
230  * gtk_hotkey_info_get_description
231  * @self:
232  * @returns: The description of the hotkey or %NULL if none is set
233  *
234  * Get the free form description of the hotkey. The description is not guaranteed
235  * to be set and may be %NULL.
236  *
237  * FIXME: Do we need to take i18n into account here?
238  */
239 const gchar*
240 gtk_hotkey_info_get_description (GtkHotkeyInfo* self)
241 {
242         g_return_val_if_fail (GTK_HOTKEY_IS_INFO(self), NULL);
243         return self->priv->description;
244 }
245
246 /**
247  * gtk_hotkey_info_set_description
248  * @self:
249  *
250  * Set a description for the hotkey. See also gtk_hotkey_info_get_description().
251  */
252 void
253 gtk_hotkey_info_set_description (GtkHotkeyInfo* self, const gchar *description)
254 {
255         g_return_if_fail (GTK_HOTKEY_IS_INFO(self));
256         g_object_set (self, "description", description, NULL); 
257 }
258
259 /**
260  * gtk_hotkey_info_equals
261  * @hotkey1: The first hotkey to compare
262  * @hotkey2: Second hotkey to compare to
263  * @sloppy_equals: If %TRUE sloppy equality will be used. This ignores
264  *                 the #GtkHotkeyInfo:description and #GtkHotkeyInfo:app-info
265  *                 properties of the objects.
266  * @returns: %TRUE if all the properties of the hotkeys match. Two %NULL hotkeys
267  *           are also considered equal.
268  *
269  * Compare two #GtkHotkeyInfo<!-- -->s to see if they are equal. This method
270  * allows an optional 'sloppy equality' which ignores #GtkHotkeyInfo:description
271  * and #GtkHotkeyInfo:app-info.
272  */
273 gboolean
274 gtk_hotkey_info_equals (GtkHotkeyInfo *hotkey1,
275                                                 GtkHotkeyInfo *hotkey2,
276                                                 gboolean                        sloppy_equals)
277 {       
278         if (hotkey1 == hotkey2) return TRUE;
279         
280         g_return_val_if_fail (GTK_HOTKEY_IS_INFO (hotkey1), FALSE);
281         g_return_val_if_fail (GTK_HOTKEY_IS_INFO (hotkey2), FALSE);
282         
283         if (!g_str_equal (gtk_hotkey_info_get_application_id (hotkey1),
284                                           gtk_hotkey_info_get_application_id (hotkey2)))
285                 return FALSE;
286         
287         if (!g_str_equal (gtk_hotkey_info_get_key_id (hotkey1),
288                                           gtk_hotkey_info_get_key_id (hotkey2)))
289                 return FALSE;
290         
291         if (!g_str_equal (gtk_hotkey_info_get_signature (hotkey1),
292                                           gtk_hotkey_info_get_signature (hotkey2)))
293                 return FALSE;
294         
295         /* For sloppy equality this is good enough */
296         if (sloppy_equals)
297                 return TRUE;
298         
299         const gchar     *d1, *d2;
300         d1 = gtk_hotkey_info_get_description (hotkey1);
301         d2 = gtk_hotkey_info_get_description (hotkey2);
302         if (d1 != NULL && d2 != NULL) {
303                 if (!g_str_equal (gtk_hotkey_info_get_description (hotkey1),
304                                                   gtk_hotkey_info_get_description (hotkey2)))
305                         return FALSE;
306         } else if (d1 != d2)
307                 return FALSE;
308         /* The case d1 == d2 == NULL will pass through the above */
309         
310         GAppInfo        *app1, *app2;
311         app1 = gtk_hotkey_info_get_app_info (hotkey1);
312         app2 = gtk_hotkey_info_get_app_info (hotkey2);
313         if (app1 != NULL && app2 != NULL) {
314                 if (!g_app_info_equal (app1, app2))
315                         return FALSE;
316         } else if (app1 != app2)
317                 return FALSE;
318         /* As above, if app1 == app2 == NULL we count equality */
319         
320         return TRUE;
321 }
322
323 /**
324  * gtk_hotkey_info_activated
325  * @self: #GtkHotkeyInfo to emit the #GtkHotkeyInfo::activated signal
326  * @event_time: The system time the event happened on. This is useful for
327  *              applications to pass through focus stealing prevention when
328  *              mapping windows
329  *
330  * Emit the #GtkHotkeyInfo::activated signal on a hotkey. Mainly called
331  * by #GtkHotkeyListener implementations. This method should not normally be
332  * used by applications.
333  */
334 void
335 gtk_hotkey_info_activated (GtkHotkeyInfo* self, guint event_time)
336 {
337         g_return_if_fail (GTK_HOTKEY_IS_INFO(self));
338         
339         g_signal_emit (self, info_signals[ACTIVATED], 0, event_time);
340 }
341
342 /**
343  * gtk_hotkey_info_new:
344  * @app_id: Unique identifier the running application can choose for it self. 
345  *          May be a free form string, but a descriptive name is encouraged
346  * @key_id: A key the application uses to recognize the hotkey. May be a free 
347  *          form string, but a descriptive name is encouraged
348  * @signature: A key press signature parsable by gtk_accelerator_parse(). For 
349  *             examplpe '&lt;Alt&gt;F3' or '&lt;Control&gt;&lt;Shift&gt;G'.
350  * @app_info: An optional #GAppInfo to associate with the hotkey. Pass %NULL to
351  *            ignore this
352  * @returns: A new #GtkHotkeyInfo or %NULL on error. Error conditions could for 
353  *           example be invalid an invalid @signature, or %NULL arguments.
354  *
355  * Create a new hotkey. To actually trigger the hotkey when the user enters
356  * the right keyboard combination call gtk_hotkey_info_bind(). To save and
357  * load your hotkey settings use the #GtkHotkeyRegistry provided by
358  * gtk_hotkey_registry_get_default().
359  **/
360 GtkHotkeyInfo*
361 gtk_hotkey_info_new (const gchar        *app_id,
362                                          const gchar    *key_id,
363                                          const gchar    *signature,
364                                          GAppInfo               *app_info)
365 {
366         GtkHotkeyInfo * self;
367         
368         g_return_val_if_fail (app_id != NULL, NULL);
369         g_return_val_if_fail (key_id != NULL, NULL);
370         
371         /* A NULL app_info is ok, but it better be a GAppInfo then */
372         if (app_info != NULL)
373                 g_return_val_if_fail (G_IS_APP_INFO(app_info), NULL);
374         
375         self = g_object_new (GTK_HOTKEY_TYPE_INFO, "application-id", app_id,
376                                                                                            "key-id", key_id,
377                                                                                            "signature", signature,
378                                                                                            "app-info", app_info,
379                                                                                                 NULL);
380         return self;
381 }
382
383 static void
384 gtk_hotkey_info_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec)
385 {
386         GtkHotkeyInfo * self;
387         
388         self = GTK_HOTKEY_INFO (object);
389         
390         switch (property_id) {
391                 case GTK_HOTKEY_INFO_BOUND:
392                         g_value_set_boolean (value,
393                                                                  (self->priv->listener != NULL));
394                         break;
395                 case GTK_HOTKEY_INFO_APPLICATION_ID:
396                         g_value_set_string (value,
397                                                                 gtk_hotkey_info_get_application_id (self));
398                         break;
399                 case GTK_HOTKEY_INFO_KEY_ID:
400                         g_value_set_string (value,
401                                                                 gtk_hotkey_info_get_key_id (self));
402                         break;
403                 case GTK_HOTKEY_INFO_APP_INFO:
404                         g_value_set_object (value,
405                                                                 gtk_hotkey_info_get_app_info (self));
406                         break;
407                 case GTK_HOTKEY_INFO_SIGNATURE:
408                         g_value_set_string (value,
409                                                                 gtk_hotkey_info_get_signature (self));
410                         break;
411                 case GTK_HOTKEY_INFO_DESCRIPTION:
412                         g_value_set_string (value,
413                                                                 gtk_hotkey_info_get_description (self));
414                         break;
415                 default:
416                         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
417                         break;
418         }
419 }
420
421
422 static void
423 gtk_hotkey_info_set_property (GObject * object, guint property_id, const GValue * value, GParamSpec * pspec)
424 {
425         GtkHotkeyInfo                   *self;
426         GtkHotkeyInfoPrivate    *priv;
427         
428         self = GTK_HOTKEY_INFO (object);
429         priv = self->priv;
430         
431         switch (property_id) {
432                 case GTK_HOTKEY_INFO_BOUND:
433                         g_critical ("Writing to read only property 'bound'");
434                         break;
435                 case GTK_HOTKEY_INFO_APPLICATION_ID:
436                         if (priv->app_id)
437                                 g_critical ("Overwriting construct only property 'application-id'");
438                         priv->app_id = g_value_dup_string (value);
439                         break;
440                 case GTK_HOTKEY_INFO_KEY_ID:
441                         if (priv->key_id)
442                                 g_critical ("Overwriting construct only property 'key-id'");
443                         priv->key_id = g_value_dup_string (value);
444                         break;
445                 case GTK_HOTKEY_INFO_APP_INFO:
446                         if (priv->app_info)
447                                 g_critical ("Overwriting construct only property 'app-info'");
448                         priv->app_info = g_value_dup_object (value);
449                         break;
450                 case GTK_HOTKEY_INFO_SIGNATURE:
451                         if (priv->signature)
452                                 g_critical ("Overwriting construct only property 'signature'");
453                         priv->signature = g_value_dup_string (value);
454                         break;
455                 case GTK_HOTKEY_INFO_DESCRIPTION:
456                         if (priv->description)
457                                 g_free(priv->description);
458                         priv->description = g_value_dup_string (value);
459                         break;
460                 default:
461                         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
462                         break;
463         }
464 }
465
466
467 static void
468 gtk_hotkey_info_class_init (GtkHotkeyInfoClass * klass)
469 {
470         gtk_hotkey_info_parent_class = g_type_class_peek_parent (klass);
471         g_type_class_add_private (klass, sizeof (GtkHotkeyInfoPrivate));
472         
473         G_OBJECT_CLASS (klass)->get_property = gtk_hotkey_info_get_property;
474         G_OBJECT_CLASS (klass)->set_property = gtk_hotkey_info_set_property;
475         G_OBJECT_CLASS (klass)->finalize = gtk_hotkey_info_finalize;
476         
477         /**
478          * GtkHotkeyInfo:bound
479          *
480          * Property reflecting whether or not this hotkey has been bound to
481          * a #GtkHotkeyListener. If this property is %TRUE you will receive
482          * #GtkHotkeyInfo::activated signals when the hotkey is triggered
483          * by the user.
484          */
485         g_object_class_install_property (G_OBJECT_CLASS (klass),
486                                                                          GTK_HOTKEY_INFO_BOUND,
487                                                                          g_param_spec_boolean ("bound",
488                                                                                                                   "Is Bound",
489                                                                                                                   "Whether or not the hotkey is bound to a GtkHotkeyListener",
490                                                                                                                   FALSE, 
491                                                                                                                   G_PARAM_READABLE));
492         
493         /**
494          * GtkHotkeyInfo:application-id
495          *
496          * A free form string chosen by the application using the hotkey, under
497          * which the application identifies itself.
498          */
499         g_object_class_install_property (G_OBJECT_CLASS (klass),
500                                                                          GTK_HOTKEY_INFO_APPLICATION_ID,
501                                                                          g_param_spec_string ("application-id",
502                                                                                                                   "Application Id",
503                                                                                                                   "Globally unique application id",
504                                                                                                                   NULL, 
505                                                                                                                   G_PARAM_READABLE | G_PARAM_WRITABLE |
506                                                                                                                   G_PARAM_CONSTRUCT_ONLY));
507         
508         /**
509          * GtkHotkeyInfo:key-id
510          *
511          * A free form string the application using the hotkey has attributed
512          * the hotkey so that it can be identified later on. Applications are
513          * encouraged to choose descriptive key ids.
514          */
515         g_object_class_install_property (G_OBJECT_CLASS (klass),
516                                                                          GTK_HOTKEY_INFO_KEY_ID,
517                                                                          g_param_spec_string ("key-id",
518                                                                                                                   "Hotkey Id",
519                                                                                                                   "Globally unique identifier for the hotkey",
520                                                                                                                   NULL, 
521                                                                                                                   G_PARAM_READABLE | G_PARAM_WRITABLE |
522                                                                                                                   G_PARAM_CONSTRUCT_ONLY));
523         
524         /**
525          * GtkHotkeyInfo:app-info
526          *
527          * A #GAppInfo associated with the key. This is mainly useful for external
528          * applications which can use the information provided by the #GAppInfo
529          * to display meaningful messages to the user. Like 'The keyboard 
530          * combination &lt;Alt&gt;F3' is already assigned to the application
531          * "Deskbar Applet", please select another'.
532          */
533         g_object_class_install_property (G_OBJECT_CLASS (klass),
534                                                                          GTK_HOTKEY_INFO_APP_INFO,
535                                                                          g_param_spec_object ("app-info",
536                                                                                                                   "Application Information",
537                                                                                                                   "Object holding metadata about "
538                                                                                                                   "the hotkey's application",
539                                                                                                                   G_TYPE_APP_INFO, 
540                                                                                                                   G_PARAM_READABLE | G_PARAM_WRITABLE |
541                                                                                                                   G_PARAM_CONSTRUCT_ONLY));
542         
543         /**
544          * GtkHotkeyInfo:signature
545          *
546          * The keyboard signature of the hotkey. This could for example by
547          * '&lt;Alt&gt;F3' or '&lt;Control&gt;&lt;Shift&gt;G'. The signature should be parsable by
548          * gtk_accelerator_parse().
549          */
550         g_object_class_install_property (G_OBJECT_CLASS (klass),
551                                                                          GTK_HOTKEY_INFO_SIGNATURE,
552                                                                          g_param_spec_string ("signature",
553                                                                                                                   "Signature",
554                                                                                                                   "String defining the keyboard shortcut",
555                                                                                                                   NULL, 
556                                                                                                                   G_PARAM_READABLE | G_PARAM_WRITABLE |
557                                                                                                                   G_PARAM_CONSTRUCT_ONLY));
558         
559         /**
560          * GtkHotkeyInfo:description
561          *
562          * An optional free form description of the hotkey.
563          */
564         g_object_class_install_property (G_OBJECT_CLASS (klass),
565                                                                          GTK_HOTKEY_INFO_DESCRIPTION,
566                                                                          g_param_spec_string ("description",
567                                                                                                                   "Description",
568                                                                                                                   "Short description of what happens upon activation",
569                                                                                                                   "", 
570                                                                                                                   G_PARAM_READABLE | G_PARAM_WRITABLE));
571         
572         /**
573          * GtkHotkeyInfo::activated:
574          * @hotkey: a #GtkHotkeyInfo for the hotkey that was activated
575          * @event_time: Time for event triggering the keypress. This is mainly
576          *              used to pass to window management functions to pass through
577          *              focus stealing prevention
578          *
579          * Emitted when a hotkey has been activated.
580          */
581         info_signals[ACTIVATED] = \
582         g_signal_new ("activated",
583                                   GTK_HOTKEY_TYPE_INFO,
584                                   G_SIGNAL_RUN_LAST,
585                                   0, NULL, NULL,
586                                   g_cclosure_marshal_VOID__UINT,
587                                   G_TYPE_NONE, 1,
588                                   G_TYPE_UINT);
589 }
590
591
592 static void
593 gtk_hotkey_info_init (GtkHotkeyInfo * self)
594 {
595         self->priv = GTK_HOTKEY_INFO_GET_PRIVATE (self);
596         
597         self->priv->app_id = NULL;
598         self->priv->key_id = NULL;
599         self->priv->app_info = NULL;
600 }
601
602
603 static void
604 gtk_hotkey_info_finalize (GObject * obj)
605 {
606         GtkHotkeyInfo                   *self;
607         GtkHotkeyInfoPrivate    *priv;
608         
609         self = GTK_HOTKEY_INFO (obj);
610         priv = self->priv;
611         
612         if (priv->app_id)
613                 g_free (priv->app_id);
614         if (priv->key_id)
615                 g_free (priv->key_id);
616         if (priv->app_info)
617                 g_object_unref (priv->app_info);
618         if (priv->signature)
619                 g_free (priv->signature);
620         if (priv->description)
621                 g_free (priv->description);
622         if (GTK_HOTKEY_IS_LISTENER (priv->listener))
623                 g_object_unref (priv->listener);
624         
625         G_OBJECT_CLASS (gtk_hotkey_info_parent_class)->finalize (obj);
626 }
627
628
629 GType
630 gtk_hotkey_info_get_type (void)
631 {
632         static GType gtk_hotkey_info_type_id = 0;
633         
634         if (G_UNLIKELY (gtk_hotkey_info_type_id == 0)) {
635                 static const GTypeInfo g_define_type_info = {
636                         sizeof (GtkHotkeyInfoClass),
637                         (GBaseInitFunc) NULL,
638                         (GBaseFinalizeFunc) NULL,
639                         (GClassInitFunc) gtk_hotkey_info_class_init,
640                         (GClassFinalizeFunc) NULL,
641                         NULL,
642                         sizeof (GtkHotkeyInfo),
643                         0,
644                         (GInstanceInitFunc) gtk_hotkey_info_init
645                 };
646                 
647                 gtk_hotkey_info_type_id = g_type_register_static (G_TYPE_OBJECT,
648                                                                                                                   "GtkHotkeyInfo",
649                                                                                                                   &g_define_type_info,
650                                                                                                                   0);
651         }
652         
653         return gtk_hotkey_info_type_id;
654 }
655
656
657
658