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