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