1 #include <gdk/gdkx.h> /* for gdk_x11_window_set_user_time() */
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"
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.
16 static TildaTerminal *
17 tilda_window_find_current_terminal (TildaWindow *self)
20 debug_assert (TILDA_IS_WINDOW(self));
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);
27 for (i=0; i<self->terms->len; ++i)
29 ret = g_ptr_array_index (self->terms, i);
35 debug_printf ("ERROR: unable to find current terminal!\n");
40 tilda_window_find_next_free_terminal_number (TildaWindow *self)
43 debug_assert (TILDA_IS_WINDOW(self));
48 for (i=0; i<INT_MAX; ++i)
52 for (j=0; j<self->terms->len; ++j)
54 TildaTerminal *tt = g_ptr_array_index (self->terms, j);
71 * Clean up and remove self completely from the program
73 * Should only be used by DBus...
76 tilda_window_close (TildaWindow *self)
79 debug_assert (TILDA_IS_WINDOW(self));
81 tilda_controller_remove_window (TILDA_CONTROLLER(self->controller), self->number);
87 tilda_window_add_terminal (TildaWindow *self)
90 debug_assert (TILDA_IS_WINDOW(self));
97 number = tilda_window_find_next_free_terminal_number (self);
98 tt = g_object_new (TILDA_TYPE_TERMINAL,
100 "parent-window", self,
102 g_ptr_array_add (self->terms, tt);
104 label = gtk_label_new ("Tilda");
105 notebook_index = gtk_notebook_prepend_page (GTK_NOTEBOOK(self->notebook), tt->hbox, label);
106 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK(self->notebook), tt->hbox,
107 self->full_width_tabs, TRUE, GTK_PACK_START);
108 gtk_notebook_set_current_page (GTK_NOTEBOOK(self->notebook), notebook_index);
110 if (gtk_notebook_get_n_pages (GTK_NOTEBOOK(self->notebook)) > 1)
111 gtk_notebook_set_show_tabs (GTK_NOTEBOOK(self->notebook), TRUE);
113 /* Focus the VTE Terminal */
114 gtk_widget_grab_focus (tt->vte_term);
120 * Remove the TildaTerminal with the given number from the given
123 * Return: TRUE on success, FALSE otherwise.
126 tilda_window_remove_terminal (TildaWindow *self, gint terminal_number)
129 debug_assert (TILDA_IS_WINDOW(self));
130 debug_assert (terminal_number >= 0);
134 for (i=0; i<self->terms->len; ++i)
136 TildaTerminal *tt = g_ptr_array_index (self->terms, i);
138 if (tt->number == terminal_number)
140 gint notebook_index = gtk_notebook_page_num (GTK_NOTEBOOK(self->notebook), tt->hbox);
142 /* Make sure the index was valid */
143 if (notebook_index == -1)
145 debug_printf ("ERROR: Bad Notebook Tab\n");
149 /* Actually remove the terminal */
150 gtk_notebook_remove_page (GTK_NOTEBOOK (self->notebook), notebook_index);
152 /* We should hide the tabs if there is only one tab left */
153 if (gtk_notebook_get_n_pages (GTK_NOTEBOOK (self->notebook)) == 1)
154 gtk_notebook_set_show_tabs (GTK_NOTEBOOK (self->notebook), FALSE);
156 /* Remove the term from our lists, then free it */
157 g_ptr_array_remove_fast (self->terms, tt);
158 g_object_unref (G_OBJECT(tt));
160 /* With no pages left, it's time to remove this window */
161 if (gtk_notebook_get_n_pages (GTK_NOTEBOOK (self->notebook)) < 1)
163 debug_printf ("no terminals left, closing window %d\n", self->number);
164 tilda_controller_remove_window (TILDA_CONTROLLER(self->controller), self->number);
167 /* Leave the loop, we're done */
176 * This sets up the given TildaWindow for the capability of real
177 * transparency, if the X server is capable of it. */
179 tilda_window_setup_real_transparency (TildaWindow *self)
182 debug_assert (TILDA_IS_WINDOW(self));
185 GdkColormap *colormap;
187 screen = gtk_widget_get_screen (GTK_WIDGET(self->window));
188 colormap = gdk_screen_get_rgba_colormap (screen);
190 /* If possible, set the RGBA colormap so VTE can use real alpha
191 * channels for transparency. */
192 if (colormap != NULL && gdk_screen_is_composited (screen))
194 gtk_widget_set_colormap (GTK_WIDGET(self->window), colormap);
195 self->have_real_transparency = TRUE;
199 self->have_real_transparency = FALSE;
202 /* Center the given TildaWindow in the horizontal axis */
204 tilda_window_center_horizontally (TildaWindow *self)
207 debug_assert (TILDA_IS_WINDOW(self));
209 const gint screen_center = gdk_screen_width() / 2;
210 const gint tilda_center = self->width / 2;
211 const gint center_coord = screen_center - tilda_center;
213 g_object_set (G_OBJECT(self), "x-position", center_coord, NULL);
216 /* Center the given TildaWindow in the vertical axis */
218 tilda_window_center_vertically (TildaWindow *self)
221 debug_assert (TILDA_IS_WINDOW(self));
223 const gint screen_center = gdk_screen_height() / 2;
224 const gint tilda_center = self->height / 2;
225 const gint center_coord = screen_center - tilda_center;
227 g_object_set (G_OBJECT(self), "y-position", center_coord, NULL);
231 tilda_window_keybinding_cb (const gchar *keystr, gpointer data)
234 debug_assert (TILDA_IS_WINDOW(data));
236 TildaWindow *self = TILDA_WINDOW(data);
239 /* This call sets the X11 window property _NET_WM_USER_TIME, which GTK+ normally
240 * sets for us. However, because this callback is activated via a global keybinding,
241 * we see the event before GDK / GTK+ does. Therefore, to get the focus, we must
242 * set the property ourselves. */
243 gdk_x11_window_set_user_time (GTK_WIDGET(self->window)->window,
244 tomboy_keybinder_get_current_event_time());
248 case WINDOW_UP: /* Pull the window up */
250 /* Bugfix: having this here keeps the tilda window from being
251 * hidden if you turn off "stick", pull it down on workspace 1,
252 * switch to workspace 2, then pull it up and back down. Without
253 * this, something in metacity (at least) hides the window. Stupid. */
254 gtk_window_deiconify (GTK_WINDOW(self->window));
256 /* Re-set the window properties that do not linger after hiding the
257 * window. I know this looks stupid, but it keeps all of the state-
258 * changing code in the place it belongs: the property-setting code. */
259 g_object_set (G_OBJECT(self),
260 "keep-above", self->keep_above,
261 "stick", self->stick,
263 gtk_widget_show (GTK_WIDGET(self->window));
265 /* Focusing the term here works perfectly, near as I can tell */
266 tt = tilda_window_find_current_terminal (self);
267 gtk_widget_grab_focus (GTK_WIDGET(tt->vte_term));
269 self->state = WINDOW_DOWN;
272 case WINDOW_DOWN: /* Pull the window up */
274 gtk_widget_hide (GTK_WIDGET(self->window));
276 self->state = WINDOW_UP;
280 debug_printf ("ERROR: Window is in a bad state!\n");
282 /* Pretend we're down, for good measure.... */
283 self->state = WINDOW_DOWN;
289 * Attempt to bind the new_key to show this window.
291 * Return: TRUE if successful, FALSE otherwise.
294 tilda_window_try_to_bind_key (TildaWindow *self, const gchar *new_key)
297 debug_assert (TILDA_IS_WINDOW(self));
299 gboolean ret = FALSE;
301 /* Make sure the new key is not null in any way */
302 if (new_key == NULL || g_ascii_strcasecmp("", new_key) == 0)
305 /* Check that no other windows are using the key */
306 // FIXME: there should be a hidden option to disable this. Maybe some people want
307 // to have logs in two Tildas, and just show them with one key. Crazy...
308 if (tilda_controller_global_key_in_use(TILDA_CONTROLLER(self->controller), new_key))
311 /* Unbind if we were set */
313 tomboy_keybinder_unbind (self->key, tilda_window_keybinding_cb);
315 ret = tomboy_keybinder_bind (new_key, tilda_window_keybinding_cb, self);
317 /* If it was successful, update the self->key variable and be done with it */
321 self->key = g_strdup (new_key);
325 g_printerr (_("Bind key '%s' failed. Reverting to original keybinding\n"), self->key);
327 /* Not successful, so rebind the old key, and return FALSE */
328 if (self->key != NULL && g_ascii_strcasecmp("",self->key) != 0)
330 ret = tomboy_keybinder_bind (self->key, tilda_window_keybinding_cb, self);
332 /* Check that it went ok */
334 g_printerr (_("Unable to re-bind original key '%s'. Oh shit...\n"), self->key);
337 g_printerr (_("No original key to revert to!\n"));
343 tilda_window_dbus_register_object (TildaWindow *self)
346 debug_assert (TILDA_IS_WINDOW(self));
350 /* If DBus is not running, leave */
351 if (!dbus_connection)
354 /* Register this object with DBus */
355 object_path = g_strdup_printf ("/net/sourceforge/Tilda/Window%d", self->number);
356 dbus_g_connection_register_g_object (dbus_connection, object_path, G_OBJECT(self));
357 g_free (object_path);
360 /*******************************************************************************
361 * All accelerator-related stuff below
362 ******************************************************************************/
364 typedef gboolean (*TildaWindowAccelCallback) (TildaWindow *self, gpointer data);
367 * This function updates the accelerator used to call the given function for this
368 * TildaWindow. If accel is NULL, then func will be removed (no accelerator will
369 * cause func to be called).
371 * Returns: TRUE on success, FALSE on failure
374 tilda_window_update_accelerator (TildaWindow *self, /* object */
375 gchar **accel_to_update, /* self->??? */
376 const gchar *accel, /* new accel */
377 const TildaWindowAccelCallback func)
380 debug_assert (TILDA_IS_WINDOW(self));
381 debug_assert (accel_to_update != NULL);
382 debug_assert (func != NULL);
389 /* Remove the old accelerator if there was a previous one set */
390 if (*accel_to_update != NULL)
392 /* This should always parse, we've done it before! */
393 gtk_accelerator_parse (*accel_to_update, &key, &mod);
394 ret = gtk_accel_group_disconnect_key (self->accel_group, key, mod);
397 /* If we are just removing the old accelerator, we're already done */
400 g_free (*accel_to_update);
401 *accel_to_update = NULL;
405 /* Create the closure for this function */
406 closure = g_cclosure_new_swap (G_CALLBACK(func), self, NULL);
408 /* Try to parse the new accelerator */
409 gtk_accelerator_parse (accel, &key, &mod);
411 if (!gtk_accelerator_valid (key, mod))
413 g_warning (_("Failed to parse accelerator: %s\n"), accel);
415 /* Re-install the old accelerator */
416 if (*accel_to_update != NULL)
418 gtk_accelerator_parse (*accel_to_update, &key, &mod);
419 gtk_accel_group_connect (self->accel_group, key, mod, GTK_ACCEL_VISIBLE, closure);
424 /* All good, g_free() the old accelerator, g_strdup() the new one */
425 g_free (*accel_to_update);
426 *accel_to_update = g_strdup(accel);
428 /* Add the new accelerator */
429 gtk_accel_group_connect (self->accel_group, key, mod, GTK_ACCEL_VISIBLE, closure);
435 tilda_window_accel_quit_cb (TildaWindow *self, gpointer data)
438 debug_assert (TILDA_IS_WINDOW(self));
440 tilda_window_close (self);
442 /* Do not keep propagating */
447 tilda_window_accel_next_tab_cb (TildaWindow *self, gpointer data)
450 debug_assert (TILDA_IS_WINDOW(self));
455 num_pages = gtk_notebook_get_n_pages (GTK_NOTEBOOK(self->notebook));
456 current_page = gtk_notebook_get_current_page (GTK_NOTEBOOK(self->notebook));
458 /* Go to next page (with wrapping) */
459 if (num_pages != (current_page + num_pages))
460 gtk_notebook_next_page (GTK_NOTEBOOK(self->notebook));
462 gtk_notebook_set_current_page (GTK_NOTEBOOK(self->notebook), num_pages-1);
464 /* Do not keep propagating */
469 tilda_window_accel_prev_tab_cb (TildaWindow *self, gpointer data)
472 debug_assert (TILDA_IS_WINDOW(self));
477 num_pages = gtk_notebook_get_n_pages (GTK_NOTEBOOK(self->notebook));
478 current_page = gtk_notebook_get_current_page (GTK_NOTEBOOK(self->notebook));
480 if ((num_pages-1) != current_page)
481 gtk_notebook_prev_page (GTK_NOTEBOOK(self->notebook));
483 gtk_notebook_set_current_page (GTK_NOTEBOOK(self->notebook), 0);
485 /* Do not keep propagating */
490 tilda_window_accel_add_term_cb (TildaWindow *self, gpointer data)
493 debug_assert (TILDA_IS_WINDOW(self));
495 tilda_window_add_terminal (self);
497 /* Do not keep propagating */
502 tilda_window_accel_remove_term_cb (TildaWindow *self, gpointer data)
505 debug_assert (TILDA_IS_WINDOW(self));
507 TildaTerminal *tt = tilda_window_find_current_terminal (self);
509 tilda_window_remove_terminal (self, tt->number);
511 /* Do not keep propagating */
516 tilda_window_accel_copy_cb (TildaWindow *self, gpointer data)
519 debug_assert (TILDA_IS_WINDOW(self));
521 TildaTerminal *tt = tilda_window_find_current_terminal (self);
523 vte_terminal_copy_clipboard (VTE_TERMINAL(tt->vte_term));
525 /* Do not keep propagating */
530 tilda_window_accel_paste_cb (TildaWindow *self, gpointer data)
533 debug_assert (TILDA_IS_WINDOW(self));
535 TildaTerminal *tt = tilda_window_find_current_terminal (self);
537 vte_terminal_paste_clipboard (VTE_TERMINAL(tt->vte_term));
539 /* Do not keep propagating */
544 tilda_window_accel_goto_generic (TildaWindow *self, guint number)
547 debug_assert (TILDA_IS_WINDOW(self));
549 gtk_notebook_set_current_page (GTK_NOTEBOOK(self->notebook), number-1);
551 /* Do not keep propagating */
556 tilda_window_accel_goto_1_cb (TildaWindow *self, gpointer data)
559 debug_assert (TILDA_IS_WINDOW(self));
561 return tilda_window_accel_goto_generic (self, 1);
565 tilda_window_accel_goto_2_cb (TildaWindow *self, gpointer data)
568 debug_assert (TILDA_IS_WINDOW(self));
570 return tilda_window_accel_goto_generic (self, 2);
574 tilda_window_accel_goto_3_cb (TildaWindow *self, gpointer data)
577 debug_assert (TILDA_IS_WINDOW(self));
579 return tilda_window_accel_goto_generic (self, 3);
583 tilda_window_accel_goto_4_cb (TildaWindow *self, gpointer data)
586 debug_assert (TILDA_IS_WINDOW(self));
588 return tilda_window_accel_goto_generic (self, 4);
592 tilda_window_accel_goto_5_cb (TildaWindow *self, gpointer data)
595 debug_assert (TILDA_IS_WINDOW(self));
597 return tilda_window_accel_goto_generic (self, 5);
601 tilda_window_accel_goto_6_cb (TildaWindow *self, gpointer data)
604 debug_assert (TILDA_IS_WINDOW(self));
606 return tilda_window_accel_goto_generic (self, 6);
610 tilda_window_accel_goto_7_cb (TildaWindow *self, gpointer data)
613 debug_assert (TILDA_IS_WINDOW(self));
615 return tilda_window_accel_goto_generic (self, 7);
619 tilda_window_accel_goto_8_cb (TildaWindow *self, gpointer data)
622 debug_assert (TILDA_IS_WINDOW(self));
624 return tilda_window_accel_goto_generic (self, 8);
628 tilda_window_accel_goto_9_cb (TildaWindow *self, gpointer data)
631 debug_assert (TILDA_IS_WINDOW(self));
633 return tilda_window_accel_goto_generic (self, 9);
637 tilda_window_accel_goto_10_cb (TildaWindow *self, gpointer data)
640 debug_assert (TILDA_IS_WINDOW(self));
642 return tilda_window_accel_goto_generic (self, 10);
645 /*******************************************************************************
646 * ALL GOBJECT STUFF BELOW PLEASE
647 ******************************************************************************/
649 static GObjectClass *parent_class = NULL;
651 enum tilda_window_properties {
652 TILDA_WINDOW_NUMBER = 1,
653 TILDA_WINDOW_CONTROLLER,
655 TILDA_WINDOW_ACCEL_QUIT,
656 TILDA_WINDOW_ACCEL_NEXT_TAB,
657 TILDA_WINDOW_ACCEL_PREV_TAB,
658 TILDA_WINDOW_ACCEL_ADD_TERM,
659 TILDA_WINDOW_ACCEL_REMOVE_TERM,
660 TILDA_WINDOW_ACCEL_COPY,
661 TILDA_WINDOW_ACCEL_PASTE,
662 TILDA_WINDOW_ACCEL_GOTO_1,
663 TILDA_WINDOW_ACCEL_GOTO_2,
664 TILDA_WINDOW_ACCEL_GOTO_3,
665 TILDA_WINDOW_ACCEL_GOTO_4,
666 TILDA_WINDOW_ACCEL_GOTO_5,
667 TILDA_WINDOW_ACCEL_GOTO_6,
668 TILDA_WINDOW_ACCEL_GOTO_7,
669 TILDA_WINDOW_ACCEL_GOTO_8,
670 TILDA_WINDOW_ACCEL_GOTO_9,
671 TILDA_WINDOW_ACCEL_GOTO_10,
677 TILDA_WINDOW_X_POSITION,
678 TILDA_WINDOW_Y_POSITION,
679 TILDA_WINDOW_INITIAL_TERMINALS,
681 TILDA_WINDOW_TAB_POSITION,
682 TILDA_WINDOW_ANIMATION_ORIENTATION,
683 TILDA_WINDOW_ANIMATION_DELAY,
685 TILDA_WINDOW_KEEP_ABOVE,
686 TILDA_WINDOW_SKIP_TASKBAR_HINT,
688 TILDA_WINDOW_HIDDEN_AT_START,
689 TILDA_WINDOW_CENTERED_HORIZONTALLY,
690 TILDA_WINDOW_CENTERED_VERTICALLY,
691 TILDA_WINDOW_FULL_WIDTH_TABS,
693 TILDA_WINDOW_HAVE_REAL_TRANSPARENCY,
697 tilda_window_instance_init (GTypeInstance *instance,
702 TildaWindow *self = (TildaWindow *) instance;
703 self->dispose_has_run = FALSE;
705 /* Initialize all properties */
706 self->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
707 self->notebook = gtk_notebook_new ();
708 self->terms = g_ptr_array_new ();
711 self->accel_group = gtk_accel_group_new ();
712 gtk_window_add_accel_group (GTK_WINDOW(self->window), self->accel_group);
714 /* Somewhat of a "poison" value, incase we don't set this */
715 self->number = 0xdeadbeef;
716 self->controller = NULL;
718 self->state = WINDOW_UP;
722 tilda_window_set_property (GObject *object,
727 TildaWindow *self = (TildaWindow *) object;
730 switch (property_id) {
732 case TILDA_WINDOW_NUMBER:
733 self->number = g_value_get_int (value);
734 debug_printf ("window number: %d\n", self->number);
737 case TILDA_WINDOW_CONTROLLER:
738 self->controller = g_value_get_pointer (value);
739 debug_printf ("window controller: 0x%p\n", self->controller);
742 case TILDA_WINDOW_ACCEL_QUIT:
743 tilda_window_update_accelerator (self,
745 g_value_get_string (value),
746 tilda_window_accel_quit_cb);
747 debug_printf ("window accel quit: %s\n", self->accel_quit);
750 case TILDA_WINDOW_ACCEL_NEXT_TAB:
751 tilda_window_update_accelerator (self,
752 &self->accel_next_tab,
753 g_value_get_string (value),
754 tilda_window_accel_next_tab_cb);
755 debug_printf ("window accel next tab: %s\n", self->accel_next_tab);
758 case TILDA_WINDOW_ACCEL_PREV_TAB:
759 tilda_window_update_accelerator (self,
760 &self->accel_prev_tab,
761 g_value_get_string (value),
762 tilda_window_accel_prev_tab_cb);
763 debug_printf ("window accel prev tab: %s\n", self->accel_prev_tab);
766 case TILDA_WINDOW_ACCEL_ADD_TERM:
767 tilda_window_update_accelerator (self,
768 &self->accel_add_term,
769 g_value_get_string (value),
770 tilda_window_accel_add_term_cb);
771 debug_printf ("window accel add term: %s\n", self->accel_add_term);
774 case TILDA_WINDOW_ACCEL_REMOVE_TERM:
775 tilda_window_update_accelerator (self,
776 &self->accel_remove_term,
777 g_value_get_string (value),
778 tilda_window_accel_remove_term_cb);
779 debug_printf ("window accel remove term: %s\n", self->accel_remove_term);
782 case TILDA_WINDOW_ACCEL_COPY:
783 tilda_window_update_accelerator (self,
785 g_value_get_string (value),
786 tilda_window_accel_copy_cb);
787 debug_printf ("window accel copy: %s\n", self->accel_copy);
790 case TILDA_WINDOW_ACCEL_PASTE:
791 tilda_window_update_accelerator (self,
793 g_value_get_string (value),
794 tilda_window_accel_paste_cb);
795 debug_printf ("window accel paste: %s\n", self->accel_paste);
798 case TILDA_WINDOW_ACCEL_GOTO_1:
799 tilda_window_update_accelerator (self,
801 g_value_get_string (value),
802 tilda_window_accel_goto_1_cb);
803 debug_printf ("window accel goto 1: %s\n", self->accel_goto_1);
806 case TILDA_WINDOW_ACCEL_GOTO_2:
807 tilda_window_update_accelerator (self,
809 g_value_get_string (value),
810 tilda_window_accel_goto_2_cb);
811 debug_printf ("window accel goto 2: %s\n", self->accel_goto_2);
814 case TILDA_WINDOW_ACCEL_GOTO_3:
815 tilda_window_update_accelerator (self,
817 g_value_get_string (value),
818 tilda_window_accel_goto_3_cb);
819 debug_printf ("window accel goto 3: %s\n", self->accel_goto_3);
822 case TILDA_WINDOW_ACCEL_GOTO_4:
823 tilda_window_update_accelerator (self,
825 g_value_get_string (value),
826 tilda_window_accel_goto_4_cb);
827 debug_printf ("window accel goto 4: %s\n", self->accel_goto_4);
830 case TILDA_WINDOW_ACCEL_GOTO_5:
831 tilda_window_update_accelerator (self,
833 g_value_get_string (value),
834 tilda_window_accel_goto_5_cb);
835 debug_printf ("window accel goto 5: %s\n", self->accel_goto_5);
838 case TILDA_WINDOW_ACCEL_GOTO_6:
839 tilda_window_update_accelerator (self,
841 g_value_get_string (value),
842 tilda_window_accel_goto_6_cb);
843 debug_printf ("window accel goto 6: %s\n", self->accel_goto_6);
846 case TILDA_WINDOW_ACCEL_GOTO_7:
847 tilda_window_update_accelerator (self,
849 g_value_get_string (value),
850 tilda_window_accel_goto_7_cb);
851 debug_printf ("window accel goto 7: %s\n", self->accel_goto_7);
854 case TILDA_WINDOW_ACCEL_GOTO_8:
855 tilda_window_update_accelerator (self,
857 g_value_get_string (value),
858 tilda_window_accel_goto_8_cb);
859 debug_printf ("window accel goto 8: %s\n", self->accel_goto_8);
862 case TILDA_WINDOW_ACCEL_GOTO_9:
863 tilda_window_update_accelerator (self,
865 g_value_get_string (value),
866 tilda_window_accel_goto_9_cb);
867 debug_printf ("window accel goto 9: %s\n", self->accel_goto_9);
870 case TILDA_WINDOW_ACCEL_GOTO_10:
871 tilda_window_update_accelerator (self,
872 &self->accel_goto_10,
873 g_value_get_string (value),
874 tilda_window_accel_goto_10_cb);
875 debug_printf ("window accel goto 10: %s\n", self->accel_goto_10);
878 case TILDA_WINDOW_KEY:
879 tilda_window_try_to_bind_key (self, g_value_get_string (value));
880 debug_printf ("window key %s\n", self->key);
883 case TILDA_WINDOW_HEIGHT:
884 self->height = g_value_get_int (value);
885 gtk_widget_set_size_request (self->window, self->width, self->height);
886 gtk_window_resize (GTK_WINDOW(self->window), self->width, self->height);
887 debug_printf ("window height: %d\n", self->height);
890 case TILDA_WINDOW_WIDTH:
891 self->width = g_value_get_int (value);
892 gtk_widget_set_size_request (self->window, self->width, self->height);
893 gtk_window_resize (GTK_WINDOW(self->window), self->width, self->height);
894 debug_printf ("window width: %d\n", self->width);
897 case TILDA_WINDOW_X_POSITION:
898 self->x_position = g_value_get_int (value);
899 gtk_window_move (GTK_WINDOW(self->window), self->x_position, self->y_position);
900 debug_printf ("window x position: %d\n", self->x_position);
903 case TILDA_WINDOW_Y_POSITION:
904 self->y_position = g_value_get_int (value);
905 gtk_window_move (GTK_WINDOW(self->window), self->x_position, self->y_position);
906 debug_printf ("window y position: %d\n", self->y_position);
909 case TILDA_WINDOW_INITIAL_TERMINALS:
910 self->initial_terminals = g_value_get_int (value);
911 debug_printf ("window initial terminals: %d\n", self->initial_terminals);
914 case TILDA_WINDOW_TAB_POSITION:
915 self->tab_position = g_value_get_enum (value);
916 gtk_notebook_set_tab_pos (GTK_NOTEBOOK(self->notebook), self->tab_position);
917 debug_printf ("window tab position: %d\n", self->tab_position);
920 case TILDA_WINDOW_ANIMATION_ORIENTATION:
921 self->animation_orientation = g_value_get_enum (value);
922 debug_printf ("window animation orientation: %d\n", self->animation_orientation);
925 case TILDA_WINDOW_ANIMATION_DELAY:
926 self->animation_delay = g_value_get_int (value);
927 debug_printf ("window animation delay: %d\n", self->animation_delay);
930 case TILDA_WINDOW_KEEP_ABOVE:
931 self->keep_above = g_value_get_boolean (value);
932 gtk_window_set_keep_above (GTK_WINDOW(self->window), self->keep_above);
933 debug_printf ("window keep above: %d\n", self->keep_above);
936 case TILDA_WINDOW_SKIP_TASKBAR_HINT:
937 self->skip_taskbar_hint = g_value_get_boolean (value);
938 gtk_window_set_skip_taskbar_hint (GTK_WINDOW(self->window), self->skip_taskbar_hint);
939 debug_printf ("window skip taskbar hint: %d\n", self->skip_taskbar_hint);
942 case TILDA_WINDOW_STICK:
943 self->stick = g_value_get_boolean (value);
945 /* This is moderately ugly, but GTK+ does it this way... */
946 self->stick ? gtk_window_stick (GTK_WINDOW(self->window))
947 : gtk_window_unstick (GTK_WINDOW(self->window));
948 debug_printf ("window stick: %d\n", self->stick);
951 case TILDA_WINDOW_HIDDEN_AT_START:
952 self->hidden_at_start = g_value_get_boolean (value);
953 debug_printf ("window hidden at start: %d\n", self->hidden_at_start);
956 case TILDA_WINDOW_CENTERED_HORIZONTALLY:
957 self->centered_horizontally = g_value_get_boolean (value);
958 if (self->centered_horizontally)
959 tilda_window_center_horizontally (self);
960 debug_printf ("window centered horizontally: %d\n", self->centered_horizontally);
963 case TILDA_WINDOW_CENTERED_VERTICALLY:
964 self->centered_vertically = g_value_get_boolean (value);
965 if (self->centered_vertically)
966 tilda_window_center_vertically (self);
967 debug_printf ("window centered vertically: %d\n", self->centered_vertically);
970 case TILDA_WINDOW_FULL_WIDTH_TABS:
971 self->full_width_tabs = g_value_get_boolean (value);
972 for (i=0; i<self->terms->len; ++i)
973 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK(self->notebook),
974 TILDA_TERMINAL(g_ptr_array_index(self->terms, i))->hbox,
975 self->full_width_tabs,
978 debug_printf ("window full width tabs: %d\n", self->full_width_tabs);
981 case TILDA_WINDOW_HAVE_REAL_TRANSPARENCY:
982 self->have_real_transparency = g_value_get_boolean (value);
983 debug_printf ("window have real transp: %d\n", self->have_real_transparency);
987 /* We don't have this property */
988 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
994 tilda_window_get_property (GObject *object,
999 TildaWindow *self = (TildaWindow *) object;
1001 switch (property_id) {
1003 case TILDA_WINDOW_NUMBER:
1004 g_value_set_int (value, self->number);
1007 case TILDA_WINDOW_CONTROLLER:
1008 g_value_set_pointer (value, self->controller);
1011 case TILDA_WINDOW_ACCEL_QUIT:
1012 g_value_set_string (value, self->accel_quit);
1015 case TILDA_WINDOW_ACCEL_NEXT_TAB:
1016 g_value_set_string (value, self->accel_next_tab);
1019 case TILDA_WINDOW_ACCEL_PREV_TAB:
1020 g_value_set_string (value, self->accel_prev_tab);
1023 case TILDA_WINDOW_ACCEL_ADD_TERM:
1024 g_value_set_string (value, self->accel_prev_tab);
1027 case TILDA_WINDOW_ACCEL_REMOVE_TERM:
1028 g_value_set_string (value, self->accel_remove_term);
1031 case TILDA_WINDOW_ACCEL_COPY:
1032 g_value_set_string (value, self->accel_copy);
1035 case TILDA_WINDOW_ACCEL_PASTE:
1036 g_value_set_string (value, self->accel_paste);
1039 case TILDA_WINDOW_ACCEL_GOTO_1:
1040 g_value_set_string (value, self->accel_goto_1);
1043 case TILDA_WINDOW_ACCEL_GOTO_2:
1044 g_value_set_string (value, self->accel_goto_2);
1047 case TILDA_WINDOW_ACCEL_GOTO_3:
1048 g_value_set_string (value, self->accel_goto_3);
1051 case TILDA_WINDOW_ACCEL_GOTO_4:
1052 g_value_set_string (value, self->accel_goto_4);
1055 case TILDA_WINDOW_ACCEL_GOTO_5:
1056 g_value_set_string (value, self->accel_goto_5);
1059 case TILDA_WINDOW_ACCEL_GOTO_6:
1060 g_value_set_string (value, self->accel_goto_6);
1063 case TILDA_WINDOW_ACCEL_GOTO_7:
1064 g_value_set_string (value, self->accel_goto_7);
1067 case TILDA_WINDOW_ACCEL_GOTO_8:
1068 g_value_set_string (value, self->accel_goto_8);
1071 case TILDA_WINDOW_ACCEL_GOTO_9:
1072 g_value_set_string (value, self->accel_goto_9);
1075 case TILDA_WINDOW_ACCEL_GOTO_10:
1076 g_value_set_string (value, self->accel_goto_10);
1079 case TILDA_WINDOW_KEY:
1080 g_value_set_string (value, self->key);
1083 case TILDA_WINDOW_HEIGHT:
1084 g_value_set_int (value, self->height);
1087 case TILDA_WINDOW_WIDTH:
1088 g_value_set_int (value, self->width);
1091 case TILDA_WINDOW_X_POSITION:
1092 g_value_set_int (value, self->x_position);
1095 case TILDA_WINDOW_Y_POSITION:
1096 g_value_set_int (value, self->y_position);
1099 case TILDA_WINDOW_INITIAL_TERMINALS:
1100 g_value_set_int (value, self->initial_terminals);
1103 case TILDA_WINDOW_TAB_POSITION:
1104 g_value_set_enum (value, self->tab_position);
1107 case TILDA_WINDOW_ANIMATION_ORIENTATION:
1108 g_value_set_enum (value, self->animation_orientation);
1111 case TILDA_WINDOW_ANIMATION_DELAY:
1112 g_value_set_int (value, self->animation_delay);
1115 case TILDA_WINDOW_KEEP_ABOVE:
1116 g_value_set_boolean (value, self->keep_above);
1119 case TILDA_WINDOW_SKIP_TASKBAR_HINT:
1120 g_value_set_boolean (value, self->skip_taskbar_hint);
1123 case TILDA_WINDOW_STICK:
1124 g_value_set_boolean (value, self->stick);
1127 case TILDA_WINDOW_HIDDEN_AT_START:
1128 g_value_set_boolean (value, self->hidden_at_start);
1131 case TILDA_WINDOW_CENTERED_HORIZONTALLY:
1132 g_value_set_boolean (value, self->centered_horizontally);
1135 case TILDA_WINDOW_CENTERED_VERTICALLY:
1136 g_value_set_boolean (value, self->centered_vertically);
1139 case TILDA_WINDOW_FULL_WIDTH_TABS:
1140 g_value_set_boolean (value, self->full_width_tabs);
1143 case TILDA_WINDOW_HAVE_REAL_TRANSPARENCY:
1144 g_value_set_boolean (value, self->have_real_transparency);
1148 /* We don't have this property */
1149 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1155 tilda_window_constructor (GType type,
1156 guint n_construct_properties,
1157 GObjectConstructParam *construct_properties)
1165 /* Invoke parent constructor */
1166 TildaWindowClass *klass;
1167 klass = TILDA_WINDOW_CLASS (g_type_class_peek (TILDA_TYPE_WINDOW));
1168 obj = parent_class->constructor (type,
1169 n_construct_properties,
1170 construct_properties);
1172 /* Do other stuff here. The object is ready to go now, and all
1173 * ctor properties have been set.
1175 self = TILDA_WINDOW(obj);
1177 /* Try to set up real transparency */
1178 tilda_window_setup_real_transparency (self);
1180 gtk_container_add (GTK_CONTAINER(self->window), self->notebook);
1181 g_object_set (G_OBJECT(self->notebook), "can-focus", FALSE, NULL);
1182 gtk_widget_show (self->notebook);
1184 /* Tilda is never decorated */
1185 gtk_window_set_decorated (GTK_WINDOW(self->window), FALSE);
1187 /* Set all of the properties out of the config file */
1188 tilda_window_set_property_from_config (self, "key");
1190 // FIXME: hack -- start the wizard in this case :)
1193 gchar *key = g_strdup_printf ("F%d", self->number+3);
1194 g_object_set (G_OBJECT(self), "key", key, NULL);
1197 g_critical ("HACK: start the wizard here\n");
1200 tilda_window_set_property_from_config (self, "accelerator-quit");
1201 tilda_window_set_property_from_config (self, "accelerator-next-tab");
1202 tilda_window_set_property_from_config (self, "accelerator-previous-tab");
1203 tilda_window_set_property_from_config (self, "accelerator-add-terminal");
1204 tilda_window_set_property_from_config (self, "accelerator-remove-terminal");
1205 tilda_window_set_property_from_config (self, "accelerator-copy");
1206 tilda_window_set_property_from_config (self, "accelerator-paste");
1207 tilda_window_set_property_from_config (self, "accelerator-goto-1");
1208 tilda_window_set_property_from_config (self, "accelerator-goto-2");
1209 tilda_window_set_property_from_config (self, "accelerator-goto-3");
1210 tilda_window_set_property_from_config (self, "accelerator-goto-4");
1211 tilda_window_set_property_from_config (self, "accelerator-goto-5");
1212 tilda_window_set_property_from_config (self, "accelerator-goto-6");
1213 tilda_window_set_property_from_config (self, "accelerator-goto-7");
1214 tilda_window_set_property_from_config (self, "accelerator-goto-8");
1215 tilda_window_set_property_from_config (self, "accelerator-goto-9");
1216 tilda_window_set_property_from_config (self, "accelerator-goto-10");
1218 tilda_window_set_property_from_config (self, "height");
1219 tilda_window_set_property_from_config (self, "width");
1220 tilda_window_set_property_from_config (self, "x-position");
1221 tilda_window_set_property_from_config (self, "y-position");
1222 tilda_window_set_property_from_config (self, "initial-terminals");
1223 tilda_window_set_property_from_config (self, "animation-delay");
1225 tilda_window_set_property_from_config (self, "tab-position");
1226 tilda_window_set_property_from_config (self, "animation-orientation");
1228 tilda_window_set_property_from_config (self, "keep-above");
1229 tilda_window_set_property_from_config (self, "skip-taskbar-hint");
1230 tilda_window_set_property_from_config (self, "stick");
1231 tilda_window_set_property_from_config (self, "hidden-at-start");
1232 tilda_window_set_property_from_config (self, "centered-horizontally");
1233 tilda_window_set_property_from_config (self, "centered-vertically");
1234 tilda_window_set_property_from_config (self, "full-width-tabs");
1236 /* Add the initial terminal(s) */
1237 for (i=0; i<self->initial_terminals; ++i)
1238 tilda_window_add_terminal (self);
1240 /* Show us if we're ready. If not, just remain hidden. All sub-widgets must
1241 * be gtk_widget_show()n by this point. */
1242 if (!self->hidden_at_start)
1244 gtk_widget_show (self->window);
1245 self->state = WINDOW_DOWN;
1248 self->state = WINDOW_UP;
1250 /* Register this object with DBus */
1251 tilda_window_dbus_register_object (self);
1257 tilda_window_dispose (GObject *obj)
1261 TildaWindow *self = (TildaWindow *) obj;
1263 /* We don't want to run dispose twice, so just return immediately */
1264 if (self->dispose_has_run)
1268 * In dispose, you are supposed to free all types referenced from this
1269 * object which might themselves hold a reference to self. Generally,
1270 * the most simple solution is to unref all members on which you own a
1273 * NOTE: See the following for how to deal with GtkObject-derived things:
1274 * http://library.gnome.org/devel/gtk/unstable/GtkObject.html
1276 g_object_unref (G_OBJECT(self->accel_group));
1277 g_ptr_array_foreach (self->terms, g_object_unref, NULL);
1278 gtk_widget_destroy (self->window);
1280 /* Unbind if we were set */
1282 tomboy_keybinder_unbind (self->key, tilda_window_keybinding_cb);
1284 /* Chain up to the parent class */
1285 G_OBJECT_CLASS (parent_class)->dispose (obj);
1289 tilda_window_finalize (GObject *obj)
1293 TildaWindow *self = (TildaWindow *) obj;
1296 * Here, complete the object's destruction.
1297 * You might not need to do much...
1299 // TODO: g_free() any primitives here
1300 g_ptr_array_free (self->terms, TRUE);
1303 /* Chain up to the parent class */
1304 G_OBJECT_CLASS (parent_class)->finalize (obj);
1308 tilda_window_class_init (gpointer g_class,
1309 gpointer g_class_data)
1313 GObjectClass *gobject_class = G_OBJECT_CLASS (g_class);
1314 TildaWindowClass *klass = TILDA_WINDOW_CLASS (g_class);
1317 /* Hook our functions to this type */
1318 gobject_class->set_property = tilda_window_set_property;
1319 gobject_class->get_property = tilda_window_get_property;
1320 gobject_class->dispose = tilda_window_dispose;
1321 gobject_class->finalize = tilda_window_finalize;
1322 gobject_class->constructor = tilda_window_constructor;
1324 parent_class = g_type_class_peek_parent (klass);
1326 /* Install all of the properties */
1327 pspec = g_param_spec_int ("number",
1331 INT_MAX, // max value
1333 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
1335 g_object_class_install_property (gobject_class,
1336 TILDA_WINDOW_NUMBER,
1339 pspec = g_param_spec_pointer ("controller",
1340 _("Pointer to window's controlling TildaController"),
1342 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
1344 g_object_class_install_property (gobject_class,
1345 TILDA_WINDOW_CONTROLLER,
1348 pspec = g_param_spec_string ("accelerator-quit",
1349 _("Accelerator to quit this window"),
1354 g_object_class_install_property (gobject_class,
1355 TILDA_WINDOW_ACCEL_QUIT,
1358 pspec = g_param_spec_string ("accelerator-next-tab",
1359 _("Accelerator to go to the next tab"),
1364 g_object_class_install_property (gobject_class,
1365 TILDA_WINDOW_ACCEL_NEXT_TAB,
1368 pspec = g_param_spec_string ("accelerator-previous-tab",
1369 _("Accelerator to go to the previous tab"),
1374 g_object_class_install_property (gobject_class,
1375 TILDA_WINDOW_ACCEL_PREV_TAB,
1378 pspec = g_param_spec_string ("accelerator-add-terminal",
1379 _("Accelerator to add a terminal"),
1384 g_object_class_install_property (gobject_class,
1385 TILDA_WINDOW_ACCEL_ADD_TERM,
1388 pspec = g_param_spec_string ("accelerator-remove-terminal",
1389 _("Accelerator to remove a terminal"),
1394 g_object_class_install_property (gobject_class,
1395 TILDA_WINDOW_ACCEL_REMOVE_TERM,
1398 pspec = g_param_spec_string ("accelerator-copy",
1399 _("Accelerator to copy to the clipboard"),
1404 g_object_class_install_property (gobject_class,
1405 TILDA_WINDOW_ACCEL_COPY,
1408 pspec = g_param_spec_string ("accelerator-paste",
1409 _("Accelerator to paste from the clipboard"),
1414 g_object_class_install_property (gobject_class,
1415 TILDA_WINDOW_ACCEL_PASTE,
1418 pspec = g_param_spec_string ("accelerator-goto-1",
1419 _("Accelerator to go to tab 1"),
1424 g_object_class_install_property (gobject_class,
1425 TILDA_WINDOW_ACCEL_GOTO_1,
1428 pspec = g_param_spec_string ("accelerator-goto-2",
1429 _("Accelerator to go to tab 2"),
1434 g_object_class_install_property (gobject_class,
1435 TILDA_WINDOW_ACCEL_GOTO_2,
1438 pspec = g_param_spec_string ("accelerator-goto-3",
1439 _("Accelerator to go to tab 3"),
1444 g_object_class_install_property (gobject_class,
1445 TILDA_WINDOW_ACCEL_GOTO_3,
1448 pspec = g_param_spec_string ("accelerator-goto-4",
1449 _("Accelerator to go to tab 4"),
1454 g_object_class_install_property (gobject_class,
1455 TILDA_WINDOW_ACCEL_GOTO_4,
1458 pspec = g_param_spec_string ("accelerator-goto-5",
1459 _("Accelerator to go to tab 5"),
1464 g_object_class_install_property (gobject_class,
1465 TILDA_WINDOW_ACCEL_GOTO_5,
1468 pspec = g_param_spec_string ("accelerator-goto-6",
1469 _("Accelerator to go to tab 6"),
1474 g_object_class_install_property (gobject_class,
1475 TILDA_WINDOW_ACCEL_GOTO_6,
1478 pspec = g_param_spec_string ("accelerator-goto-7",
1479 _("Accelerator to go to tab 7"),
1484 g_object_class_install_property (gobject_class,
1485 TILDA_WINDOW_ACCEL_GOTO_7,
1488 pspec = g_param_spec_string ("accelerator-goto-8",
1489 _("Accelerator to go to tab 8"),
1494 g_object_class_install_property (gobject_class,
1495 TILDA_WINDOW_ACCEL_GOTO_8,
1498 pspec = g_param_spec_string ("accelerator-goto-9",
1499 _("Accelerator to go to tab 9"),
1504 g_object_class_install_property (gobject_class,
1505 TILDA_WINDOW_ACCEL_GOTO_9,
1508 pspec = g_param_spec_string ("accelerator-goto-10",
1509 _("Accelerator to go to tab 10"),
1514 g_object_class_install_property (gobject_class,
1515 TILDA_WINDOW_ACCEL_GOTO_10,
1518 pspec = g_param_spec_string ("key",
1519 _("Window's drop-down keybinding"),
1524 g_object_class_install_property (gobject_class,
1528 pspec = g_param_spec_int ("height",
1529 _("Window's height"),
1536 g_object_class_install_property (gobject_class,
1537 TILDA_WINDOW_HEIGHT,
1540 pspec = g_param_spec_int ("width",
1541 _("Window's width"),
1548 g_object_class_install_property (gobject_class,
1552 pspec = g_param_spec_int ("x-position",
1553 _("Window's x position"),
1560 g_object_class_install_property (gobject_class,
1561 TILDA_WINDOW_X_POSITION,
1564 pspec = g_param_spec_int ("y-position",
1565 _("Window's y position"),
1572 g_object_class_install_property (gobject_class,
1573 TILDA_WINDOW_Y_POSITION,
1576 pspec = g_param_spec_int ("initial-terminals",
1577 _("Window's inital number of terminals"),
1584 g_object_class_install_property (gobject_class,
1585 TILDA_WINDOW_INITIAL_TERMINALS,
1588 pspec = g_param_spec_enum ("tab-position",
1589 _("Position of window's tab bar"),
1591 gtk_position_type_get_type(),
1595 g_object_class_install_property (gobject_class,
1596 TILDA_WINDOW_TAB_POSITION,
1599 pspec = g_param_spec_enum ("animation-orientation",
1600 _("Window's animation orientation"),
1602 gtk_position_type_get_type(),
1606 g_object_class_install_property (gobject_class,
1607 TILDA_WINDOW_ANIMATION_ORIENTATION,
1610 pspec = g_param_spec_int ("animation-delay",
1611 _("Amount of time in milliseconds between animation intervals"),
1618 g_object_class_install_property (gobject_class,
1619 TILDA_WINDOW_ANIMATION_DELAY,
1622 pspec = g_param_spec_boolean ("keep-above",
1623 _("Keep this window above all others"),
1628 g_object_class_install_property (gobject_class,
1629 TILDA_WINDOW_KEEP_ABOVE,
1632 pspec = g_param_spec_boolean ("skip-taskbar-hint",
1633 _("Hide this window in the taskbar if TRUE"),
1638 g_object_class_install_property (gobject_class,
1639 TILDA_WINDOW_SKIP_TASKBAR_HINT,
1642 pspec = g_param_spec_boolean ("stick",
1643 _("Display this window on all workspaces"),
1648 g_object_class_install_property (gobject_class,
1652 pspec = g_param_spec_boolean ("hidden-at-start",
1653 _("Hide the window when it is first created"),
1658 g_object_class_install_property (gobject_class,
1659 TILDA_WINDOW_HIDDEN_AT_START,
1662 pspec = g_param_spec_boolean ("centered-horizontally",
1663 _("Center the window horizontally"),
1668 g_object_class_install_property (gobject_class,
1669 TILDA_WINDOW_CENTERED_HORIZONTALLY,
1672 pspec = g_param_spec_boolean ("centered-vertically",
1673 _("Center the window vertically"),
1678 g_object_class_install_property (gobject_class,
1679 TILDA_WINDOW_CENTERED_VERTICALLY,
1682 pspec = g_param_spec_boolean ("full-width-tabs",
1683 _("Tabs should have full width of window"),
1688 g_object_class_install_property (gobject_class,
1689 TILDA_WINDOW_FULL_WIDTH_TABS,
1692 pspec = g_param_spec_boolean ("have-real-transparency",
1693 NULL, NULL, FALSE, G_PARAM_READABLE);
1695 g_object_class_install_property (gobject_class,
1696 TILDA_WINDOW_HAVE_REAL_TRANSPARENCY,
1699 /* Hook the TildaWindow type into DBus */
1700 dbus_g_object_type_install_info (tilda_window_get_type(), &dbus_glib_tilda_window_object_info);
1704 tilda_window_get_type (void)
1706 static GType type = 0;
1710 static const GTypeInfo info = {
1711 sizeof (TildaWindowClass),
1712 NULL, /* base_init */
1713 NULL, /* base_finalize */
1714 tilda_window_class_init, /* class_init */
1715 NULL, /* class_finalize */
1716 NULL, /* class_data */
1717 sizeof (TildaWindow),
1718 0, /* n_preallocs */
1719 tilda_window_instance_init, /* instance_init */
1722 type = g_type_register_static (G_TYPE_OBJECT,
1731 /* vim: set ts=4 sts=4 sw=4 noet tw=112: */