Add debugging macros + use them
[tilda-gobject.git] / tilda-window.c
1 #include "tilda.h"
2 #include "tilda-window.h"
3 #include "tilda-window-dbus-glue.h"
4
5 /**
6  * Find the TildaTerminal corresponding to the currently selected
7  * tab in self->notebook. This could go away if TildaTerminal were
8  * a proper subclass of GtkWidget.
9  */
10 static TildaTerminal *
11 tilda_window_find_current_terminal (TildaWindow *self)
12 {
13         debug_enter();
14         debug_assert (TILDA_IS_WINDOW(self));
15
16         gint i;
17         TildaTerminal *ret;
18         gint current_page = gtk_notebook_get_current_page (GTK_NOTEBOOK(self->notebook));
19         GtkWidget *box = gtk_notebook_get_nth_page (GTK_NOTEBOOK(self->notebook), current_page);
20
21         for (i=0; i<self->terms->len; ++i)
22         {
23                 ret = g_ptr_array_index (self->terms, i);
24
25                 if (ret->hbox == box)
26                         return ret;
27         }
28
29         debug_printf ("ERROR: unable to find current terminal!\n");
30         return NULL;
31 }
32
33 static gint
34 tilda_window_find_next_free_terminal_number (TildaWindow *tw)
35 {
36         debug_enter ();
37         debug_assert (TILDA_IS_WINDOW(tw));
38
39         gint i, j;
40         gboolean found;
41
42         for (i=0; i<INT_MAX; ++i)
43         {
44                 found = FALSE;
45
46                 for (j=0; j<tw->terms->len; ++j)
47                 {
48                         TildaTerminal *tt = g_ptr_array_index (tw->terms, j);
49
50                         if (tt->number == i)
51                         {
52                                 found = TRUE;
53                                 break;
54                         }
55                 }
56
57                 if (!found)
58                         return i;
59         }
60
61         return 0;
62 }
63
64 static gboolean
65 tilda_window_add_term (TildaWindow *tw)
66 {
67         debug_enter ();
68         debug_assert (TILDA_IS_WINDOW(tw));
69
70         gint number;
71         TildaTerminal *tt;
72
73         number = tilda_window_find_next_free_terminal_number (tw);
74         tt = g_object_new (TILDA_TYPE_TERMINAL,
75                                            "number", number,
76                                            "window-number", tw->number,
77                                            "parent-window", tw,
78                                            NULL);
79         g_ptr_array_add (tw->terms, tt);
80
81         GtkWidget *label = gtk_label_new ("Tilda");
82         gint index = gtk_notebook_prepend_page (GTK_NOTEBOOK(tw->notebook), tt->hbox, label);
83         gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK(tw->notebook), tt->hbox, TRUE, TRUE, GTK_PACK_END);
84         //gtk_notebook_set_current_page (GTK_NOTEBOOK(tw->notebook), index);
85
86         if (gtk_notebook_get_n_pages (GTK_NOTEBOOK(tw->notebook)) > 1)
87                 gtk_notebook_set_show_tabs (GTK_NOTEBOOK(tw->notebook), TRUE);
88
89         return TRUE;
90 }
91
92 /**
93  * Remove the TildaTerminal with the given number from the given
94  * TildaWindow.
95  *
96  * Return: TRUE on success, FALSE otherwise.
97  */
98 gboolean
99 tilda_window_remove_term (TildaWindow *tw, gint terminal_number)
100 {
101         debug_enter  ();
102         debug_assert (TILDA_IS_WINDOW(tw));
103         debug_assert (terminal_number >= 0);
104
105         gint i;
106
107         for (i=0; i<tw->terms->len; ++i)
108         {
109                 TildaTerminal *tt = g_ptr_array_index (tw->terms, i);
110
111                 if (tt->number == terminal_number)
112                 {
113                         gint notebook_index = gtk_notebook_page_num (GTK_NOTEBOOK(tw->notebook), tt->hbox);
114
115                         /* Make sure the index was valid */
116                         if (notebook_index == -1)
117                         {
118                                 debug_printf ("ERROR: Bad Notebook Tab\n");
119                                 return FALSE;
120                         }
121
122                         /* Actually remove the terminal */
123                         gtk_notebook_remove_page (GTK_NOTEBOOK (tw->notebook), notebook_index);
124
125                         /* We should hide the tabs if there is only one tab left */
126                         if (gtk_notebook_get_n_pages (GTK_NOTEBOOK (tw->notebook)) == 1)
127                                 gtk_notebook_set_show_tabs (GTK_NOTEBOOK (tw->notebook), FALSE);
128
129 #if 0
130                         // FIXME FIXME FIXME: need to actually do the stuff below
131                         /* With no pages left, it's time to leave the program */
132                         if (gtk_notebook_get_n_pages (GTK_NOTEBOOK (tw->notebook)) < 1)
133                                 gtk_main_quit ();
134 #endif
135
136                         /* Remove the term from our lists, then free it */
137                         g_ptr_array_remove_fast (tw->terms, tt);
138                         g_object_unref (G_OBJECT(tt));
139
140                         /* Leave the loop, we're done */
141                         break;
142                 }
143         }
144
145         return TRUE;
146 }
147
148 /**
149  * This sets up the given TildaWindow for the capability of real
150  * transparency, if the X server is capable of it. */
151 static void
152 tilda_window_setup_real_transparency (TildaWindow *self)
153 {
154         debug_enter  ();
155         debug_assert (TILDA_IS_WINDOW(self));
156
157         GdkScreen *screen;
158         GdkColormap *colormap;
159
160         screen = gtk_widget_get_screen (GTK_WIDGET(self->window));
161         colormap = gdk_screen_get_rgba_colormap (screen);
162
163         /* If possible, set the RGBA colormap so VTE can use real alpha
164          * channels for transparency. */
165         if (colormap != NULL && gdk_screen_is_composited (screen))
166         {
167                 gtk_widget_set_colormap (GTK_WIDGET(self->window), colormap);
168                 self->have_real_transparency = TRUE;
169                 return;
170         }
171
172         self->have_real_transparency = FALSE;
173 }
174
175 /* Center the given TildaWindow in the horizontal axis */
176 static void
177 tilda_window_center_horizontally (TildaWindow *self)
178 {
179         debug_enter  ();
180         debug_assert (TILDA_IS_WINDOW(self));
181
182         const gint screen_center = gdk_screen_width() / 2;
183         const gint tilda_center  = self->width / 2;
184         const gint center_coord  = screen_center - tilda_center;
185
186         g_object_set (G_OBJECT(self), "x-position", center_coord, NULL);
187 }
188
189 /* Center the given TildaWindow in the vertical axis */
190 static void
191 tilda_window_center_vertically (TildaWindow *self)
192 {
193         debug_enter  ();
194         debug_assert (TILDA_IS_WINDOW(self));
195
196         const gint screen_center = gdk_screen_height() / 2;
197         const gint tilda_center  = self->height / 2;
198         const gint center_coord  = screen_center - tilda_center;
199
200         g_object_set (G_OBJECT(self), "y-position", center_coord, NULL);
201 }
202
203 static void
204 tilda_window_keybinding_cb (const gchar *keystr, gpointer data)
205 {
206         debug_enter  ();
207         debug_assert (TILDA_IS_WINDOW(data));
208
209         TildaWindow *self = TILDA_WINDOW(data);
210         TildaTerminal *tt;
211
212         // FIXME: this doesn't handle animation!
213
214         switch (self->state)
215         {
216                 case WINDOW_UP: /* Pull the window up */
217
218                         /* Bugfix: having this here keeps the tilda window from being
219                          * hidden if you turn off "stick", pull it down on workspace 1,
220                          * switch to workspace 2, then pull it up and back down. Without
221                          * this, something in metacity (at least) hides the window. Stupid. */
222                         gtk_window_deiconify (GTK_WINDOW(self->window));
223
224                         /* Re-set the window properties that do not linger after hiding the
225                          * window. I know this looks stupid, but it keeps all of the state-
226                          * changing code in the place it belongs: the property-setting code. */
227                         g_object_set (G_OBJECT(self),
228                                         "keep-above", self->keep_above,
229                                         "stick", self->stick,
230                                         NULL);
231                         gtk_window_present_with_time (GTK_WINDOW(self->window),
232                                                                                   tomboy_keybinder_get_current_event_time());
233
234                         /* Focusing the term here works perfectly, near as I can tell */
235                         tt = tilda_window_find_current_terminal (self);
236                         gtk_widget_grab_focus (GTK_WIDGET(tt->vte_term));
237
238                         self->state = WINDOW_DOWN;
239                         break;
240
241                 case WINDOW_DOWN: /* Pull the window up */
242
243                         gtk_widget_hide (GTK_WIDGET(self->window));
244
245                         self->state = WINDOW_UP;
246                         break;
247
248                 default:
249                         debug_printf ("ERROR: Window is in a bad state!\n");
250
251                         /* Pretend we're down, for good measure.... */
252                         self->state = WINDOW_DOWN;
253                         break;
254         }
255 }
256
257 /**
258  * Attempt to bind the new_key to show this window.
259  *
260  * Return: TRUE if successful, FALSE otherwise.
261  */
262 static gboolean
263 tilda_window_try_to_bind_key (TildaWindow *self, const gchar *new_key)
264 {
265         debug_enter  ();
266         debug_assert (TILDA_IS_WINDOW(self));
267
268         gboolean ret = FALSE;
269
270         /* Make sure the new key is not null in any way */
271         if (new_key == NULL || strcmp("", new_key) == 0)
272                 return FALSE;
273
274         /* Unbind if we were set */
275         if (self->key)
276                 tomboy_keybinder_unbind (self->key, tilda_window_keybinding_cb, self);
277
278         ret = tomboy_keybinder_bind (new_key, tilda_window_keybinding_cb, self);
279
280         /* If it was successful, update the self->key variable and be done with it */
281         if (ret)
282         {
283                 g_free (self->key);
284                 self->key = g_strdup (new_key);
285                 return TRUE;
286         }
287
288         g_printerr ("Keybinding unsuccessful. Reverting to original key\n");
289
290         /* Not successful, so rebind the old key, and return FALSE */
291         if (self->key != NULL && strcmp("",self->key) != 0)
292         {
293                 ret = tomboy_keybinder_bind (self->key, tilda_window_keybinding_cb, self);
294
295                 /* Check that it went ok */
296                 if (!ret)
297                         g_printerr ("Unable to bind original key as well! Oh shit...\n");
298         }
299         else
300                 g_printerr ("No original key to revert to!\n");
301
302         return FALSE;
303 }
304
305 static void
306 tilda_window_dbus_register_object (TildaWindow *tw)
307 {
308         debug_enter  ();
309         debug_assert (TILDA_IS_WINDOW(tw));
310
311         gchar *object_path;
312
313         // Register this object with DBus
314         object_path = g_strdup_printf ("/net/sourceforge/Tilda/Window%d", tw->number);
315         dbus_g_connection_register_g_object (dbus_connection, object_path, G_OBJECT(tw));
316         g_free (object_path);
317 }
318
319 /*******************************************************************************
320  * ALL GOBJECT STUFF BELOW PLEASE
321  ******************************************************************************/
322
323 static GObjectClass *parent_class = NULL;
324
325 enum tilda_window_properties {
326         TILDA_WINDOW_NUMBER = 1,
327
328         TILDA_WINDOW_KEY,
329
330         TILDA_WINDOW_HEIGHT,
331         TILDA_WINDOW_WIDTH,
332         TILDA_WINDOW_X_POSITION,
333         TILDA_WINDOW_Y_POSITION,
334
335         TILDA_WINDOW_TAB_POSITION,
336         TILDA_WINDOW_ANIMATION_ORIENTATION,
337         TILDA_WINDOW_ANIMATION_DELAY,
338
339         TILDA_WINDOW_KEEP_ABOVE,
340         TILDA_WINDOW_SKIP_TASKBAR_HINT,
341         TILDA_WINDOW_STICK,
342         TILDA_WINDOW_HIDDEN_AT_START,
343         TILDA_WINDOW_CENTERED_HORIZONTALLY,
344         TILDA_WINDOW_CENTERED_VERTICALLY,
345
346         TILDA_WINDOW_HAVE_REAL_TRANSPARENCY,
347 };
348
349 static void
350 tilda_window_instance_init (GTypeInstance *instance,
351                                                         gpointer       g_class)
352 {
353         debug_enter ();
354
355         TildaWindow *self = (TildaWindow *) instance;
356         self->dispose_has_run = FALSE;
357
358         /* Initialize all properties */
359         self->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
360         self->notebook = gtk_notebook_new ();
361         self->terms = g_ptr_array_new ();
362
363         /* Somewhat of a "poison" value, incase we don't set this */
364         self->number = 0xdeadbeef;
365
366         self->state = WINDOW_UP;
367 }
368
369 static void
370 tilda_window_set_property (GObject      *object,
371                                                    guint         property_id,
372                                                    const GValue *value,
373                                                    GParamSpec   *pspec)
374 {
375         TildaWindow *self = (TildaWindow *) object;
376
377         switch (property_id) {
378
379                 case TILDA_WINDOW_NUMBER:
380                         self->number = g_value_get_int (value);
381                         debug_printf ("window number: %d\n", self->number);
382                         break;
383
384                 case TILDA_WINDOW_KEY:
385                         tilda_window_try_to_bind_key (self, g_value_get_string (value));
386                         debug_printf ("window key %s\n", self->key);
387                         break;
388
389                 case TILDA_WINDOW_HEIGHT:
390                         self->height = g_value_get_int (value);
391                         gtk_widget_set_size_request (self->window, self->width, self->height);
392                         gtk_window_resize (GTK_WINDOW(self->window), self->width, self->height);
393                         debug_printf ("window height: %d\n", self->height);
394                         break;
395
396                 case TILDA_WINDOW_WIDTH:
397                         self->width = g_value_get_int (value);
398                         gtk_widget_set_size_request (self->window, self->width, self->height);
399                         gtk_window_resize (GTK_WINDOW(self->window), self->width, self->height);
400                         debug_printf ("window width: %d\n", self->width);
401                         break;
402
403                 case TILDA_WINDOW_X_POSITION:
404                         self->x_position = g_value_get_int (value);
405                         gtk_window_move (GTK_WINDOW(self->window), self->x_position, self->y_position);
406                         debug_printf ("window x position: %d\n", self->x_position);
407                         break;
408
409                 case TILDA_WINDOW_Y_POSITION:
410                         self->y_position = g_value_get_int (value);
411                         gtk_window_move (GTK_WINDOW(self->window), self->x_position, self->y_position);
412                         debug_printf ("window y position: %d\n", self->y_position);
413                         break;
414
415                 case TILDA_WINDOW_TAB_POSITION:
416                         self->tab_position = g_value_get_int (value);
417                         gtk_notebook_set_tab_pos (GTK_NOTEBOOK(self->notebook), self->tab_position);
418                         debug_printf ("window tab position: %d\n", self->tab_position);
419                         break;
420
421                 case TILDA_WINDOW_ANIMATION_ORIENTATION:
422                         self->animation_orientation = g_value_get_int (value);
423                         debug_printf ("window animation orientation: %d\n", self->animation_orientation);
424                         break;
425
426                 case TILDA_WINDOW_ANIMATION_DELAY:
427                         self->animation_delay = g_value_get_int (value);
428                         debug_printf ("window animation delay: %d\n", self->animation_delay);
429                         break;
430
431                 case TILDA_WINDOW_KEEP_ABOVE:
432                         self->keep_above = g_value_get_boolean (value);
433                         gtk_window_set_keep_above (GTK_WINDOW(self->window), self->keep_above);
434                         debug_printf ("window keep above: %d\n", self->keep_above);
435                         break;
436
437                 case TILDA_WINDOW_SKIP_TASKBAR_HINT:
438                         self->skip_taskbar_hint = g_value_get_boolean (value);
439                         gtk_window_set_skip_taskbar_hint (GTK_WINDOW(self->window), self->skip_taskbar_hint);
440                         debug_printf ("window skip taskbar hint: %d\n", self->skip_taskbar_hint);
441                         break;
442
443                 case TILDA_WINDOW_STICK:
444                         self->stick = g_value_get_boolean (value);
445
446                         /* This is moderately ugly, but GTK+ does it this way... */
447                         self->stick ? gtk_window_stick (GTK_WINDOW(self->window))
448                                                 : gtk_window_unstick (GTK_WINDOW(self->window));
449                         debug_printf ("window stick: %d\n", self->stick);
450                         break;
451
452                 case TILDA_WINDOW_HIDDEN_AT_START:
453                         self->hidden_at_start = g_value_get_boolean (value);
454                         debug_printf ("window hidden at start: %d\n", self->hidden_at_start);
455                         break;
456
457                 case TILDA_WINDOW_CENTERED_HORIZONTALLY:
458                         self->centered_horizontally = g_value_get_boolean (value);
459                         if (self->centered_horizontally)
460                                 tilda_window_center_horizontally (self);
461                         debug_printf ("window centered horizontally: %d\n", self->centered_horizontally);
462                         break;
463
464                 case TILDA_WINDOW_CENTERED_VERTICALLY:
465                         self->centered_vertically = g_value_get_boolean (value);
466                         if (self->centered_vertically)
467                                 tilda_window_center_vertically (self);
468                         debug_printf ("window centered vertically: %d\n", self->centered_vertically);
469                         break;
470
471                 case TILDA_WINDOW_HAVE_REAL_TRANSPARENCY:
472                         self->have_real_transparency = g_value_get_boolean (value);
473                         debug_printf ("window have real transp: %d\n", self->have_real_transparency);
474                         break;
475
476                 default:
477                         /* We don't have this property */
478                         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
479                         break;
480         }
481 }
482
483 static void
484 tilda_window_get_property (GObject    *object,
485                                                    guint       property_id,
486                                                    GValue     *value,
487                                                    GParamSpec *pspec)
488 {
489         TildaWindow *self = (TildaWindow *) object;
490
491         switch (property_id) {
492
493                 case TILDA_WINDOW_NUMBER:
494                         g_value_set_int (value, self->number);
495                         break;
496
497                 case TILDA_WINDOW_KEY:
498                         g_value_set_string (value, self->key);
499                         break;
500
501                 case TILDA_WINDOW_HEIGHT:
502                         g_value_set_int (value, self->height);
503                         break;
504
505                 case TILDA_WINDOW_WIDTH:
506                         g_value_set_int (value, self->width);
507                         break;
508
509                 case TILDA_WINDOW_X_POSITION:
510                         g_value_set_int (value, self->x_position);
511                         break;
512
513                 case TILDA_WINDOW_Y_POSITION:
514                         g_value_set_int (value, self->y_position);
515                         break;
516
517                 case TILDA_WINDOW_TAB_POSITION:
518                         g_value_set_int (value, self->tab_position);
519                         break;
520
521                 case TILDA_WINDOW_ANIMATION_ORIENTATION:
522                         g_value_set_int (value, self->animation_orientation);
523                         break;
524
525                 case TILDA_WINDOW_ANIMATION_DELAY:
526                         g_value_set_int (value, self->animation_delay);
527                         break;
528
529                 case TILDA_WINDOW_KEEP_ABOVE:
530                         g_value_set_boolean (value, self->keep_above);
531                         break;
532
533                 case TILDA_WINDOW_SKIP_TASKBAR_HINT:
534                         g_value_set_boolean (value, self->skip_taskbar_hint);
535                         break;
536
537                 case TILDA_WINDOW_STICK:
538                         g_value_set_boolean (value, self->stick);
539                         break;
540
541                 case TILDA_WINDOW_HIDDEN_AT_START:
542                         g_value_set_boolean (value, self->hidden_at_start);
543                         break;
544
545                 case TILDA_WINDOW_CENTERED_HORIZONTALLY:
546                         g_value_set_boolean (value, self->centered_horizontally);
547                         break;
548
549                 case TILDA_WINDOW_CENTERED_VERTICALLY:
550                         g_value_set_boolean (value, self->centered_vertically);
551                         break;
552
553                 case TILDA_WINDOW_HAVE_REAL_TRANSPARENCY:
554                         g_value_set_boolean (value, self->have_real_transparency);
555                         break;
556
557                 default:
558                         /* We don't have this property */
559                         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
560                         break;
561         }
562 }
563
564 static GObject *
565 tilda_window_constructor (GType                  type,
566                                                   guint                  n_construct_properties,
567                                                   GObjectConstructParam *construct_properties)
568 {
569         debug_enter ();
570
571         GObject *obj;
572         TildaWindow *self;
573
574         /* Invoke parent constructor */
575         TildaWindowClass *klass;
576         klass = TILDA_WINDOW_CLASS (g_type_class_peek (TILDA_TYPE_WINDOW));
577         obj = parent_class->constructor (type,
578                                                                          n_construct_properties,
579                                                                          construct_properties);
580
581         /* Do other stuff here. The object is ready to go now, and all
582          * ctor properties have been set.
583          *
584          * TODO: This is the place to do DBus-init */
585         self = TILDA_WINDOW(obj);
586
587         /* Register this object with DBus */
588         tilda_window_dbus_register_object (self);
589
590         /* Try to set up real transparency */
591         tilda_window_setup_real_transparency (self);
592
593         gtk_container_add (GTK_CONTAINER(self->window), self->notebook);
594         gtk_widget_show (self->notebook);
595
596         // FIXME: Remove these, and replace with reads from the config system
597         g_object_set (G_OBJECT(self), "key", "F2", NULL);
598         g_object_set (G_OBJECT(self), "x-position", 0, "y-position", 0, NULL);
599         g_object_set (G_OBJECT(self), "height", 400, "width", 1680, NULL);
600         g_object_set (G_OBJECT(self), "keep-above", TRUE, "stick", TRUE, NULL);
601         g_object_set (G_OBJECT(self), "hidden-at-start", FALSE, NULL);
602
603         gtk_window_set_decorated (GTK_WINDOW(self->window), FALSE);
604
605         // FIXME: It should be configurable how many terms we add at startup
606         tilda_window_add_term (self);
607         tilda_window_add_term (self);
608
609         /* Show us if we're ready. If not, just remain hidden. All sub-widgets must
610          * be gtk_widget_show()n by this point. */
611         if (!self->hidden_at_start)
612         {
613                 gtk_widget_show (self->window);
614                 self->state = WINDOW_DOWN;
615         }
616         else
617                 self->state = WINDOW_UP;
618
619         return obj;
620 }
621
622 static void
623 my_unref (gpointer data, gpointer user_data)
624 {
625         debug_enter ();
626
627         // FIXME: This function should probably be eliminated. It /is/ rather ugly
628         g_object_unref (G_OBJECT(data));
629 }
630
631 static void
632 tilda_window_dispose (GObject *obj)
633 {
634         debug_enter ();
635
636         TildaWindow *self = (TildaWindow *) obj;
637
638         /* We don't want to run dispose twice, so just return immediately */
639         if (self->dispose_has_run)
640                 return;
641
642         /*
643          * In dispose, you are supposed to free all types referenced from this
644          * object which might themselves hold a reference to self. Generally,
645          * the most simple solution is to unref all members on which you own a
646          * reference.
647          *
648          * NOTE: See the following for how to deal with GtkObject-derived things:
649          * http://library.gnome.org/devel/gtk/unstable/GtkObject.html
650          */
651         g_ptr_array_foreach (self->terms, my_unref, NULL);
652         gtk_widget_destroy (self->window);
653
654         /* Chain up to the parent class */
655         G_OBJECT_CLASS (parent_class)->dispose (obj);
656 }
657
658 static void
659 tilda_window_finalize (GObject *obj)
660 {
661         debug_enter ();
662
663         TildaWindow *self = (TildaWindow *) obj;
664
665         /*
666          * Here, complete the object's destruction.
667          * You might not need to do much...
668          */
669         // TODO: g_free() any primitives here
670         g_ptr_array_free (self->terms, TRUE);
671
672
673         /* Chain up to the parent class */
674         G_OBJECT_CLASS (parent_class)->finalize (obj);
675 }
676
677 static void
678 tilda_window_class_init (gpointer g_class,
679                                                  gpointer g_class_data)
680 {
681         debug_enter ();
682
683         GObjectClass *gobject_class = G_OBJECT_CLASS (g_class);
684         TildaWindowClass *klass = TILDA_WINDOW_CLASS (g_class);
685         GParamSpec *pspec;
686
687         /* Hook our functions to this type */
688         gobject_class->set_property = tilda_window_set_property;
689         gobject_class->get_property = tilda_window_get_property;
690         gobject_class->dispose = tilda_window_dispose;
691         gobject_class->finalize = tilda_window_finalize;
692         gobject_class->constructor = tilda_window_constructor;
693
694         parent_class = g_type_class_peek_parent (klass);
695
696         /* Install all of the properties */
697         pspec = g_param_spec_int ("number",
698                                                           "Window number",
699                                                           "Set window's number",
700                                                           0,            // min value
701                                                           INT_MAX,      // max value
702                                                           0,            // def value
703                                                           G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
704
705         g_object_class_install_property (gobject_class,
706                                                                          TILDA_WINDOW_NUMBER,
707                                                                          pspec);
708
709         pspec = g_param_spec_string ("key",
710                                                                  "Window's drop-down keybinding",
711                                                                  NULL,
712                                                                  NULL,
713                                                                  G_PARAM_READWRITE);
714
715         g_object_class_install_property (gobject_class,
716                                                                          TILDA_WINDOW_KEY,
717                                                                          pspec);
718
719         pspec = g_param_spec_int ("height",
720                                                           "Window's height",
721                                                           NULL,
722                                                           0,
723                                                           INT_MAX,
724                                                           0,
725                                                           G_PARAM_READWRITE);
726
727         g_object_class_install_property (gobject_class,
728                                                                          TILDA_WINDOW_HEIGHT,
729                                                                          pspec);
730
731         pspec = g_param_spec_int ("width",
732                                                           "Window's width",
733                                                           NULL,
734                                                           0,
735                                                           INT_MAX,
736                                                           0,
737                                                           G_PARAM_READWRITE);
738
739         g_object_class_install_property (gobject_class,
740                                                                          TILDA_WINDOW_WIDTH,
741                                                                          pspec);
742
743         pspec = g_param_spec_int ("x-position",
744                                                           "Window's x position",
745                                                           NULL,
746                                                           0,
747                                                           INT_MAX,
748                                                           0,
749                                                           G_PARAM_READWRITE);
750
751         g_object_class_install_property (gobject_class,
752                                                                          TILDA_WINDOW_X_POSITION,
753                                                                          pspec);
754
755         pspec = g_param_spec_int ("y-position",
756                                                           "Window's y position",
757                                                           NULL,
758                                                           0,
759                                                           INT_MAX,
760                                                           0,
761                                                           G_PARAM_READWRITE);
762
763         g_object_class_install_property (gobject_class,
764                                                                          TILDA_WINDOW_Y_POSITION,
765                                                                          pspec);
766
767         pspec = g_param_spec_int ("tab-position",
768                                                           "Window's tab position",
769                                                           NULL,
770                                                           0,
771                                                           INT_MAX,
772                                                           0,
773                                                           G_PARAM_READWRITE);
774
775         g_object_class_install_property (gobject_class,
776                                                                          TILDA_WINDOW_TAB_POSITION,
777                                                                          pspec);
778
779         pspec = g_param_spec_int ("animation-orientation",
780                                                           "Window's animation orientation",
781                                                           NULL,
782                                                           0,
783                                                           INT_MAX,
784                                                           0,
785                                                           G_PARAM_READWRITE);
786
787         g_object_class_install_property (gobject_class,
788                                                                          TILDA_WINDOW_ANIMATION_ORIENTATION,
789                                                                          pspec);
790
791         pspec = g_param_spec_int ("animation-delay",
792                                                           "Amount of time in milliseconds between animation intervals",
793                                                           NULL,
794                                                           0,
795                                                           INT_MAX,
796                                                           0,
797                                                           G_PARAM_READWRITE);
798
799         g_object_class_install_property (gobject_class,
800                                                                          TILDA_WINDOW_ANIMATION_DELAY,
801                                                                          pspec);
802
803         pspec = g_param_spec_boolean ("keep-above",
804                                                                   "Keep this window above all others",
805                                                                   NULL,
806                                                                   FALSE,
807                                                                   G_PARAM_READWRITE);
808
809         g_object_class_install_property (gobject_class,
810                                                                          TILDA_WINDOW_KEEP_ABOVE,
811                                                                          pspec);
812
813         pspec = g_param_spec_boolean ("skip-taskbar-hint",
814                                                                   "Hide this window in the taskbar if TRUE",
815                                                                   NULL,
816                                                                   FALSE,
817                                                                   G_PARAM_READWRITE);
818
819         g_object_class_install_property (gobject_class,
820                                                                          TILDA_WINDOW_SKIP_TASKBAR_HINT,
821                                                                          pspec);
822
823         pspec = g_param_spec_boolean ("stick",
824                                                                   "Display this window on all workspaces",
825                                                                   NULL,
826                                                                   FALSE,
827                                                                   G_PARAM_READWRITE);
828
829         g_object_class_install_property (gobject_class,
830                                                                          TILDA_WINDOW_STICK,
831                                                                          pspec);
832
833         pspec = g_param_spec_boolean ("hidden-at-start",
834                                                                   "Hide the window when it is first created",
835                                                                   NULL,
836                                                                   FALSE,
837                                                                   G_PARAM_READWRITE);
838
839         g_object_class_install_property (gobject_class,
840                                                                          TILDA_WINDOW_HIDDEN_AT_START,
841                                                                          pspec);
842
843         pspec = g_param_spec_boolean ("centered-horizontally",
844                                                                   "Center the window horizontally",
845                                                                   NULL,
846                                                                   FALSE,
847                                                                   G_PARAM_READWRITE);
848
849         g_object_class_install_property (gobject_class,
850                                                                          TILDA_WINDOW_CENTERED_HORIZONTALLY,
851                                                                          pspec);
852
853         pspec = g_param_spec_boolean ("centered-vertically",
854                                                                   "Center the window vertically",
855                                                                   NULL,
856                                                                   FALSE,
857                                                                   G_PARAM_READWRITE);
858
859         g_object_class_install_property (gobject_class,
860                                                                          TILDA_WINDOW_CENTERED_VERTICALLY,
861                                                                          pspec);
862
863         pspec = g_param_spec_boolean ("have-real-transparency",
864                                                                   NULL, NULL, FALSE, G_PARAM_READABLE);
865
866         g_object_class_install_property (gobject_class,
867                                                                          TILDA_WINDOW_HAVE_REAL_TRANSPARENCY,
868                                                                          pspec);
869
870         /* Hook the TildaWindow type into DBus */
871         dbus_g_object_type_install_info (tilda_window_get_type(), &dbus_glib_tilda_window_object_info);
872 }
873
874 GType
875 tilda_window_get_type (void)
876 {
877         static GType type = 0;
878
879         if (type == 0)
880         {
881                 static const GTypeInfo info = {
882                         sizeof (TildaWindowClass),
883                         NULL,   /* base_init */
884                         NULL,   /* base_finalize */
885                         tilda_window_class_init,        /* class_init */
886                         NULL,   /* class_finalize */
887                         NULL,   /* class_data */
888                         sizeof (TildaWindow),
889                         0,              /* n_preallocs */
890                         tilda_window_instance_init,     /* instance_init */
891                 };
892
893                 type = g_type_register_static (G_TYPE_OBJECT,
894                                                                            "TildaWindowType",
895                                                                            &info,
896                                                                            0);
897         }
898
899         return type;
900 }
901
902 #if 0
903
904 int main (int argc, char *argv[])
905 {
906         GObject *tw;
907         gint test_number = INT_MIN;
908
909         /* Initialize the GObject type system */
910         g_type_init ();
911         gtk_init (&argc, &argv);
912
913         tw = g_object_new (TILDA_TYPE_WINDOW, "number", 10, NULL);
914         g_object_get (G_OBJECT (tw), "number", &test_number, NULL);
915         g_assert (test_number == 10);
916
917         g_object_unref (G_OBJECT (tw));
918
919         tw = g_object_new (TILDA_TYPE_WINDOW, "number", 22, NULL);
920         g_object_get (G_OBJECT (tw), "number", &test_number, NULL);
921         g_assert (test_number == 22);
922
923         gtk_main ();
924
925         g_object_unref (G_OBJECT (tw));
926
927         return 0;
928 }
929
930 #endif
931
932 /* vim: set ts=4 sts=4 sw=4 noet tw=112: */