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 if (self->terms->len > (number - 1))
551 gint temp = self->terms->len - number;
552 gtk_notebook_set_current_page (GTK_NOTEBOOK(self->notebook), temp);
555 /* Do not keep propagating */
560 tilda_window_accel_goto_1_cb (TildaWindow *self, gpointer data)
563 debug_assert (TILDA_IS_WINDOW(self));
565 return tilda_window_accel_goto_generic (self, 1);
569 tilda_window_accel_goto_2_cb (TildaWindow *self, gpointer data)
572 debug_assert (TILDA_IS_WINDOW(self));
574 return tilda_window_accel_goto_generic (self, 2);
578 tilda_window_accel_goto_3_cb (TildaWindow *self, gpointer data)
581 debug_assert (TILDA_IS_WINDOW(self));
583 return tilda_window_accel_goto_generic (self, 3);
587 tilda_window_accel_goto_4_cb (TildaWindow *self, gpointer data)
590 debug_assert (TILDA_IS_WINDOW(self));
592 return tilda_window_accel_goto_generic (self, 4);
596 tilda_window_accel_goto_5_cb (TildaWindow *self, gpointer data)
599 debug_assert (TILDA_IS_WINDOW(self));
601 return tilda_window_accel_goto_generic (self, 5);
605 tilda_window_accel_goto_6_cb (TildaWindow *self, gpointer data)
608 debug_assert (TILDA_IS_WINDOW(self));
610 return tilda_window_accel_goto_generic (self, 6);
614 tilda_window_accel_goto_7_cb (TildaWindow *self, gpointer data)
617 debug_assert (TILDA_IS_WINDOW(self));
619 return tilda_window_accel_goto_generic (self, 7);
623 tilda_window_accel_goto_8_cb (TildaWindow *self, gpointer data)
626 debug_assert (TILDA_IS_WINDOW(self));
628 return tilda_window_accel_goto_generic (self, 8);
632 tilda_window_accel_goto_9_cb (TildaWindow *self, gpointer data)
635 debug_assert (TILDA_IS_WINDOW(self));
637 return tilda_window_accel_goto_generic (self, 9);
641 tilda_window_accel_goto_10_cb (TildaWindow *self, gpointer data)
644 debug_assert (TILDA_IS_WINDOW(self));
646 return tilda_window_accel_goto_generic (self, 10);
649 /*******************************************************************************
650 * ALL GOBJECT STUFF BELOW PLEASE
651 ******************************************************************************/
653 static GObjectClass *parent_class = NULL;
655 enum tilda_window_properties {
656 TILDA_WINDOW_NUMBER = 1,
657 TILDA_WINDOW_CONTROLLER,
659 TILDA_WINDOW_ACCEL_QUIT,
660 TILDA_WINDOW_ACCEL_NEXT_TAB,
661 TILDA_WINDOW_ACCEL_PREV_TAB,
662 TILDA_WINDOW_ACCEL_ADD_TERM,
663 TILDA_WINDOW_ACCEL_REMOVE_TERM,
664 TILDA_WINDOW_ACCEL_COPY,
665 TILDA_WINDOW_ACCEL_PASTE,
666 TILDA_WINDOW_ACCEL_GOTO_1,
667 TILDA_WINDOW_ACCEL_GOTO_2,
668 TILDA_WINDOW_ACCEL_GOTO_3,
669 TILDA_WINDOW_ACCEL_GOTO_4,
670 TILDA_WINDOW_ACCEL_GOTO_5,
671 TILDA_WINDOW_ACCEL_GOTO_6,
672 TILDA_WINDOW_ACCEL_GOTO_7,
673 TILDA_WINDOW_ACCEL_GOTO_8,
674 TILDA_WINDOW_ACCEL_GOTO_9,
675 TILDA_WINDOW_ACCEL_GOTO_10,
681 TILDA_WINDOW_X_POSITION,
682 TILDA_WINDOW_Y_POSITION,
683 TILDA_WINDOW_INITIAL_TERMINALS,
685 TILDA_WINDOW_TAB_POSITION,
686 TILDA_WINDOW_ANIMATION_ORIENTATION,
687 TILDA_WINDOW_ANIMATION_DELAY,
689 TILDA_WINDOW_KEEP_ABOVE,
690 TILDA_WINDOW_SKIP_TASKBAR_HINT,
692 TILDA_WINDOW_HIDDEN_AT_START,
693 TILDA_WINDOW_CENTERED_HORIZONTALLY,
694 TILDA_WINDOW_CENTERED_VERTICALLY,
695 TILDA_WINDOW_FULL_WIDTH_TABS,
697 TILDA_WINDOW_HAVE_REAL_TRANSPARENCY,
701 tilda_window_instance_init (GTypeInstance *instance,
706 TildaWindow *self = (TildaWindow *) instance;
707 self->dispose_has_run = FALSE;
709 /* Initialize all properties */
710 self->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
711 self->notebook = gtk_notebook_new ();
712 self->terms = g_ptr_array_new ();
715 self->accel_group = gtk_accel_group_new ();
716 gtk_window_add_accel_group (GTK_WINDOW(self->window), self->accel_group);
718 /* Somewhat of a "poison" value, incase we don't set this */
719 self->number = 0xdeadbeef;
720 self->controller = NULL;
722 self->state = WINDOW_UP;
726 tilda_window_set_property (GObject *object,
731 TildaWindow *self = (TildaWindow *) object;
734 switch (property_id) {
736 case TILDA_WINDOW_NUMBER:
737 self->number = g_value_get_int (value);
738 debug_printf ("window number: %d\n", self->number);
741 case TILDA_WINDOW_CONTROLLER:
742 self->controller = g_value_get_pointer (value);
743 debug_printf ("window controller: 0x%x\n", self->controller);
746 case TILDA_WINDOW_ACCEL_QUIT:
747 tilda_window_update_accelerator (self,
749 g_value_get_string (value),
750 tilda_window_accel_quit_cb);
751 debug_printf ("window accel quit: %s\n", self->accel_quit);
754 case TILDA_WINDOW_ACCEL_NEXT_TAB:
755 tilda_window_update_accelerator (self,
756 &self->accel_next_tab,
757 g_value_get_string (value),
758 tilda_window_accel_next_tab_cb);
759 debug_printf ("window accel next tab: %s\n", self->accel_next_tab);
762 case TILDA_WINDOW_ACCEL_PREV_TAB:
763 tilda_window_update_accelerator (self,
764 &self->accel_prev_tab,
765 g_value_get_string (value),
766 tilda_window_accel_prev_tab_cb);
767 debug_printf ("window accel prev tab: %s\n", self->accel_prev_tab);
770 case TILDA_WINDOW_ACCEL_ADD_TERM:
771 tilda_window_update_accelerator (self,
772 &self->accel_add_term,
773 g_value_get_string (value),
774 tilda_window_accel_add_term_cb);
775 debug_printf ("window accel add term: %s\n", self->accel_add_term);
778 case TILDA_WINDOW_ACCEL_REMOVE_TERM:
779 tilda_window_update_accelerator (self,
780 &self->accel_remove_term,
781 g_value_get_string (value),
782 tilda_window_accel_remove_term_cb);
783 debug_printf ("window accel remove term: %s\n", self->accel_remove_term);
786 case TILDA_WINDOW_ACCEL_COPY:
787 tilda_window_update_accelerator (self,
789 g_value_get_string (value),
790 tilda_window_accel_copy_cb);
791 debug_printf ("window accel copy: %s\n", self->accel_copy);
794 case TILDA_WINDOW_ACCEL_PASTE:
795 tilda_window_update_accelerator (self,
797 g_value_get_string (value),
798 tilda_window_accel_paste_cb);
799 debug_printf ("window accel paste: %s\n", self->accel_paste);
802 case TILDA_WINDOW_ACCEL_GOTO_1:
803 tilda_window_update_accelerator (self,
805 g_value_get_string (value),
806 tilda_window_accel_goto_1_cb);
807 debug_printf ("window accel goto 1: %s\n", self->accel_goto_1);
810 case TILDA_WINDOW_ACCEL_GOTO_2:
811 tilda_window_update_accelerator (self,
813 g_value_get_string (value),
814 tilda_window_accel_goto_2_cb);
815 debug_printf ("window accel goto 2: %s\n", self->accel_goto_2);
818 case TILDA_WINDOW_ACCEL_GOTO_3:
819 tilda_window_update_accelerator (self,
821 g_value_get_string (value),
822 tilda_window_accel_goto_3_cb);
823 debug_printf ("window accel goto 3: %s\n", self->accel_goto_3);
826 case TILDA_WINDOW_ACCEL_GOTO_4:
827 tilda_window_update_accelerator (self,
829 g_value_get_string (value),
830 tilda_window_accel_goto_4_cb);
831 debug_printf ("window accel goto 4: %s\n", self->accel_goto_4);
834 case TILDA_WINDOW_ACCEL_GOTO_5:
835 tilda_window_update_accelerator (self,
837 g_value_get_string (value),
838 tilda_window_accel_goto_5_cb);
839 debug_printf ("window accel goto 5: %s\n", self->accel_goto_5);
842 case TILDA_WINDOW_ACCEL_GOTO_6:
843 tilda_window_update_accelerator (self,
845 g_value_get_string (value),
846 tilda_window_accel_goto_6_cb);
847 debug_printf ("window accel goto 6: %s\n", self->accel_goto_6);
850 case TILDA_WINDOW_ACCEL_GOTO_7:
851 tilda_window_update_accelerator (self,
853 g_value_get_string (value),
854 tilda_window_accel_goto_7_cb);
855 debug_printf ("window accel goto 7: %s\n", self->accel_goto_7);
858 case TILDA_WINDOW_ACCEL_GOTO_8:
859 tilda_window_update_accelerator (self,
861 g_value_get_string (value),
862 tilda_window_accel_goto_8_cb);
863 debug_printf ("window accel goto 8: %s\n", self->accel_goto_8);
866 case TILDA_WINDOW_ACCEL_GOTO_9:
867 tilda_window_update_accelerator (self,
869 g_value_get_string (value),
870 tilda_window_accel_goto_9_cb);
871 debug_printf ("window accel goto 9: %s\n", self->accel_goto_9);
874 case TILDA_WINDOW_ACCEL_GOTO_10:
875 tilda_window_update_accelerator (self,
876 &self->accel_goto_10,
877 g_value_get_string (value),
878 tilda_window_accel_goto_10_cb);
879 debug_printf ("window accel goto 10: %s\n", self->accel_goto_10);
882 case TILDA_WINDOW_KEY:
883 tilda_window_try_to_bind_key (self, g_value_get_string (value));
884 debug_printf ("window key %s\n", self->key);
887 case TILDA_WINDOW_HEIGHT:
888 self->height = g_value_get_int (value);
889 gtk_widget_set_size_request (self->window, self->width, self->height);
890 gtk_window_resize (GTK_WINDOW(self->window), self->width, self->height);
891 debug_printf ("window height: %d\n", self->height);
894 case TILDA_WINDOW_WIDTH:
895 self->width = g_value_get_int (value);
896 gtk_widget_set_size_request (self->window, self->width, self->height);
897 gtk_window_resize (GTK_WINDOW(self->window), self->width, self->height);
898 debug_printf ("window width: %d\n", self->width);
901 case TILDA_WINDOW_X_POSITION:
902 self->x_position = g_value_get_int (value);
903 gtk_window_move (GTK_WINDOW(self->window), self->x_position, self->y_position);
904 debug_printf ("window x position: %d\n", self->x_position);
907 case TILDA_WINDOW_Y_POSITION:
908 self->y_position = g_value_get_int (value);
909 gtk_window_move (GTK_WINDOW(self->window), self->x_position, self->y_position);
910 debug_printf ("window y position: %d\n", self->y_position);
913 case TILDA_WINDOW_INITIAL_TERMINALS:
914 self->initial_terminals = g_value_get_int (value);
915 debug_printf ("window initial terminals: %d\n", self->initial_terminals);
918 case TILDA_WINDOW_TAB_POSITION:
919 self->tab_position = g_value_get_enum (value);
920 gtk_notebook_set_tab_pos (GTK_NOTEBOOK(self->notebook), self->tab_position);
921 debug_printf ("window tab position: %d\n", self->tab_position);
924 case TILDA_WINDOW_ANIMATION_ORIENTATION:
925 self->animation_orientation = g_value_get_enum (value);
926 debug_printf ("window animation orientation: %d\n", self->animation_orientation);
929 case TILDA_WINDOW_ANIMATION_DELAY:
930 self->animation_delay = g_value_get_int (value);
931 debug_printf ("window animation delay: %d\n", self->animation_delay);
934 case TILDA_WINDOW_KEEP_ABOVE:
935 self->keep_above = g_value_get_boolean (value);
936 gtk_window_set_keep_above (GTK_WINDOW(self->window), self->keep_above);
937 debug_printf ("window keep above: %d\n", self->keep_above);
940 case TILDA_WINDOW_SKIP_TASKBAR_HINT:
941 self->skip_taskbar_hint = g_value_get_boolean (value);
942 gtk_window_set_skip_taskbar_hint (GTK_WINDOW(self->window), self->skip_taskbar_hint);
943 debug_printf ("window skip taskbar hint: %d\n", self->skip_taskbar_hint);
946 case TILDA_WINDOW_STICK:
947 self->stick = g_value_get_boolean (value);
949 /* This is moderately ugly, but GTK+ does it this way... */
950 self->stick ? gtk_window_stick (GTK_WINDOW(self->window))
951 : gtk_window_unstick (GTK_WINDOW(self->window));
952 debug_printf ("window stick: %d\n", self->stick);
955 case TILDA_WINDOW_HIDDEN_AT_START:
956 self->hidden_at_start = g_value_get_boolean (value);
957 debug_printf ("window hidden at start: %d\n", self->hidden_at_start);
960 case TILDA_WINDOW_CENTERED_HORIZONTALLY:
961 self->centered_horizontally = g_value_get_boolean (value);
962 if (self->centered_horizontally)
963 tilda_window_center_horizontally (self);
964 debug_printf ("window centered horizontally: %d\n", self->centered_horizontally);
967 case TILDA_WINDOW_CENTERED_VERTICALLY:
968 self->centered_vertically = g_value_get_boolean (value);
969 if (self->centered_vertically)
970 tilda_window_center_vertically (self);
971 debug_printf ("window centered vertically: %d\n", self->centered_vertically);
974 case TILDA_WINDOW_FULL_WIDTH_TABS:
975 self->full_width_tabs = g_value_get_boolean (value);
976 for (i=0; i<self->terms->len; ++i)
977 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK(self->notebook),
978 TILDA_TERMINAL(g_ptr_array_index(self->terms, i))->hbox,
979 self->full_width_tabs,
982 debug_printf ("window full width tabs: %d\n", self->full_width_tabs);
985 case TILDA_WINDOW_HAVE_REAL_TRANSPARENCY:
986 self->have_real_transparency = g_value_get_boolean (value);
987 debug_printf ("window have real transp: %d\n", self->have_real_transparency);
991 /* We don't have this property */
992 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
998 tilda_window_get_property (GObject *object,
1003 TildaWindow *self = (TildaWindow *) object;
1005 switch (property_id) {
1007 case TILDA_WINDOW_NUMBER:
1008 g_value_set_int (value, self->number);
1011 case TILDA_WINDOW_CONTROLLER:
1012 g_value_set_pointer (value, self->controller);
1015 case TILDA_WINDOW_ACCEL_QUIT:
1016 g_value_set_string (value, self->accel_quit);
1019 case TILDA_WINDOW_ACCEL_NEXT_TAB:
1020 g_value_set_string (value, self->accel_next_tab);
1023 case TILDA_WINDOW_ACCEL_PREV_TAB:
1024 g_value_set_string (value, self->accel_prev_tab);
1027 case TILDA_WINDOW_ACCEL_ADD_TERM:
1028 g_value_set_string (value, self->accel_prev_tab);
1031 case TILDA_WINDOW_ACCEL_REMOVE_TERM:
1032 g_value_set_string (value, self->accel_remove_term);
1035 case TILDA_WINDOW_ACCEL_COPY:
1036 g_value_set_string (value, self->accel_copy);
1039 case TILDA_WINDOW_ACCEL_PASTE:
1040 g_value_set_string (value, self->accel_paste);
1043 case TILDA_WINDOW_ACCEL_GOTO_1:
1044 g_value_set_string (value, self->accel_goto_1);
1047 case TILDA_WINDOW_ACCEL_GOTO_2:
1048 g_value_set_string (value, self->accel_goto_2);
1051 case TILDA_WINDOW_ACCEL_GOTO_3:
1052 g_value_set_string (value, self->accel_goto_3);
1055 case TILDA_WINDOW_ACCEL_GOTO_4:
1056 g_value_set_string (value, self->accel_goto_4);
1059 case TILDA_WINDOW_ACCEL_GOTO_5:
1060 g_value_set_string (value, self->accel_goto_5);
1063 case TILDA_WINDOW_ACCEL_GOTO_6:
1064 g_value_set_string (value, self->accel_goto_6);
1067 case TILDA_WINDOW_ACCEL_GOTO_7:
1068 g_value_set_string (value, self->accel_goto_7);
1071 case TILDA_WINDOW_ACCEL_GOTO_8:
1072 g_value_set_string (value, self->accel_goto_8);
1075 case TILDA_WINDOW_ACCEL_GOTO_9:
1076 g_value_set_string (value, self->accel_goto_9);
1079 case TILDA_WINDOW_ACCEL_GOTO_10:
1080 g_value_set_string (value, self->accel_goto_10);
1083 case TILDA_WINDOW_KEY:
1084 g_value_set_string (value, self->key);
1087 case TILDA_WINDOW_HEIGHT:
1088 g_value_set_int (value, self->height);
1091 case TILDA_WINDOW_WIDTH:
1092 g_value_set_int (value, self->width);
1095 case TILDA_WINDOW_X_POSITION:
1096 g_value_set_int (value, self->x_position);
1099 case TILDA_WINDOW_Y_POSITION:
1100 g_value_set_int (value, self->y_position);
1103 case TILDA_WINDOW_INITIAL_TERMINALS:
1104 g_value_set_int (value, self->initial_terminals);
1107 case TILDA_WINDOW_TAB_POSITION:
1108 g_value_set_enum (value, self->tab_position);
1111 case TILDA_WINDOW_ANIMATION_ORIENTATION:
1112 g_value_set_enum (value, self->animation_orientation);
1115 case TILDA_WINDOW_ANIMATION_DELAY:
1116 g_value_set_int (value, self->animation_delay);
1119 case TILDA_WINDOW_KEEP_ABOVE:
1120 g_value_set_boolean (value, self->keep_above);
1123 case TILDA_WINDOW_SKIP_TASKBAR_HINT:
1124 g_value_set_boolean (value, self->skip_taskbar_hint);
1127 case TILDA_WINDOW_STICK:
1128 g_value_set_boolean (value, self->stick);
1131 case TILDA_WINDOW_HIDDEN_AT_START:
1132 g_value_set_boolean (value, self->hidden_at_start);
1135 case TILDA_WINDOW_CENTERED_HORIZONTALLY:
1136 g_value_set_boolean (value, self->centered_horizontally);
1139 case TILDA_WINDOW_CENTERED_VERTICALLY:
1140 g_value_set_boolean (value, self->centered_vertically);
1143 case TILDA_WINDOW_FULL_WIDTH_TABS:
1144 g_value_set_boolean (value, self->full_width_tabs);
1147 case TILDA_WINDOW_HAVE_REAL_TRANSPARENCY:
1148 g_value_set_boolean (value, self->have_real_transparency);
1152 /* We don't have this property */
1153 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1159 tilda_window_constructor (GType type,
1160 guint n_construct_properties,
1161 GObjectConstructParam *construct_properties)
1169 /* Invoke parent constructor */
1170 TildaWindowClass *klass;
1171 klass = TILDA_WINDOW_CLASS (g_type_class_peek (TILDA_TYPE_WINDOW));
1172 obj = parent_class->constructor (type,
1173 n_construct_properties,
1174 construct_properties);
1176 /* Do other stuff here. The object is ready to go now, and all
1177 * ctor properties have been set.
1179 self = TILDA_WINDOW(obj);
1181 /* Try to set up real transparency */
1182 tilda_window_setup_real_transparency (self);
1184 gtk_container_add (GTK_CONTAINER(self->window), self->notebook);
1185 g_object_set (G_OBJECT(self->notebook), "can-focus", FALSE, NULL);
1186 gtk_widget_show (self->notebook);
1188 /* Tilda is never decorated */
1189 gtk_window_set_decorated (GTK_WINDOW(self->window), FALSE);
1191 /* Set all of the properties out of the config file */
1192 tilda_window_set_property_from_config (self, "key");
1194 // FIXME: hack -- start the wizard in this case :)
1197 gchar *key = g_strdup_printf ("F%d", self->number+3);
1198 g_object_set (G_OBJECT(self), "key", key, NULL);
1201 g_critical ("HACK: start the wizard here\n");
1204 tilda_window_set_property_from_config (self, "accelerator-quit");
1205 tilda_window_set_property_from_config (self, "accelerator-next-tab");
1206 tilda_window_set_property_from_config (self, "accelerator-previous-tab");
1207 tilda_window_set_property_from_config (self, "accelerator-add-terminal");
1208 tilda_window_set_property_from_config (self, "accelerator-remove-terminal");
1209 tilda_window_set_property_from_config (self, "accelerator-copy");
1210 tilda_window_set_property_from_config (self, "accelerator-paste");
1211 tilda_window_set_property_from_config (self, "accelerator-goto-1");
1212 tilda_window_set_property_from_config (self, "accelerator-goto-2");
1213 tilda_window_set_property_from_config (self, "accelerator-goto-3");
1214 tilda_window_set_property_from_config (self, "accelerator-goto-4");
1215 tilda_window_set_property_from_config (self, "accelerator-goto-5");
1216 tilda_window_set_property_from_config (self, "accelerator-goto-6");
1217 tilda_window_set_property_from_config (self, "accelerator-goto-7");
1218 tilda_window_set_property_from_config (self, "accelerator-goto-8");
1219 tilda_window_set_property_from_config (self, "accelerator-goto-9");
1220 tilda_window_set_property_from_config (self, "accelerator-goto-10");
1222 tilda_window_set_property_from_config (self, "height");
1223 tilda_window_set_property_from_config (self, "width");
1224 tilda_window_set_property_from_config (self, "x-position");
1225 tilda_window_set_property_from_config (self, "y-position");
1226 tilda_window_set_property_from_config (self, "initial-terminals");
1227 tilda_window_set_property_from_config (self, "animation-delay");
1229 tilda_window_set_property_from_config (self, "tab-position");
1230 tilda_window_set_property_from_config (self, "animation-orientation");
1232 tilda_window_set_property_from_config (self, "keep-above");
1233 tilda_window_set_property_from_config (self, "skip-taskbar-hint");
1234 tilda_window_set_property_from_config (self, "stick");
1235 tilda_window_set_property_from_config (self, "hidden-at-start");
1236 tilda_window_set_property_from_config (self, "centered-horizontally");
1237 tilda_window_set_property_from_config (self, "centered-vertically");
1238 tilda_window_set_property_from_config (self, "full-width-tabs");
1240 /* Add the initial terminal(s) */
1241 for (i=0; i<self->initial_terminals; ++i)
1242 tilda_window_add_terminal (self);
1244 /* Show us if we're ready. If not, just remain hidden. All sub-widgets must
1245 * be gtk_widget_show()n by this point. */
1246 if (!self->hidden_at_start)
1248 gtk_widget_show (self->window);
1249 self->state = WINDOW_DOWN;
1252 self->state = WINDOW_UP;
1254 /* Register this object with DBus */
1255 tilda_window_dbus_register_object (self);
1261 tilda_window_dispose (GObject *obj)
1265 TildaWindow *self = (TildaWindow *) obj;
1267 /* We don't want to run dispose twice, so just return immediately */
1268 if (self->dispose_has_run)
1272 * In dispose, you are supposed to free all types referenced from this
1273 * object which might themselves hold a reference to self. Generally,
1274 * the most simple solution is to unref all members on which you own a
1277 * NOTE: See the following for how to deal with GtkObject-derived things:
1278 * http://library.gnome.org/devel/gtk/unstable/GtkObject.html
1280 g_object_unref (G_OBJECT(self->accel_group));
1281 g_ptr_array_foreach (self->terms, g_object_unref, NULL);
1282 gtk_widget_destroy (self->window);
1284 /* Unbind if we were set */
1286 tomboy_keybinder_unbind (self->key, tilda_window_keybinding_cb);
1288 /* Chain up to the parent class */
1289 G_OBJECT_CLASS (parent_class)->dispose (obj);
1293 tilda_window_finalize (GObject *obj)
1297 TildaWindow *self = (TildaWindow *) obj;
1300 * Here, complete the object's destruction.
1301 * You might not need to do much...
1303 // TODO: g_free() any primitives here
1304 g_ptr_array_free (self->terms, TRUE);
1307 /* Chain up to the parent class */
1308 G_OBJECT_CLASS (parent_class)->finalize (obj);
1312 tilda_window_class_init (gpointer g_class,
1313 gpointer g_class_data)
1317 GObjectClass *gobject_class = G_OBJECT_CLASS (g_class);
1318 TildaWindowClass *klass = TILDA_WINDOW_CLASS (g_class);
1321 /* Hook our functions to this type */
1322 gobject_class->set_property = tilda_window_set_property;
1323 gobject_class->get_property = tilda_window_get_property;
1324 gobject_class->dispose = tilda_window_dispose;
1325 gobject_class->finalize = tilda_window_finalize;
1326 gobject_class->constructor = tilda_window_constructor;
1328 parent_class = g_type_class_peek_parent (klass);
1330 /* Install all of the properties */
1331 pspec = g_param_spec_int ("number",
1335 INT_MAX, // max value
1337 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
1339 g_object_class_install_property (gobject_class,
1340 TILDA_WINDOW_NUMBER,
1343 pspec = g_param_spec_pointer ("controller",
1344 _("Pointer to window's controlling TildaController"),
1346 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
1348 g_object_class_install_property (gobject_class,
1349 TILDA_WINDOW_CONTROLLER,
1352 pspec = g_param_spec_string ("accelerator-quit",
1353 _("Accelerator to quit this window"),
1358 g_object_class_install_property (gobject_class,
1359 TILDA_WINDOW_ACCEL_QUIT,
1362 pspec = g_param_spec_string ("accelerator-next-tab",
1363 _("Accelerator to go to the next tab"),
1368 g_object_class_install_property (gobject_class,
1369 TILDA_WINDOW_ACCEL_NEXT_TAB,
1372 pspec = g_param_spec_string ("accelerator-previous-tab",
1373 _("Accelerator to go to the previous tab"),
1378 g_object_class_install_property (gobject_class,
1379 TILDA_WINDOW_ACCEL_PREV_TAB,
1382 pspec = g_param_spec_string ("accelerator-add-terminal",
1383 _("Accelerator to add a terminal"),
1388 g_object_class_install_property (gobject_class,
1389 TILDA_WINDOW_ACCEL_ADD_TERM,
1392 pspec = g_param_spec_string ("accelerator-remove-terminal",
1393 _("Accelerator to remove a terminal"),
1398 g_object_class_install_property (gobject_class,
1399 TILDA_WINDOW_ACCEL_REMOVE_TERM,
1402 pspec = g_param_spec_string ("accelerator-copy",
1403 _("Accelerator to copy to the clipboard"),
1408 g_object_class_install_property (gobject_class,
1409 TILDA_WINDOW_ACCEL_COPY,
1412 pspec = g_param_spec_string ("accelerator-paste",
1413 _("Accelerator to paste from the clipboard"),
1418 g_object_class_install_property (gobject_class,
1419 TILDA_WINDOW_ACCEL_PASTE,
1422 pspec = g_param_spec_string ("accelerator-goto-1",
1423 _("Accelerator to go to tab 1"),
1428 g_object_class_install_property (gobject_class,
1429 TILDA_WINDOW_ACCEL_GOTO_1,
1432 pspec = g_param_spec_string ("accelerator-goto-2",
1433 _("Accelerator to go to tab 2"),
1438 g_object_class_install_property (gobject_class,
1439 TILDA_WINDOW_ACCEL_GOTO_2,
1442 pspec = g_param_spec_string ("accelerator-goto-3",
1443 _("Accelerator to go to tab 3"),
1448 g_object_class_install_property (gobject_class,
1449 TILDA_WINDOW_ACCEL_GOTO_3,
1452 pspec = g_param_spec_string ("accelerator-goto-4",
1453 _("Accelerator to go to tab 4"),
1458 g_object_class_install_property (gobject_class,
1459 TILDA_WINDOW_ACCEL_GOTO_4,
1462 pspec = g_param_spec_string ("accelerator-goto-5",
1463 _("Accelerator to go to tab 5"),
1468 g_object_class_install_property (gobject_class,
1469 TILDA_WINDOW_ACCEL_GOTO_5,
1472 pspec = g_param_spec_string ("accelerator-goto-6",
1473 _("Accelerator to go to tab 6"),
1478 g_object_class_install_property (gobject_class,
1479 TILDA_WINDOW_ACCEL_GOTO_6,
1482 pspec = g_param_spec_string ("accelerator-goto-7",
1483 _("Accelerator to go to tab 7"),
1488 g_object_class_install_property (gobject_class,
1489 TILDA_WINDOW_ACCEL_GOTO_7,
1492 pspec = g_param_spec_string ("accelerator-goto-8",
1493 _("Accelerator to go to tab 8"),
1498 g_object_class_install_property (gobject_class,
1499 TILDA_WINDOW_ACCEL_GOTO_8,
1502 pspec = g_param_spec_string ("accelerator-goto-9",
1503 _("Accelerator to go to tab 9"),
1508 g_object_class_install_property (gobject_class,
1509 TILDA_WINDOW_ACCEL_GOTO_9,
1512 pspec = g_param_spec_string ("accelerator-goto-10",
1513 _("Accelerator to go to tab 10"),
1518 g_object_class_install_property (gobject_class,
1519 TILDA_WINDOW_ACCEL_GOTO_10,
1522 pspec = g_param_spec_string ("key",
1523 _("Window's drop-down keybinding"),
1528 g_object_class_install_property (gobject_class,
1532 pspec = g_param_spec_int ("height",
1533 _("Window's height"),
1540 g_object_class_install_property (gobject_class,
1541 TILDA_WINDOW_HEIGHT,
1544 pspec = g_param_spec_int ("width",
1545 _("Window's width"),
1552 g_object_class_install_property (gobject_class,
1556 pspec = g_param_spec_int ("x-position",
1557 _("Window's x position"),
1564 g_object_class_install_property (gobject_class,
1565 TILDA_WINDOW_X_POSITION,
1568 pspec = g_param_spec_int ("y-position",
1569 _("Window's y position"),
1576 g_object_class_install_property (gobject_class,
1577 TILDA_WINDOW_Y_POSITION,
1580 pspec = g_param_spec_int ("initial-terminals",
1581 _("Window's inital number of terminals"),
1588 g_object_class_install_property (gobject_class,
1589 TILDA_WINDOW_INITIAL_TERMINALS,
1592 pspec = g_param_spec_enum ("tab-position",
1593 _("Position of window's tab bar"),
1595 gtk_position_type_get_type(),
1599 g_object_class_install_property (gobject_class,
1600 TILDA_WINDOW_TAB_POSITION,
1603 pspec = g_param_spec_enum ("animation-orientation",
1604 _("Window's animation orientation"),
1606 gtk_position_type_get_type(),
1610 g_object_class_install_property (gobject_class,
1611 TILDA_WINDOW_ANIMATION_ORIENTATION,
1614 pspec = g_param_spec_int ("animation-delay",
1615 _("Amount of time in milliseconds between animation intervals"),
1622 g_object_class_install_property (gobject_class,
1623 TILDA_WINDOW_ANIMATION_DELAY,
1626 pspec = g_param_spec_boolean ("keep-above",
1627 _("Keep this window above all others"),
1632 g_object_class_install_property (gobject_class,
1633 TILDA_WINDOW_KEEP_ABOVE,
1636 pspec = g_param_spec_boolean ("skip-taskbar-hint",
1637 _("Hide this window in the taskbar if TRUE"),
1642 g_object_class_install_property (gobject_class,
1643 TILDA_WINDOW_SKIP_TASKBAR_HINT,
1646 pspec = g_param_spec_boolean ("stick",
1647 _("Display this window on all workspaces"),
1652 g_object_class_install_property (gobject_class,
1656 pspec = g_param_spec_boolean ("hidden-at-start",
1657 _("Hide the window when it is first created"),
1662 g_object_class_install_property (gobject_class,
1663 TILDA_WINDOW_HIDDEN_AT_START,
1666 pspec = g_param_spec_boolean ("centered-horizontally",
1667 _("Center the window horizontally"),
1672 g_object_class_install_property (gobject_class,
1673 TILDA_WINDOW_CENTERED_HORIZONTALLY,
1676 pspec = g_param_spec_boolean ("centered-vertically",
1677 _("Center the window vertically"),
1682 g_object_class_install_property (gobject_class,
1683 TILDA_WINDOW_CENTERED_VERTICALLY,
1686 pspec = g_param_spec_boolean ("full-width-tabs",
1687 _("Tabs should have full width of window"),
1692 g_object_class_install_property (gobject_class,
1693 TILDA_WINDOW_FULL_WIDTH_TABS,
1696 pspec = g_param_spec_boolean ("have-real-transparency",
1697 NULL, NULL, FALSE, G_PARAM_READABLE);
1699 g_object_class_install_property (gobject_class,
1700 TILDA_WINDOW_HAVE_REAL_TRANSPARENCY,
1703 /* Hook the TildaWindow type into DBus */
1704 dbus_g_object_type_install_info (tilda_window_get_type(), &dbus_glib_tilda_window_object_info);
1708 tilda_window_get_type (void)
1710 static GType type = 0;
1714 static const GTypeInfo info = {
1715 sizeof (TildaWindowClass),
1716 NULL, /* base_init */
1717 NULL, /* base_finalize */
1718 tilda_window_class_init, /* class_init */
1719 NULL, /* class_finalize */
1720 NULL, /* class_data */
1721 sizeof (TildaWindow),
1722 0, /* n_preallocs */
1723 tilda_window_instance_init, /* instance_init */
1726 type = g_type_register_static (G_TYPE_OBJECT,
1735 /* vim: set ts=4 sts=4 sw=4 noet tw=112: */