[Window] Add accelerator support
[tilda-gobject.git] / tilda-window.c
1 #include <gdk/gdkx.h> /* for gdk_x11_window_set_user_time() */
2 #include <stdlib.h>
3
4 #include "tilda.h"
5 #include "tilda-config.h"
6 #include "tilda-controller.h"
7 #include "tilda-window.h"
8 #include "tilda-window-dbus-glue.h"
9 #include "tomboykeybinder.h"
10
11 /**
12  * Find the TildaTerminal corresponding to the currently selected
13  * tab in self->notebook. This could go away if TildaTerminal were
14  * a proper subclass of GtkWidget.
15  */
16 static TildaTerminal *
17 tilda_window_find_current_terminal (TildaWindow *self)
18 {
19         debug_enter();
20         debug_assert (TILDA_IS_WINDOW(self));
21
22         gint i;
23         TildaTerminal *ret;
24         gint current_page = gtk_notebook_get_current_page (GTK_NOTEBOOK(self->notebook));
25         GtkWidget *box = gtk_notebook_get_nth_page (GTK_NOTEBOOK(self->notebook), current_page);
26
27         for (i=0; i<self->terms->len; ++i)
28         {
29                 ret = g_ptr_array_index (self->terms, i);
30
31                 if (ret->hbox == box)
32                         return ret;
33         }
34
35         debug_printf ("ERROR: unable to find current terminal!\n");
36         return NULL;
37 }
38
39 static gint
40 tilda_window_find_next_free_terminal_number (TildaWindow *self)
41 {
42         debug_enter ();
43         debug_assert (TILDA_IS_WINDOW(self));
44
45         gint i, j;
46         gboolean found;
47
48         for (i=0; i<INT_MAX; ++i)
49         {
50                 found = FALSE;
51
52                 for (j=0; j<self->terms->len; ++j)
53                 {
54                         TildaTerminal *tt = g_ptr_array_index (self->terms, j);
55
56                         if (tt->number == i)
57                         {
58                                 found = TRUE;
59                                 break;
60                         }
61                 }
62
63                 if (!found)
64                         return i;
65         }
66
67         return 0;
68 }
69
70 /**
71  * Clean up and remove self completely from the program
72  *
73  * Should only be used by DBus...
74  */
75 gboolean
76 tilda_window_close (TildaWindow *self)
77 {
78         debug_enter  ();
79         debug_assert (TILDA_IS_WINDOW(self));
80
81         tilda_controller_remove_window (TILDA_CONTROLLER(self->controller), self->number);
82
83         return TRUE;
84 }
85
86 gboolean
87 tilda_window_add_terminal (TildaWindow *self)
88 {
89         debug_enter ();
90         debug_assert (TILDA_IS_WINDOW(self));
91
92         gint number;
93         TildaTerminal *tt;
94         GtkWidget *label;
95         gint notebook_index;
96
97         number = tilda_window_find_next_free_terminal_number (self);
98         tt = g_object_new (TILDA_TYPE_TERMINAL,
99                                            "number", number,
100                                            "parent-window", self,
101                                            NULL);
102         g_ptr_array_add (self->terms, tt);
103
104         label = gtk_label_new ("Tilda");
105         notebook_index = gtk_notebook_prepend_page (GTK_NOTEBOOK(self->notebook), tt->hbox, label);
106         gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK(self->notebook), tt->hbox, TRUE, TRUE, GTK_PACK_END);
107         gtk_notebook_set_current_page (GTK_NOTEBOOK(self->notebook), notebook_index);
108
109         if (gtk_notebook_get_n_pages (GTK_NOTEBOOK(self->notebook)) > 1)
110                 gtk_notebook_set_show_tabs (GTK_NOTEBOOK(self->notebook), TRUE);
111
112         /* Focus the VTE Terminal */
113         gtk_widget_grab_focus (tt->vte_term);
114
115         return TRUE;
116 }
117
118 /**
119  * Remove the TildaTerminal with the given number from the given
120  * TildaWindow.
121  *
122  * Return: TRUE on success, FALSE otherwise.
123  */
124 gboolean
125 tilda_window_remove_terminal (TildaWindow *self, gint terminal_number)
126 {
127         debug_enter  ();
128         debug_assert (TILDA_IS_WINDOW(self));
129         debug_assert (terminal_number >= 0);
130
131         gint i;
132
133         for (i=0; i<self->terms->len; ++i)
134         {
135                 TildaTerminal *tt = g_ptr_array_index (self->terms, i);
136
137                 if (tt->number == terminal_number)
138                 {
139                         gint notebook_index = gtk_notebook_page_num (GTK_NOTEBOOK(self->notebook), tt->hbox);
140
141                         /* Make sure the index was valid */
142                         if (notebook_index == -1)
143                         {
144                                 debug_printf ("ERROR: Bad Notebook Tab\n");
145                                 return FALSE;
146                         }
147
148                         /* Actually remove the terminal */
149                         gtk_notebook_remove_page (GTK_NOTEBOOK (self->notebook), notebook_index);
150
151                         /* We should hide the tabs if there is only one tab left */
152                         if (gtk_notebook_get_n_pages (GTK_NOTEBOOK (self->notebook)) == 1)
153                                 gtk_notebook_set_show_tabs (GTK_NOTEBOOK (self->notebook), FALSE);
154
155                         /* Remove the term from our lists, then free it */
156                         g_ptr_array_remove_fast (self->terms, tt);
157                         g_object_unref (G_OBJECT(tt));
158
159                         /* With no pages left, it's time to remove this window */
160                         if (gtk_notebook_get_n_pages (GTK_NOTEBOOK (self->notebook)) < 1)
161                         {
162                                 debug_printf ("no terminals left, closing window %d\n", self->number);
163                                 tilda_controller_remove_window (TILDA_CONTROLLER(self->controller), self->number);
164                         }
165
166                         /* Leave the loop, we're done */
167                         break;
168                 }
169         }
170
171         return TRUE;
172 }
173
174 /**
175  * This sets up the given TildaWindow for the capability of real
176  * transparency, if the X server is capable of it. */
177 static void
178 tilda_window_setup_real_transparency (TildaWindow *self)
179 {
180         debug_enter  ();
181         debug_assert (TILDA_IS_WINDOW(self));
182
183         GdkScreen *screen;
184         GdkColormap *colormap;
185
186         screen = gtk_widget_get_screen (GTK_WIDGET(self->window));
187         colormap = gdk_screen_get_rgba_colormap (screen);
188
189         /* If possible, set the RGBA colormap so VTE can use real alpha
190          * channels for transparency. */
191         if (colormap != NULL && gdk_screen_is_composited (screen))
192         {
193                 gtk_widget_set_colormap (GTK_WIDGET(self->window), colormap);
194                 self->have_real_transparency = TRUE;
195                 return;
196         }
197
198         self->have_real_transparency = FALSE;
199 }
200
201 /* Center the given TildaWindow in the horizontal axis */
202 static void
203 tilda_window_center_horizontally (TildaWindow *self)
204 {
205         debug_enter  ();
206         debug_assert (TILDA_IS_WINDOW(self));
207
208         const gint screen_center = gdk_screen_width() / 2;
209         const gint tilda_center  = self->width / 2;
210         const gint center_coord  = screen_center - tilda_center;
211
212         g_object_set (G_OBJECT(self), "x-position", center_coord, NULL);
213 }
214
215 /* Center the given TildaWindow in the vertical axis */
216 static void
217 tilda_window_center_vertically (TildaWindow *self)
218 {
219         debug_enter  ();
220         debug_assert (TILDA_IS_WINDOW(self));
221
222         const gint screen_center = gdk_screen_height() / 2;
223         const gint tilda_center  = self->height / 2;
224         const gint center_coord  = screen_center - tilda_center;
225
226         g_object_set (G_OBJECT(self), "y-position", center_coord, NULL);
227 }
228
229 static void
230 tilda_window_keybinding_cb (const gchar *keystr, gpointer data)
231 {
232         debug_enter  ();
233         debug_assert (TILDA_IS_WINDOW(data));
234
235         TildaWindow *self = TILDA_WINDOW(data);
236         TildaTerminal *tt;
237
238         /* This call sets the X11 window property _NET_WM_USER_TIME, which GTK+ normally
239          * sets for us. However, because this callback is activated via a global keybinding,
240          * we see the event before GDK / GTK+ does. Therefore, to get the focus, we must
241          * set the property ourselves. */
242         gdk_x11_window_set_user_time (GTK_WIDGET(self->window)->window,
243                                                                   tomboy_keybinder_get_current_event_time());
244
245         switch (self->state)
246         {
247                 case WINDOW_UP: /* Pull the window up */
248
249                         /* Bugfix: having this here keeps the tilda window from being
250                          * hidden if you turn off "stick", pull it down on workspace 1,
251                          * switch to workspace 2, then pull it up and back down. Without
252                          * this, something in metacity (at least) hides the window. Stupid. */
253                         gtk_window_deiconify (GTK_WINDOW(self->window));
254
255                         /* Re-set the window properties that do not linger after hiding the
256                          * window. I know this looks stupid, but it keeps all of the state-
257                          * changing code in the place it belongs: the property-setting code. */
258                         g_object_set (G_OBJECT(self),
259                                         "keep-above", self->keep_above,
260                                         "stick", self->stick,
261                                         NULL);
262                         gtk_widget_show (GTK_WIDGET(self->window));
263
264                         /* Focusing the term here works perfectly, near as I can tell */
265                         tt = tilda_window_find_current_terminal (self);
266                         gtk_widget_grab_focus (GTK_WIDGET(tt->vte_term));
267
268                         self->state = WINDOW_DOWN;
269                         break;
270
271                 case WINDOW_DOWN: /* Pull the window up */
272
273                         gtk_widget_hide (GTK_WIDGET(self->window));
274
275                         self->state = WINDOW_UP;
276                         break;
277
278                 default:
279                         debug_printf ("ERROR: Window is in a bad state!\n");
280
281                         /* Pretend we're down, for good measure.... */
282                         self->state = WINDOW_DOWN;
283                         break;
284         }
285 }
286
287 /**
288  * Attempt to bind the new_key to show this window.
289  *
290  * Return: TRUE if successful, FALSE otherwise.
291  */
292 static gboolean
293 tilda_window_try_to_bind_key (TildaWindow *self, const gchar *new_key)
294 {
295         debug_enter  ();
296         debug_assert (TILDA_IS_WINDOW(self));
297
298         gboolean ret = FALSE;
299
300         /* Make sure the new key is not null in any way */
301         if (new_key == NULL || g_ascii_strcasecmp("", new_key) == 0)
302                 return FALSE;
303
304         /* Check that no other windows are using the key */
305         // FIXME: there should be a hidden option to disable this. Maybe some people want
306         // to have logs in two Tildas, and just show them with one key. Crazy...
307         if (tilda_controller_global_key_in_use(TILDA_CONTROLLER(self->controller), new_key))
308                 return FALSE;
309
310         /* Unbind if we were set */
311         if (self->key)
312                 tomboy_keybinder_unbind (self->key, tilda_window_keybinding_cb);
313
314         ret = tomboy_keybinder_bind (new_key, tilda_window_keybinding_cb, self);
315
316         /* If it was successful, update the self->key variable and be done with it */
317         if (ret)
318         {
319                 g_free (self->key);
320                 self->key = g_strdup (new_key);
321                 return TRUE;
322         }
323
324         g_printerr (_("Bind key '%s' failed. Reverting to original keybinding\n"), self->key);
325
326         /* Not successful, so rebind the old key, and return FALSE */
327         if (self->key != NULL && g_ascii_strcasecmp("",self->key) != 0)
328         {
329                 ret = tomboy_keybinder_bind (self->key, tilda_window_keybinding_cb, self);
330
331                 /* Check that it went ok */
332                 if (!ret)
333                         g_printerr (_("Unable to re-bind original key '%s'. Oh shit...\n"), self->key);
334         }
335         else
336                 g_printerr (_("No original key to revert to!\n"));
337
338         return FALSE;
339 }
340
341 static void
342 tilda_window_dbus_register_object (TildaWindow *self)
343 {
344         debug_enter  ();
345         debug_assert (TILDA_IS_WINDOW(self));
346
347         gchar *object_path;
348
349         // Register this object with DBus
350         object_path = g_strdup_printf ("/net/sourceforge/Tilda/Window%d", self->number);
351         dbus_g_connection_register_g_object (dbus_connection, object_path, G_OBJECT(self));
352         g_free (object_path);
353 }
354
355 /*******************************************************************************
356  * All accelerator-related stuff below
357  ******************************************************************************/
358
359 typedef gboolean (*TildaWindowAccelCallback) (TildaWindow *self, gpointer data);
360
361 /**
362  * This function updates the accelerator used to call the given function for this
363  * TildaWindow. If accel is NULL, then func will be removed (no accelerator will
364  * cause func to be called).
365  *
366  * Returns: TRUE on success, FALSE on failure
367  */
368 static gboolean
369 tilda_window_update_accelerator (TildaWindow *self,                             /* object */
370                                                                  gchar **accel_to_update,               /* self->??? */
371                                                                  const gchar *accel,                    /* new accel */
372                                                                  const TildaWindowAccelCallback func)
373 {
374         debug_enter  ();
375         debug_assert (TILDA_IS_WINDOW(self));
376         debug_assert (accel_to_update != NULL);
377         debug_assert (func != NULL);
378
379         gboolean ret;
380         guint key;
381         GdkModifierType mod;
382         GClosure *closure;
383
384         /* Remove the old accelerator if there was a previous one set */
385         if (*accel_to_update != NULL)
386         {
387                 /* This should always parse, we've done it before! */
388                 gtk_accelerator_parse (*accel_to_update, &key, &mod);
389                 ret = gtk_accel_group_disconnect_key (self->accel_group, key, mod);
390         }
391
392         /* If we are just removing the old accelerator, we're already done */
393         if (accel == NULL)
394         {
395                 g_free (*accel_to_update);
396                 *accel_to_update = NULL;
397                 return TRUE;
398         }
399
400         /* Create the closure for this function */
401         closure = g_cclosure_new_swap (G_CALLBACK(func), self, NULL);
402
403         /* Try to parse the new accelerator */
404         gtk_accelerator_parse (accel, &key, &mod);
405
406         if (!gtk_accelerator_valid (key, mod))
407         {
408                 g_warning (_("Failed to parse accelerator: %s\n"), accel);
409
410                 /* Re-install the old accelerator */
411                 if (*accel_to_update != NULL)
412                 {
413                         gtk_accelerator_parse (*accel_to_update, &key, &mod);
414                         gtk_accel_group_connect (self->accel_group, key, mod, GTK_ACCEL_VISIBLE, closure);
415                 }
416                 return FALSE;
417         }
418
419         /* All good, g_free() the old accelerator, g_strdup() the new one */
420         g_free (*accel_to_update);
421         *accel_to_update = g_strdup(accel);
422
423         /* Add the new accelerator */
424         gtk_accel_group_connect (self->accel_group, key, mod, GTK_ACCEL_VISIBLE, closure);
425
426         return TRUE;
427 }
428
429 static gboolean
430 tilda_window_accel_quit_cb (TildaWindow *self, gpointer data)
431 {
432         debug_enter  ();
433         debug_assert (TILDA_IS_WINDOW(self));
434
435         tilda_window_close (self);
436
437         /* Do not keep propagating */
438         return TRUE;
439 }
440
441 static gboolean
442 tilda_window_accel_next_tab_cb (TildaWindow *self, gpointer data)
443 {
444         debug_enter  ();
445         debug_assert (TILDA_IS_WINDOW(self));
446
447         gint num_pages;
448         gint current_page;
449
450         num_pages = gtk_notebook_get_n_pages (GTK_NOTEBOOK(self->notebook));
451         current_page = gtk_notebook_get_current_page (GTK_NOTEBOOK(self->notebook));
452
453         /* Go to next page (with wrapping) */
454         if (num_pages != (current_page + num_pages))
455                 gtk_notebook_next_page (GTK_NOTEBOOK(self->notebook));
456         else
457                 gtk_notebook_set_current_page (GTK_NOTEBOOK(self->notebook), num_pages-1);
458
459         /* Do not keep propagating */
460         return TRUE;
461 }
462
463 static gboolean
464 tilda_window_accel_prev_tab_cb (TildaWindow *self, gpointer data)
465 {
466         debug_enter  ();
467         debug_assert (TILDA_IS_WINDOW(self));
468
469         gint num_pages;
470         gint current_page;
471
472         num_pages = gtk_notebook_get_n_pages (GTK_NOTEBOOK(self->notebook));
473         current_page = gtk_notebook_get_current_page (GTK_NOTEBOOK(self->notebook));
474
475         if ((num_pages-1) != current_page)
476                 gtk_notebook_prev_page (GTK_NOTEBOOK(self->notebook));
477         else
478                 gtk_notebook_set_current_page (GTK_NOTEBOOK(self->notebook), 0);
479
480         /* Do not keep propagating */
481         return TRUE;
482 }
483
484 static gboolean
485 tilda_window_accel_add_term_cb (TildaWindow *self, gpointer data)
486 {
487         debug_enter  ();
488         debug_assert (TILDA_IS_WINDOW(self));
489
490         tilda_window_add_terminal (self);
491
492         /* Do not keep propagating */
493         return TRUE;
494 }
495
496 static gboolean
497 tilda_window_accel_remove_term_cb (TildaWindow *self, gpointer data)
498 {
499         debug_enter  ();
500         debug_assert (TILDA_IS_WINDOW(self));
501
502         TildaTerminal *tt = tilda_window_find_current_terminal (self);
503
504         tilda_window_remove_terminal (self, tt->number);
505
506         /* Do not keep propagating */
507         return TRUE;
508 }
509
510 static gboolean
511 tilda_window_accel_copy_cb (TildaWindow *self, gpointer data)
512 {
513         debug_enter  ();
514         debug_assert (TILDA_IS_WINDOW(self));
515
516         TildaTerminal *tt = tilda_window_find_current_terminal (self);
517
518         vte_terminal_copy_clipboard (VTE_TERMINAL(tt->vte_term));
519
520         /* Do not keep propagating */
521         return TRUE;
522 }
523
524 static gboolean
525 tilda_window_accel_paste_cb (TildaWindow *self, gpointer data)
526 {
527         debug_enter  ();
528         debug_assert (TILDA_IS_WINDOW(self));
529
530         TildaTerminal *tt = tilda_window_find_current_terminal (self);
531
532         vte_terminal_paste_clipboard (VTE_TERMINAL(tt->vte_term));
533
534         /* Do not keep propagating */
535         return TRUE;
536 }
537
538 static gboolean
539 tilda_window_accel_goto_generic (TildaWindow *self, guint number)
540 {
541         debug_enter  ();
542         debug_assert (TILDA_IS_WINDOW(self));
543
544         if (self->terms->len > (number - 1))
545         {
546                 gint temp = self->terms->len - number;
547                 gtk_notebook_set_current_page (GTK_NOTEBOOK(self->notebook), temp);
548         }
549
550         /* Do not keep propagating */
551         return TRUE;
552 }
553
554 static gboolean
555 tilda_window_accel_goto_1_cb (TildaWindow *self, gpointer data)
556 {
557         debug_enter  ();
558         debug_assert (TILDA_IS_WINDOW(self));
559
560         return tilda_window_accel_goto_generic (self, 1);
561 }
562
563 static gboolean
564 tilda_window_accel_goto_2_cb (TildaWindow *self, gpointer data)
565 {
566         debug_enter  ();
567         debug_assert (TILDA_IS_WINDOW(self));
568
569         return tilda_window_accel_goto_generic (self, 2);
570 }
571
572 static gboolean
573 tilda_window_accel_goto_3_cb (TildaWindow *self, gpointer data)
574 {
575         debug_enter  ();
576         debug_assert (TILDA_IS_WINDOW(self));
577
578         return tilda_window_accel_goto_generic (self, 3);
579 }
580
581 static gboolean
582 tilda_window_accel_goto_4_cb (TildaWindow *self, gpointer data)
583 {
584         debug_enter  ();
585         debug_assert (TILDA_IS_WINDOW(self));
586
587         return tilda_window_accel_goto_generic (self, 4);
588 }
589
590 static gboolean
591 tilda_window_accel_goto_5_cb (TildaWindow *self, gpointer data)
592 {
593         debug_enter  ();
594         debug_assert (TILDA_IS_WINDOW(self));
595
596         return tilda_window_accel_goto_generic (self, 5);
597 }
598
599 static gboolean
600 tilda_window_accel_goto_6_cb (TildaWindow *self, gpointer data)
601 {
602         debug_enter  ();
603         debug_assert (TILDA_IS_WINDOW(self));
604
605         return tilda_window_accel_goto_generic (self, 6);
606 }
607
608 static gboolean
609 tilda_window_accel_goto_7_cb (TildaWindow *self, gpointer data)
610 {
611         debug_enter  ();
612         debug_assert (TILDA_IS_WINDOW(self));
613
614         return tilda_window_accel_goto_generic (self, 7);
615 }
616
617 static gboolean
618 tilda_window_accel_goto_8_cb (TildaWindow *self, gpointer data)
619 {
620         debug_enter  ();
621         debug_assert (TILDA_IS_WINDOW(self));
622
623         return tilda_window_accel_goto_generic (self, 8);
624 }
625
626 static gboolean
627 tilda_window_accel_goto_9_cb (TildaWindow *self, gpointer data)
628 {
629         debug_enter  ();
630         debug_assert (TILDA_IS_WINDOW(self));
631
632         return tilda_window_accel_goto_generic (self, 9);
633 }
634
635 static gboolean
636 tilda_window_accel_goto_10_cb (TildaWindow *self, gpointer data)
637 {
638         debug_enter  ();
639         debug_assert (TILDA_IS_WINDOW(self));
640
641         return tilda_window_accel_goto_generic (self, 10);
642 }
643
644 /*******************************************************************************
645  * ALL GOBJECT STUFF BELOW PLEASE
646  ******************************************************************************/
647
648 static GObjectClass *parent_class = NULL;
649
650 enum tilda_window_properties {
651         TILDA_WINDOW_NUMBER = 1,
652         TILDA_WINDOW_CONTROLLER,
653
654         TILDA_WINDOW_ACCEL_QUIT,
655         TILDA_WINDOW_ACCEL_NEXT_TAB,
656         TILDA_WINDOW_ACCEL_PREV_TAB,
657         TILDA_WINDOW_ACCEL_ADD_TERM,
658         TILDA_WINDOW_ACCEL_REMOVE_TERM,
659         TILDA_WINDOW_ACCEL_COPY,
660         TILDA_WINDOW_ACCEL_PASTE,
661         TILDA_WINDOW_ACCEL_GOTO_1,
662         TILDA_WINDOW_ACCEL_GOTO_2,
663         TILDA_WINDOW_ACCEL_GOTO_3,
664         TILDA_WINDOW_ACCEL_GOTO_4,
665         TILDA_WINDOW_ACCEL_GOTO_5,
666         TILDA_WINDOW_ACCEL_GOTO_6,
667         TILDA_WINDOW_ACCEL_GOTO_7,
668         TILDA_WINDOW_ACCEL_GOTO_8,
669         TILDA_WINDOW_ACCEL_GOTO_9,
670         TILDA_WINDOW_ACCEL_GOTO_10,
671
672         TILDA_WINDOW_KEY,
673
674         TILDA_WINDOW_HEIGHT,
675         TILDA_WINDOW_WIDTH,
676         TILDA_WINDOW_X_POSITION,
677         TILDA_WINDOW_Y_POSITION,
678         TILDA_WINDOW_INITIAL_TERMINALS,
679
680         TILDA_WINDOW_TAB_POSITION,
681         TILDA_WINDOW_ANIMATION_ORIENTATION,
682         TILDA_WINDOW_ANIMATION_DELAY,
683
684         TILDA_WINDOW_KEEP_ABOVE,
685         TILDA_WINDOW_SKIP_TASKBAR_HINT,
686         TILDA_WINDOW_STICK,
687         TILDA_WINDOW_HIDDEN_AT_START,
688         TILDA_WINDOW_CENTERED_HORIZONTALLY,
689         TILDA_WINDOW_CENTERED_VERTICALLY,
690
691         TILDA_WINDOW_HAVE_REAL_TRANSPARENCY,
692 };
693
694 static void
695 tilda_window_instance_init (GTypeInstance *instance,
696                                                         gpointer       g_class)
697 {
698         debug_enter ();
699
700         TildaWindow *self = (TildaWindow *) instance;
701         self->dispose_has_run = FALSE;
702
703         /* Initialize all properties */
704         self->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
705         self->notebook = gtk_notebook_new ();
706         self->terms = g_ptr_array_new ();
707
708         /* Accelerators */
709         self->accel_group = gtk_accel_group_new ();
710         gtk_window_add_accel_group (GTK_WINDOW(self->window), self->accel_group);
711
712         /* Somewhat of a "poison" value, incase we don't set this */
713         self->number = 0xdeadbeef;
714         self->controller = NULL;
715
716         self->state = WINDOW_UP;
717 }
718
719 static void
720 tilda_window_set_property (GObject      *object,
721                                                    guint         property_id,
722                                                    const GValue *value,
723                                                    GParamSpec   *pspec)
724 {
725         TildaWindow *self = (TildaWindow *) object;
726
727         switch (property_id) {
728
729                 case TILDA_WINDOW_NUMBER:
730                         self->number = g_value_get_int (value);
731                         debug_printf ("window number: %d\n", self->number);
732                         break;
733
734                 case TILDA_WINDOW_CONTROLLER:
735                         self->controller = g_value_get_pointer (value);
736                         debug_printf ("window controller: 0x%x\n", self->controller);
737                         break;
738
739                 case TILDA_WINDOW_ACCEL_QUIT:
740                         tilda_window_update_accelerator (self,
741                                                                                          &self->accel_quit,
742                                                                                          g_value_get_string (value),
743                                                                                          tilda_window_accel_quit_cb);
744                         debug_printf ("window accel quit: %s\n", self->accel_quit);
745                         break;
746
747                 case TILDA_WINDOW_ACCEL_NEXT_TAB:
748                         tilda_window_update_accelerator (self,
749                                                                                          &self->accel_next_tab,
750                                                                                          g_value_get_string (value),
751                                                                                          tilda_window_accel_next_tab_cb);
752                         debug_printf ("window accel next tab: %s\n", self->accel_next_tab);
753                         break;
754
755                 case TILDA_WINDOW_ACCEL_PREV_TAB:
756                         tilda_window_update_accelerator (self,
757                                                                                          &self->accel_prev_tab,
758                                                                                          g_value_get_string (value),
759                                                                                          tilda_window_accel_prev_tab_cb);
760                         debug_printf ("window accel prev tab: %s\n", self->accel_prev_tab);
761                         break;
762
763                 case TILDA_WINDOW_ACCEL_ADD_TERM:
764                         tilda_window_update_accelerator (self,
765                                                                                          &self->accel_add_term,
766                                                                                          g_value_get_string (value),
767                                                                                          tilda_window_accel_add_term_cb);
768                         debug_printf ("window accel add term: %s\n", self->accel_add_term);
769                         break;
770
771                 case TILDA_WINDOW_ACCEL_REMOVE_TERM:
772                         tilda_window_update_accelerator (self,
773                                                                                          &self->accel_remove_term,
774                                                                                          g_value_get_string (value),
775                                                                                          tilda_window_accel_remove_term_cb);
776                         debug_printf ("window accel remove term: %s\n", self->accel_remove_term);
777                         break;
778
779                 case TILDA_WINDOW_ACCEL_COPY:
780                         tilda_window_update_accelerator (self,
781                                                                                          &self->accel_copy,
782                                                                                          g_value_get_string (value),
783                                                                                          tilda_window_accel_copy_cb);
784                         debug_printf ("window accel copy: %s\n", self->accel_copy);
785                         break;
786
787                 case TILDA_WINDOW_ACCEL_PASTE:
788                         tilda_window_update_accelerator (self,
789                                                                                          &self->accel_paste,
790                                                                                          g_value_get_string (value),
791                                                                                          tilda_window_accel_paste_cb);
792                         debug_printf ("window accel paste: %s\n", self->accel_paste);
793                         break;
794
795                 case TILDA_WINDOW_ACCEL_GOTO_1:
796                         tilda_window_update_accelerator (self,
797                                                                                          &self->accel_goto_1,
798                                                                                          g_value_get_string (value),
799                                                                                          tilda_window_accel_goto_1_cb);
800                         debug_printf ("window accel goto 1: %s\n", self->accel_goto_1);
801                         break;
802
803                 case TILDA_WINDOW_ACCEL_GOTO_2:
804                         tilda_window_update_accelerator (self,
805                                                                                          &self->accel_goto_2,
806                                                                                          g_value_get_string (value),
807                                                                                          tilda_window_accel_goto_2_cb);
808                         debug_printf ("window accel goto 2: %s\n", self->accel_goto_2);
809                         break;
810
811                 case TILDA_WINDOW_ACCEL_GOTO_3:
812                         tilda_window_update_accelerator (self,
813                                                                                          &self->accel_goto_3,
814                                                                                          g_value_get_string (value),
815                                                                                          tilda_window_accel_goto_3_cb);
816                         debug_printf ("window accel goto 3: %s\n", self->accel_goto_3);
817                         break;
818
819                 case TILDA_WINDOW_ACCEL_GOTO_4:
820                         tilda_window_update_accelerator (self,
821                                                                                          &self->accel_goto_4,
822                                                                                          g_value_get_string (value),
823                                                                                          tilda_window_accel_goto_4_cb);
824                         debug_printf ("window accel goto 4: %s\n", self->accel_goto_4);
825                         break;
826
827                 case TILDA_WINDOW_ACCEL_GOTO_5:
828                         tilda_window_update_accelerator (self,
829                                                                                          &self->accel_goto_5,
830                                                                                          g_value_get_string (value),
831                                                                                          tilda_window_accel_goto_5_cb);
832                         debug_printf ("window accel goto 5: %s\n", self->accel_goto_5);
833                         break;
834
835                 case TILDA_WINDOW_ACCEL_GOTO_6:
836                         tilda_window_update_accelerator (self,
837                                                                                          &self->accel_goto_6,
838                                                                                          g_value_get_string (value),
839                                                                                          tilda_window_accel_goto_6_cb);
840                         debug_printf ("window accel goto 6: %s\n", self->accel_goto_6);
841                         break;
842
843                 case TILDA_WINDOW_ACCEL_GOTO_7:
844                         tilda_window_update_accelerator (self,
845                                                                                          &self->accel_goto_7,
846                                                                                          g_value_get_string (value),
847                                                                                          tilda_window_accel_goto_7_cb);
848                         debug_printf ("window accel goto 7: %s\n", self->accel_goto_7);
849                         break;
850
851                 case TILDA_WINDOW_ACCEL_GOTO_8:
852                         tilda_window_update_accelerator (self,
853                                                                                          &self->accel_goto_8,
854                                                                                          g_value_get_string (value),
855                                                                                          tilda_window_accel_goto_8_cb);
856                         debug_printf ("window accel goto 8: %s\n", self->accel_goto_8);
857                         break;
858
859                 case TILDA_WINDOW_ACCEL_GOTO_9:
860                         tilda_window_update_accelerator (self,
861                                                                                          &self->accel_goto_9,
862                                                                                          g_value_get_string (value),
863                                                                                          tilda_window_accel_goto_9_cb);
864                         debug_printf ("window accel goto 9: %s\n", self->accel_goto_9);
865                         break;
866
867                 case TILDA_WINDOW_ACCEL_GOTO_10:
868                         tilda_window_update_accelerator (self,
869                                                                                          &self->accel_goto_10,
870                                                                                          g_value_get_string (value),
871                                                                                          tilda_window_accel_goto_10_cb);
872                         debug_printf ("window accel goto 10: %s\n", self->accel_goto_10);
873                         break;
874
875                 case TILDA_WINDOW_KEY:
876                         tilda_window_try_to_bind_key (self, g_value_get_string (value));
877                         debug_printf ("window key %s\n", self->key);
878                         break;
879
880                 case TILDA_WINDOW_HEIGHT:
881                         self->height = g_value_get_int (value);
882                         gtk_widget_set_size_request (self->window, self->width, self->height);
883                         gtk_window_resize (GTK_WINDOW(self->window), self->width, self->height);
884                         debug_printf ("window height: %d\n", self->height);
885                         break;
886
887                 case TILDA_WINDOW_WIDTH:
888                         self->width = g_value_get_int (value);
889                         gtk_widget_set_size_request (self->window, self->width, self->height);
890                         gtk_window_resize (GTK_WINDOW(self->window), self->width, self->height);
891                         debug_printf ("window width: %d\n", self->width);
892                         break;
893
894                 case TILDA_WINDOW_X_POSITION:
895                         self->x_position = g_value_get_int (value);
896                         gtk_window_move (GTK_WINDOW(self->window), self->x_position, self->y_position);
897                         debug_printf ("window x position: %d\n", self->x_position);
898                         break;
899
900                 case TILDA_WINDOW_Y_POSITION:
901                         self->y_position = g_value_get_int (value);
902                         gtk_window_move (GTK_WINDOW(self->window), self->x_position, self->y_position);
903                         debug_printf ("window y position: %d\n", self->y_position);
904                         break;
905
906                 case TILDA_WINDOW_INITIAL_TERMINALS:
907                         self->initial_terminals = g_value_get_int (value);
908                         debug_printf ("window initial terminals: %d\n", self->initial_terminals);
909                         break;
910
911                 case TILDA_WINDOW_TAB_POSITION:
912                         self->tab_position = g_value_get_enum (value);
913                         gtk_notebook_set_tab_pos (GTK_NOTEBOOK(self->notebook), self->tab_position);
914                         debug_printf ("window tab position: %d\n", self->tab_position);
915                         break;
916
917                 case TILDA_WINDOW_ANIMATION_ORIENTATION:
918                         self->animation_orientation = g_value_get_enum (value);
919                         debug_printf ("window animation orientation: %d\n", self->animation_orientation);
920                         break;
921
922                 case TILDA_WINDOW_ANIMATION_DELAY:
923                         self->animation_delay = g_value_get_int (value);
924                         debug_printf ("window animation delay: %d\n", self->animation_delay);
925                         break;
926
927                 case TILDA_WINDOW_KEEP_ABOVE:
928                         self->keep_above = g_value_get_boolean (value);
929                         gtk_window_set_keep_above (GTK_WINDOW(self->window), self->keep_above);
930                         debug_printf ("window keep above: %d\n", self->keep_above);
931                         break;
932
933                 case TILDA_WINDOW_SKIP_TASKBAR_HINT:
934                         self->skip_taskbar_hint = g_value_get_boolean (value);
935                         gtk_window_set_skip_taskbar_hint (GTK_WINDOW(self->window), self->skip_taskbar_hint);
936                         debug_printf ("window skip taskbar hint: %d\n", self->skip_taskbar_hint);
937                         break;
938
939                 case TILDA_WINDOW_STICK:
940                         self->stick = g_value_get_boolean (value);
941
942                         /* This is moderately ugly, but GTK+ does it this way... */
943                         self->stick ? gtk_window_stick (GTK_WINDOW(self->window))
944                                                 : gtk_window_unstick (GTK_WINDOW(self->window));
945                         debug_printf ("window stick: %d\n", self->stick);
946                         break;
947
948                 case TILDA_WINDOW_HIDDEN_AT_START:
949                         self->hidden_at_start = g_value_get_boolean (value);
950                         debug_printf ("window hidden at start: %d\n", self->hidden_at_start);
951                         break;
952
953                 case TILDA_WINDOW_CENTERED_HORIZONTALLY:
954                         self->centered_horizontally = g_value_get_boolean (value);
955                         if (self->centered_horizontally)
956                                 tilda_window_center_horizontally (self);
957                         debug_printf ("window centered horizontally: %d\n", self->centered_horizontally);
958                         break;
959
960                 case TILDA_WINDOW_CENTERED_VERTICALLY:
961                         self->centered_vertically = g_value_get_boolean (value);
962                         if (self->centered_vertically)
963                                 tilda_window_center_vertically (self);
964                         debug_printf ("window centered vertically: %d\n", self->centered_vertically);
965                         break;
966
967                 case TILDA_WINDOW_HAVE_REAL_TRANSPARENCY:
968                         self->have_real_transparency = g_value_get_boolean (value);
969                         debug_printf ("window have real transp: %d\n", self->have_real_transparency);
970                         break;
971
972                 default:
973                         /* We don't have this property */
974                         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
975                         break;
976         }
977 }
978
979 static void
980 tilda_window_get_property (GObject    *object,
981                                                    guint       property_id,
982                                                    GValue     *value,
983                                                    GParamSpec *pspec)
984 {
985         TildaWindow *self = (TildaWindow *) object;
986
987         switch (property_id) {
988
989                 case TILDA_WINDOW_NUMBER:
990                         g_value_set_int (value, self->number);
991                         break;
992
993                 case TILDA_WINDOW_CONTROLLER:
994                         g_value_set_pointer (value, self->controller);
995                         break;
996
997                 case TILDA_WINDOW_ACCEL_QUIT:
998                         g_value_set_string (value, self->accel_quit);
999                         break;
1000
1001                 case TILDA_WINDOW_ACCEL_NEXT_TAB:
1002                         g_value_set_string (value, self->accel_next_tab);
1003                         break;
1004
1005                 case TILDA_WINDOW_ACCEL_PREV_TAB:
1006                         g_value_set_string (value, self->accel_prev_tab);
1007                         break;
1008
1009                 case TILDA_WINDOW_ACCEL_ADD_TERM:
1010                         g_value_set_string (value, self->accel_prev_tab);
1011                         break;
1012
1013                 case TILDA_WINDOW_ACCEL_REMOVE_TERM:
1014                         g_value_set_string (value, self->accel_remove_term);
1015                         break;
1016
1017                 case TILDA_WINDOW_ACCEL_COPY:
1018                         g_value_set_string (value, self->accel_copy);
1019                         break;
1020
1021                 case TILDA_WINDOW_ACCEL_PASTE:
1022                         g_value_set_string (value, self->accel_paste);
1023                         break;
1024
1025                 case TILDA_WINDOW_ACCEL_GOTO_1:
1026                         g_value_set_string (value, self->accel_goto_1);
1027                         break;
1028
1029                 case TILDA_WINDOW_ACCEL_GOTO_2:
1030                         g_value_set_string (value, self->accel_goto_2);
1031                         break;
1032
1033                 case TILDA_WINDOW_ACCEL_GOTO_3:
1034                         g_value_set_string (value, self->accel_goto_3);
1035                         break;
1036
1037                 case TILDA_WINDOW_ACCEL_GOTO_4:
1038                         g_value_set_string (value, self->accel_goto_4);
1039                         break;
1040
1041                 case TILDA_WINDOW_ACCEL_GOTO_5:
1042                         g_value_set_string (value, self->accel_goto_5);
1043                         break;
1044
1045                 case TILDA_WINDOW_ACCEL_GOTO_6:
1046                         g_value_set_string (value, self->accel_goto_6);
1047                         break;
1048
1049                 case TILDA_WINDOW_ACCEL_GOTO_7:
1050                         g_value_set_string (value, self->accel_goto_7);
1051                         break;
1052
1053                 case TILDA_WINDOW_ACCEL_GOTO_8:
1054                         g_value_set_string (value, self->accel_goto_8);
1055                         break;
1056
1057                 case TILDA_WINDOW_ACCEL_GOTO_9:
1058                         g_value_set_string (value, self->accel_goto_9);
1059                         break;
1060
1061                 case TILDA_WINDOW_ACCEL_GOTO_10:
1062                         g_value_set_string (value, self->accel_goto_10);
1063                         break;
1064
1065                 case TILDA_WINDOW_KEY:
1066                         g_value_set_string (value, self->key);
1067                         break;
1068
1069                 case TILDA_WINDOW_HEIGHT:
1070                         g_value_set_int (value, self->height);
1071                         break;
1072
1073                 case TILDA_WINDOW_WIDTH:
1074                         g_value_set_int (value, self->width);
1075                         break;
1076
1077                 case TILDA_WINDOW_X_POSITION:
1078                         g_value_set_int (value, self->x_position);
1079                         break;
1080
1081                 case TILDA_WINDOW_Y_POSITION:
1082                         g_value_set_int (value, self->y_position);
1083                         break;
1084
1085                 case TILDA_WINDOW_INITIAL_TERMINALS:
1086                         g_value_set_int (value, self->initial_terminals);
1087                         break;
1088
1089                 case TILDA_WINDOW_TAB_POSITION:
1090                         g_value_set_enum (value, self->tab_position);
1091                         break;
1092
1093                 case TILDA_WINDOW_ANIMATION_ORIENTATION:
1094                         g_value_set_enum (value, self->animation_orientation);
1095                         break;
1096
1097                 case TILDA_WINDOW_ANIMATION_DELAY:
1098                         g_value_set_int (value, self->animation_delay);
1099                         break;
1100
1101                 case TILDA_WINDOW_KEEP_ABOVE:
1102                         g_value_set_boolean (value, self->keep_above);
1103                         break;
1104
1105                 case TILDA_WINDOW_SKIP_TASKBAR_HINT:
1106                         g_value_set_boolean (value, self->skip_taskbar_hint);
1107                         break;
1108
1109                 case TILDA_WINDOW_STICK:
1110                         g_value_set_boolean (value, self->stick);
1111                         break;
1112
1113                 case TILDA_WINDOW_HIDDEN_AT_START:
1114                         g_value_set_boolean (value, self->hidden_at_start);
1115                         break;
1116
1117                 case TILDA_WINDOW_CENTERED_HORIZONTALLY:
1118                         g_value_set_boolean (value, self->centered_horizontally);
1119                         break;
1120
1121                 case TILDA_WINDOW_CENTERED_VERTICALLY:
1122                         g_value_set_boolean (value, self->centered_vertically);
1123                         break;
1124
1125                 case TILDA_WINDOW_HAVE_REAL_TRANSPARENCY:
1126                         g_value_set_boolean (value, self->have_real_transparency);
1127                         break;
1128
1129                 default:
1130                         /* We don't have this property */
1131                         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1132                         break;
1133         }
1134 }
1135
1136 static GObject *
1137 tilda_window_constructor (GType                  type,
1138                                                   guint                  n_construct_properties,
1139                                                   GObjectConstructParam *construct_properties)
1140 {
1141         debug_enter ();
1142
1143         GObject *obj;
1144         TildaWindow *self;
1145         gint i;
1146
1147         /* Invoke parent constructor */
1148         TildaWindowClass *klass;
1149         klass = TILDA_WINDOW_CLASS (g_type_class_peek (TILDA_TYPE_WINDOW));
1150         obj = parent_class->constructor (type,
1151                                                                          n_construct_properties,
1152                                                                          construct_properties);
1153
1154         /* Do other stuff here. The object is ready to go now, and all
1155          * ctor properties have been set.
1156          */
1157         self = TILDA_WINDOW(obj);
1158
1159         /* Try to set up real transparency */
1160         tilda_window_setup_real_transparency (self);
1161
1162         gtk_container_add (GTK_CONTAINER(self->window), self->notebook);
1163         g_object_set (G_OBJECT(self->notebook), "can-focus", FALSE, NULL);
1164         gtk_widget_show (self->notebook);
1165
1166         /* Tilda is never decorated */
1167         gtk_window_set_decorated (GTK_WINDOW(self->window), FALSE);
1168
1169         /* Set all of the properties out of the config file */
1170         tilda_window_set_property_from_config (self, "key");
1171
1172         // FIXME: hack -- start the wizard in this case :)
1173         if (!self->key)
1174         {
1175                 gchar *key = g_strdup_printf ("F%d", self->number+3);
1176                 g_object_set (G_OBJECT(self), "key", key, NULL);
1177                 g_free (key);
1178
1179                 g_critical ("HACK: start the wizard here\n");
1180         }
1181
1182         tilda_window_set_property_from_config (self, "accelerator-quit");
1183         tilda_window_set_property_from_config (self, "accelerator-next-tab");
1184         tilda_window_set_property_from_config (self, "accelerator-previous-tab");
1185         tilda_window_set_property_from_config (self, "accelerator-add-terminal");
1186         tilda_window_set_property_from_config (self, "accelerator-remove-terminal");
1187         tilda_window_set_property_from_config (self, "accelerator-copy");
1188         tilda_window_set_property_from_config (self, "accelerator-paste");
1189         tilda_window_set_property_from_config (self, "accelerator-goto-1");
1190         tilda_window_set_property_from_config (self, "accelerator-goto-2");
1191         tilda_window_set_property_from_config (self, "accelerator-goto-3");
1192         tilda_window_set_property_from_config (self, "accelerator-goto-4");
1193         tilda_window_set_property_from_config (self, "accelerator-goto-5");
1194         tilda_window_set_property_from_config (self, "accelerator-goto-6");
1195         tilda_window_set_property_from_config (self, "accelerator-goto-7");
1196         tilda_window_set_property_from_config (self, "accelerator-goto-8");
1197         tilda_window_set_property_from_config (self, "accelerator-goto-9");
1198         tilda_window_set_property_from_config (self, "accelerator-goto-10");
1199
1200         tilda_window_set_property_from_config (self, "height");
1201         tilda_window_set_property_from_config (self, "width");
1202         tilda_window_set_property_from_config (self, "x-position");
1203         tilda_window_set_property_from_config (self, "y-position");
1204         tilda_window_set_property_from_config (self, "initial-terminals");
1205         tilda_window_set_property_from_config (self, "animation-delay");
1206
1207         tilda_window_set_property_from_config (self, "tab-position");
1208         tilda_window_set_property_from_config (self, "animation-orientation");
1209
1210         tilda_window_set_property_from_config (self, "keep-above");
1211         tilda_window_set_property_from_config (self, "skip-taskbar-hint");
1212         tilda_window_set_property_from_config (self, "stick");
1213         tilda_window_set_property_from_config (self, "hidden-at-start");
1214         tilda_window_set_property_from_config (self, "centered-horizontally");
1215         tilda_window_set_property_from_config (self, "centered-vertically");
1216
1217         /* Add the initial terminal(s) */
1218         for (i=0; i<self->initial_terminals; ++i)
1219                 tilda_window_add_terminal (self);
1220
1221         /* Show us if we're ready. If not, just remain hidden. All sub-widgets must
1222          * be gtk_widget_show()n by this point. */
1223         if (!self->hidden_at_start)
1224         {
1225                 gtk_widget_show (self->window);
1226                 self->state = WINDOW_DOWN;
1227         }
1228         else
1229                 self->state = WINDOW_UP;
1230
1231         /* Register this object with DBus */
1232         tilda_window_dbus_register_object (self);
1233
1234         return obj;
1235 }
1236
1237 static void
1238 tilda_window_dispose (GObject *obj)
1239 {
1240         debug_enter ();
1241
1242         TildaWindow *self = (TildaWindow *) obj;
1243
1244         /* We don't want to run dispose twice, so just return immediately */
1245         if (self->dispose_has_run)
1246                 return;
1247
1248         /*
1249          * In dispose, you are supposed to free all types referenced from this
1250          * object which might themselves hold a reference to self. Generally,
1251          * the most simple solution is to unref all members on which you own a
1252          * reference.
1253          *
1254          * NOTE: See the following for how to deal with GtkObject-derived things:
1255          * http://library.gnome.org/devel/gtk/unstable/GtkObject.html
1256          */
1257         g_object_unref (G_OBJECT(self->accel_group));
1258         g_ptr_array_foreach (self->terms, g_object_unref, NULL);
1259         gtk_widget_destroy (self->window);
1260
1261         /* Unbind if we were set */
1262         if (self->key)
1263                 tomboy_keybinder_unbind (self->key, tilda_window_keybinding_cb);
1264
1265         /* Chain up to the parent class */
1266         G_OBJECT_CLASS (parent_class)->dispose (obj);
1267 }
1268
1269 static void
1270 tilda_window_finalize (GObject *obj)
1271 {
1272         debug_enter ();
1273
1274         TildaWindow *self = (TildaWindow *) obj;
1275
1276         /*
1277          * Here, complete the object's destruction.
1278          * You might not need to do much...
1279          */
1280         // TODO: g_free() any primitives here
1281         g_ptr_array_free (self->terms, TRUE);
1282
1283
1284         /* Chain up to the parent class */
1285         G_OBJECT_CLASS (parent_class)->finalize (obj);
1286 }
1287
1288 static void
1289 tilda_window_class_init (gpointer g_class,
1290                                                  gpointer g_class_data)
1291 {
1292         debug_enter ();
1293
1294         GObjectClass *gobject_class = G_OBJECT_CLASS (g_class);
1295         TildaWindowClass *klass = TILDA_WINDOW_CLASS (g_class);
1296         GParamSpec *pspec;
1297
1298         /* Hook our functions to this type */
1299         gobject_class->set_property = tilda_window_set_property;
1300         gobject_class->get_property = tilda_window_get_property;
1301         gobject_class->dispose = tilda_window_dispose;
1302         gobject_class->finalize = tilda_window_finalize;
1303         gobject_class->constructor = tilda_window_constructor;
1304
1305         parent_class = g_type_class_peek_parent (klass);
1306
1307         /* Install all of the properties */
1308         pspec = g_param_spec_int ("number",
1309                                                           _("Window number"),
1310                                                           NULL,
1311                                                           0,            // min value
1312                                                           INT_MAX,      // max value
1313                                                           0,            // def value
1314                                                           G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
1315
1316         g_object_class_install_property (gobject_class,
1317                                                                          TILDA_WINDOW_NUMBER,
1318                                                                          pspec);
1319
1320         pspec = g_param_spec_pointer ("controller",
1321                                                                   _("Pointer to window's controlling TildaController"),
1322                                                                   NULL,
1323                                                                   G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
1324
1325         g_object_class_install_property (gobject_class,
1326                                                                          TILDA_WINDOW_CONTROLLER,
1327                                                                          pspec);
1328
1329         pspec = g_param_spec_string ("accelerator-quit",
1330                                                                  _("Accelerator to quit this window"),
1331                                                                  NULL,
1332                                                                  NULL,
1333                                                                  G_PARAM_READWRITE);
1334
1335         g_object_class_install_property (gobject_class,
1336                                                                          TILDA_WINDOW_ACCEL_QUIT,
1337                                                                          pspec);
1338
1339         pspec = g_param_spec_string ("accelerator-next-tab",
1340                                                                  _("Accelerator to go to the next tab"),
1341                                                                  NULL,
1342                                                                  NULL,
1343                                                                  G_PARAM_READWRITE);
1344
1345         g_object_class_install_property (gobject_class,
1346                                                                          TILDA_WINDOW_ACCEL_NEXT_TAB,
1347                                                                          pspec);
1348
1349         pspec = g_param_spec_string ("accelerator-previous-tab",
1350                                                                  _("Accelerator to go to the previous tab"),
1351                                                                  NULL,
1352                                                                  NULL,
1353                                                                  G_PARAM_READWRITE);
1354
1355         g_object_class_install_property (gobject_class,
1356                                                                          TILDA_WINDOW_ACCEL_PREV_TAB,
1357                                                                          pspec);
1358
1359         pspec = g_param_spec_string ("accelerator-add-terminal",
1360                                                                  _("Accelerator to add a terminal"),
1361                                                                  NULL,
1362                                                                  NULL,
1363                                                                  G_PARAM_READWRITE);
1364
1365         g_object_class_install_property (gobject_class,
1366                                                                          TILDA_WINDOW_ACCEL_ADD_TERM,
1367                                                                          pspec);
1368
1369         pspec = g_param_spec_string ("accelerator-remove-terminal",
1370                                                                  _("Accelerator to remove a terminal"),
1371                                                                  NULL,
1372                                                                  NULL,
1373                                                                  G_PARAM_READWRITE);
1374
1375         g_object_class_install_property (gobject_class,
1376                                                                          TILDA_WINDOW_ACCEL_REMOVE_TERM,
1377                                                                          pspec);
1378
1379         pspec = g_param_spec_string ("accelerator-copy",
1380                                                                  _("Accelerator to copy to the clipboard"),
1381                                                                  NULL,
1382                                                                  NULL,
1383                                                                  G_PARAM_READWRITE);
1384
1385         g_object_class_install_property (gobject_class,
1386                                                                          TILDA_WINDOW_ACCEL_COPY,
1387                                                                          pspec);
1388
1389         pspec = g_param_spec_string ("accelerator-paste",
1390                                                                  _("Accelerator to paste from the clipboard"),
1391                                                                  NULL,
1392                                                                  NULL,
1393                                                                  G_PARAM_READWRITE);
1394
1395         g_object_class_install_property (gobject_class,
1396                                                                          TILDA_WINDOW_ACCEL_PASTE,
1397                                                                          pspec);
1398
1399         pspec = g_param_spec_string ("accelerator-goto-1",
1400                                                                  _("Accelerator to go to tab 1"),
1401                                                                  NULL,
1402                                                                  NULL,
1403                                                                  G_PARAM_READWRITE);
1404
1405         g_object_class_install_property (gobject_class,
1406                                                                          TILDA_WINDOW_ACCEL_GOTO_1,
1407                                                                          pspec);
1408
1409         pspec = g_param_spec_string ("accelerator-goto-2",
1410                                                                  _("Accelerator to go to tab 2"),
1411                                                                  NULL,
1412                                                                  NULL,
1413                                                                  G_PARAM_READWRITE);
1414
1415         g_object_class_install_property (gobject_class,
1416                                                                          TILDA_WINDOW_ACCEL_GOTO_2,
1417                                                                          pspec);
1418
1419         pspec = g_param_spec_string ("accelerator-goto-3",
1420                                                                  _("Accelerator to go to tab 3"),
1421                                                                  NULL,
1422                                                                  NULL,
1423                                                                  G_PARAM_READWRITE);
1424
1425         g_object_class_install_property (gobject_class,
1426                                                                          TILDA_WINDOW_ACCEL_GOTO_3,
1427                                                                          pspec);
1428
1429         pspec = g_param_spec_string ("accelerator-goto-4",
1430                                                                  _("Accelerator to go to tab 4"),
1431                                                                  NULL,
1432                                                                  NULL,
1433                                                                  G_PARAM_READWRITE);
1434
1435         g_object_class_install_property (gobject_class,
1436                                                                          TILDA_WINDOW_ACCEL_GOTO_4,
1437                                                                          pspec);
1438
1439         pspec = g_param_spec_string ("accelerator-goto-5",
1440                                                                  _("Accelerator to go to tab 5"),
1441                                                                  NULL,
1442                                                                  NULL,
1443                                                                  G_PARAM_READWRITE);
1444
1445         g_object_class_install_property (gobject_class,
1446                                                                          TILDA_WINDOW_ACCEL_GOTO_5,
1447                                                                          pspec);
1448
1449         pspec = g_param_spec_string ("accelerator-goto-6",
1450                                                                  _("Accelerator to go to tab 6"),
1451                                                                  NULL,
1452                                                                  NULL,
1453                                                                  G_PARAM_READWRITE);
1454
1455         g_object_class_install_property (gobject_class,
1456                                                                          TILDA_WINDOW_ACCEL_GOTO_6,
1457                                                                          pspec);
1458
1459         pspec = g_param_spec_string ("accelerator-goto-7",
1460                                                                  _("Accelerator to go to tab 7"),
1461                                                                  NULL,
1462                                                                  NULL,
1463                                                                  G_PARAM_READWRITE);
1464
1465         g_object_class_install_property (gobject_class,
1466                                                                          TILDA_WINDOW_ACCEL_GOTO_7,
1467                                                                          pspec);
1468
1469         pspec = g_param_spec_string ("accelerator-goto-8",
1470                                                                  _("Accelerator to go to tab 8"),
1471                                                                  NULL,
1472                                                                  NULL,
1473                                                                  G_PARAM_READWRITE);
1474
1475         g_object_class_install_property (gobject_class,
1476                                                                          TILDA_WINDOW_ACCEL_GOTO_8,
1477                                                                          pspec);
1478
1479         pspec = g_param_spec_string ("accelerator-goto-9",
1480                                                                  _("Accelerator to go to tab 9"),
1481                                                                  NULL,
1482                                                                  NULL,
1483                                                                  G_PARAM_READWRITE);
1484
1485         g_object_class_install_property (gobject_class,
1486                                                                          TILDA_WINDOW_ACCEL_GOTO_9,
1487                                                                          pspec);
1488
1489         pspec = g_param_spec_string ("accelerator-goto-10",
1490                                                                  _("Accelerator to go to tab 10"),
1491                                                                  NULL,
1492                                                                  NULL,
1493                                                                  G_PARAM_READWRITE);
1494
1495         g_object_class_install_property (gobject_class,
1496                                                                          TILDA_WINDOW_ACCEL_GOTO_10,
1497                                                                          pspec);
1498
1499         pspec = g_param_spec_string ("key",
1500                                                                  _("Window's drop-down keybinding"),
1501                                                                  NULL,
1502                                                                  NULL,
1503                                                                  G_PARAM_READWRITE);
1504
1505         g_object_class_install_property (gobject_class,
1506                                                                          TILDA_WINDOW_KEY,
1507                                                                          pspec);
1508
1509         pspec = g_param_spec_int ("height",
1510                                                           _("Window's height"),
1511                                                           NULL,
1512                                                           0,
1513                                                           INT_MAX,
1514                                                           0,
1515                                                           G_PARAM_READWRITE);
1516
1517         g_object_class_install_property (gobject_class,
1518                                                                          TILDA_WINDOW_HEIGHT,
1519                                                                          pspec);
1520
1521         pspec = g_param_spec_int ("width",
1522                                                           _("Window's width"),
1523                                                           NULL,
1524                                                           0,
1525                                                           INT_MAX,
1526                                                           0,
1527                                                           G_PARAM_READWRITE);
1528
1529         g_object_class_install_property (gobject_class,
1530                                                                          TILDA_WINDOW_WIDTH,
1531                                                                          pspec);
1532
1533         pspec = g_param_spec_int ("x-position",
1534                                                           _("Window's x position"),
1535                                                           NULL,
1536                                                           0,
1537                                                           INT_MAX,
1538                                                           0,
1539                                                           G_PARAM_READWRITE);
1540
1541         g_object_class_install_property (gobject_class,
1542                                                                          TILDA_WINDOW_X_POSITION,
1543                                                                          pspec);
1544
1545         pspec = g_param_spec_int ("y-position",
1546                                                           _("Window's y position"),
1547                                                           NULL,
1548                                                           0,
1549                                                           INT_MAX,
1550                                                           0,
1551                                                           G_PARAM_READWRITE);
1552
1553         g_object_class_install_property (gobject_class,
1554                                                                          TILDA_WINDOW_Y_POSITION,
1555                                                                          pspec);
1556
1557         pspec = g_param_spec_int ("initial-terminals",
1558                                                           _("Window's inital number of terminals"),
1559                                                           NULL,
1560                                                           1,
1561                                                           INT_MAX,
1562                                                           1,
1563                                                           G_PARAM_READWRITE);
1564
1565         g_object_class_install_property (gobject_class,
1566                                                                          TILDA_WINDOW_INITIAL_TERMINALS,
1567                                                                          pspec);
1568
1569         pspec = g_param_spec_enum ("tab-position",
1570                                                            _("Position of window's tab bar"),
1571                                                            NULL,
1572                                                            gtk_position_type_get_type(),
1573                                                            GTK_POS_TOP,
1574                                                            G_PARAM_READWRITE);
1575
1576         g_object_class_install_property (gobject_class,
1577                                                                          TILDA_WINDOW_TAB_POSITION,
1578                                                                          pspec);
1579
1580         pspec = g_param_spec_enum ("animation-orientation",
1581                                                            _("Window's animation orientation"),
1582                                                            NULL,
1583                                                            gtk_position_type_get_type(),
1584                                                            GTK_POS_TOP,
1585                                                            G_PARAM_READWRITE);
1586
1587         g_object_class_install_property (gobject_class,
1588                                                                          TILDA_WINDOW_ANIMATION_ORIENTATION,
1589                                                                          pspec);
1590
1591         pspec = g_param_spec_int ("animation-delay",
1592                                                           _("Amount of time in milliseconds between animation intervals"),
1593                                                           NULL,
1594                                                           0,
1595                                                           INT_MAX,
1596                                                           0,
1597                                                           G_PARAM_READWRITE);
1598
1599         g_object_class_install_property (gobject_class,
1600                                                                          TILDA_WINDOW_ANIMATION_DELAY,
1601                                                                          pspec);
1602
1603         pspec = g_param_spec_boolean ("keep-above",
1604                                                                   _("Keep this window above all others"),
1605                                                                   NULL,
1606                                                                   FALSE,
1607                                                                   G_PARAM_READWRITE);
1608
1609         g_object_class_install_property (gobject_class,
1610                                                                          TILDA_WINDOW_KEEP_ABOVE,
1611                                                                          pspec);
1612
1613         pspec = g_param_spec_boolean ("skip-taskbar-hint",
1614                                                                   _("Hide this window in the taskbar if TRUE"),
1615                                                                   NULL,
1616                                                                   FALSE,
1617                                                                   G_PARAM_READWRITE);
1618
1619         g_object_class_install_property (gobject_class,
1620                                                                          TILDA_WINDOW_SKIP_TASKBAR_HINT,
1621                                                                          pspec);
1622
1623         pspec = g_param_spec_boolean ("stick",
1624                                                                   _("Display this window on all workspaces"),
1625                                                                   NULL,
1626                                                                   FALSE,
1627                                                                   G_PARAM_READWRITE);
1628
1629         g_object_class_install_property (gobject_class,
1630                                                                          TILDA_WINDOW_STICK,
1631                                                                          pspec);
1632
1633         pspec = g_param_spec_boolean ("hidden-at-start",
1634                                                                   _("Hide the window when it is first created"),
1635                                                                   NULL,
1636                                                                   FALSE,
1637                                                                   G_PARAM_READWRITE);
1638
1639         g_object_class_install_property (gobject_class,
1640                                                                          TILDA_WINDOW_HIDDEN_AT_START,
1641                                                                          pspec);
1642
1643         pspec = g_param_spec_boolean ("centered-horizontally",
1644                                                                   _("Center the window horizontally"),
1645                                                                   NULL,
1646                                                                   FALSE,
1647                                                                   G_PARAM_READWRITE);
1648
1649         g_object_class_install_property (gobject_class,
1650                                                                          TILDA_WINDOW_CENTERED_HORIZONTALLY,
1651                                                                          pspec);
1652
1653         pspec = g_param_spec_boolean ("centered-vertically",
1654                                                                   _("Center the window vertically"),
1655                                                                   NULL,
1656                                                                   FALSE,
1657                                                                   G_PARAM_READWRITE);
1658
1659         g_object_class_install_property (gobject_class,
1660                                                                          TILDA_WINDOW_CENTERED_VERTICALLY,
1661                                                                          pspec);
1662
1663         pspec = g_param_spec_boolean ("have-real-transparency",
1664                                                                   NULL, NULL, FALSE, G_PARAM_READABLE);
1665
1666         g_object_class_install_property (gobject_class,
1667                                                                          TILDA_WINDOW_HAVE_REAL_TRANSPARENCY,
1668                                                                          pspec);
1669
1670         /* Hook the TildaWindow type into DBus */
1671         dbus_g_object_type_install_info (tilda_window_get_type(), &dbus_glib_tilda_window_object_info);
1672 }
1673
1674 GType
1675 tilda_window_get_type (void)
1676 {
1677         static GType type = 0;
1678
1679         if (type == 0)
1680         {
1681                 static const GTypeInfo info = {
1682                         sizeof (TildaWindowClass),
1683                         NULL,   /* base_init */
1684                         NULL,   /* base_finalize */
1685                         tilda_window_class_init,        /* class_init */
1686                         NULL,   /* class_finalize */
1687                         NULL,   /* class_data */
1688                         sizeof (TildaWindow),
1689                         0,              /* n_preallocs */
1690                         tilda_window_instance_init,     /* instance_init */
1691                 };
1692
1693                 type = g_type_register_static (G_TYPE_OBJECT,
1694                                                                            "TildaWindowType",
1695                                                                            &info,
1696                                                                            0);
1697         }
1698
1699         return type;
1700 }
1701
1702 /* vim: set ts=4 sts=4 sw=4 noet tw=112: */