1 /*-
2 * Copyright (c) 2004-2008 os-cillation e.K.
3 *
4 * Written by Benedikt Meurer <benny@xfce.org>.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 #ifdef HAVE_SYS_TYPES_H
25 #include <sys/types.h>
26 #endif
27
28 #ifdef HAVE_TIME_H
29 #include <time.h>
30 #endif
31 #ifdef HAVE_UNISTD_H
32 #include <unistd.h>
33 #endif
34
35 #include <libxfce4ui/libxfce4ui.h>
36
37 #if defined(GDK_WINDOWING_X11)
38 #include <gdk/gdkx.h>
39 #endif
40
41 #include <terminal/terminal-util.h>
42 #include <terminal/terminal-enum-types.h>
43 #include <terminal/terminal-options.h>
44 #include <terminal/terminal-preferences-dialog.h>
45 #include <terminal/terminal-search-dialog.h>
46 #include <terminal/terminal-private.h>
47 #include <terminal/terminal-marshal.h>
48 #include <terminal/terminal-encoding-action.h>
49 #include <terminal/terminal-window.h>
50 #include <terminal/terminal-window-dropdown.h>
51 #include <terminal/terminal-window-ui.h>
52 #include <terminal/terminal-widget.h>
53
54
55
56 /* Signal identifiers */
57 enum
58 {
59 NEW_WINDOW,
60 NEW_WINDOW_WITH_SCREEN,
61 LAST_SIGNAL
62 };
63
64 /* Used by confirm_close() */
65 enum
66 {
67 CONFIRMED_NONE,
68 CONFIRMED_CLOSE_TAB,
69 CONFIRMED_CLOSE_WINDOW
70 };
71
72 /* CSS for slim notebook tabs style */
73 #define NOTEBOOK_NAME PACKAGE_NAME "-notebook"
74 const gchar *CSS_SLIM_TABS =
75 "#" NOTEBOOK_NAME " tab {\n"
76 " min-height: 0;\n"
77 " font-weight: normal;\n"
78 " padding: 1px;\n"
79 " margin: 0;\n"
80 "}\n"
81 "#" NOTEBOOK_NAME " tab button {\n"
82 " min-height: 0;\n"
83 " min-width: 0;\n"
84 " padding: 1px;\n"
85 " margin: 0;\n"
86 "}\n"
87 "#" NOTEBOOK_NAME " button {\n"
88 " min-height: 0;\n"
89 " min-width: 0;\n"
90 " padding: 1px;\n"
91 "}\n";
92
93 /* See gnome-terminal bug #789356 */
94 #if GTK_CHECK_VERSION (3, 22, 23)
95 #define WINDOW_STATE_TILED (GDK_WINDOW_STATE_TILED | \
96 GDK_WINDOW_STATE_LEFT_TILED | \
97 GDK_WINDOW_STATE_RIGHT_TILED | \
98 GDK_WINDOW_STATE_TOP_TILED | \
99 GDK_WINDOW_STATE_BOTTOM_TILED)
100 #else
101 #define WINDOW_STATE_TILED (GDK_WINDOW_STATE_TILED)
102 #endif
103
104
105
106 static void terminal_window_finalize (GObject *object);
107 static gboolean terminal_window_delete_event (GtkWidget *widget,
108 GdkEventAny *event);
109 static gboolean terminal_window_state_event (GtkWidget *widget,
110 GdkEventWindowState *event);
111 static void terminal_window_style_set (GtkWidget *widget,
112 GtkStyle *previous_style);
113 static gboolean terminal_window_scroll_event (GtkWidget *widget,
114 GdkEventScroll *event);
115 static gboolean terminal_window_map_event (GtkWidget *widget,
116 GdkEventAny *event);
117 static gboolean terminal_window_focus_in_event (GtkWidget *widget,
118 GdkEventFocus *event);
119 static gboolean terminal_window_key_press_event (GtkWidget *widget,
120 GdkEventKey *event);
121 static gint terminal_window_confirm_close (TerminalScreen *screen,
122 TerminalWindow *window);
123 static void terminal_window_size_push (TerminalWindow *window);
124 static gboolean terminal_window_size_pop (gpointer data);
125 static void terminal_window_set_size_force_grid (TerminalWindow *window,
126 TerminalScreen *screen,
127 glong force_grid_width,
128 glong force_grid_height);
129 static void terminal_window_update_actions (TerminalWindow *window);
130 static void terminal_window_update_slim_tabs (TerminalWindow *window);
131 static void terminal_window_update_scroll_on_output (TerminalWindow *window);
132 static void terminal_window_update_mnemonic_modifier (TerminalWindow *window);
133 static void terminal_window_notebook_page_switched (GtkNotebook *notebook,
134 GtkWidget *page,
135 guint page_num,
136 TerminalWindow *window);
137 static void terminal_window_notebook_page_reordered (GtkNotebook *notebook,
138 GtkWidget *child,
139 guint page_num,
140 TerminalWindow *window);
141 static void terminal_window_notebook_page_added (GtkNotebook *notebook,
142 GtkWidget *child,
143 guint page_num,
144 TerminalWindow *window);
145 static void terminal_window_notebook_page_removed (GtkNotebook *notebook,
146 GtkWidget *child,
147 guint page_num,
148 TerminalWindow *window);
149 static gboolean terminal_window_notebook_event_in_allocation (gint event_x,
150 gint event_y,
151 GtkWidget *widget);
152 static gboolean terminal_window_notebook_button_press_event (GtkNotebook *notebook,
153 GdkEventButton *event,
154 TerminalWindow *window);
155 static gboolean terminal_window_notebook_button_release_event (GtkNotebook *notebook,
156 GdkEventButton *event,
157 TerminalWindow *window);
158 static gboolean terminal_window_notebook_scroll_event (GtkNotebook *notebook,
159 GdkEventScroll *event,
160 TerminalWindow *window);
161 static void terminal_window_notebook_drag_data_received (GtkWidget *widget,
162 GdkDragContext *context,
163 gint x,
164 gint y,
165 GtkSelectionData *selection_data,
166 guint info,
167 guint time,
168 TerminalWindow *window);
169 static GtkNotebook *terminal_window_notebook_create_window (GtkNotebook *notebook,
170 GtkWidget *child,
171 gint x,
172 gint y,
173 TerminalWindow *window);
174 static GtkWidget *terminal_window_get_context_menu (TerminalScreen *screen,
175 TerminalWindow *window);
176 static void terminal_window_notify_title (TerminalScreen *screen,
177 GParamSpec *pspec,
178 TerminalWindow *window);
179 static void terminal_window_action_set_encoding (GtkAction *action,
180 const gchar *charset,
181 TerminalWindow *window);
182 static void terminal_window_action_new_tab (GtkAction *action,
183 TerminalWindow *window);
184 static void terminal_window_action_new_window (GtkAction *action,
185 TerminalWindow *window);
186 static void terminal_window_action_undo_close_tab (GtkAction *action,
187 TerminalWindow *window);
188 static void terminal_window_action_detach_tab (GtkAction *action,
189 TerminalWindow *window);
190 static void terminal_window_action_close_tab (GtkAction *action,
191 TerminalWindow *window);
192 static void terminal_window_action_close_other_tabs (GtkAction *action,
193 TerminalWindow *window);
194 static void terminal_window_action_close_window (GtkAction *action,
195 TerminalWindow *window);
196 static void terminal_window_action_copy (GtkAction *action,
197 TerminalWindow *window);
198 #if VTE_CHECK_VERSION (0, 49, 2)
199 static void terminal_window_action_copy_html (GtkAction *action,
200 TerminalWindow *window);
201 #endif
202 static void terminal_window_action_paste (GtkAction *action,
203 TerminalWindow *window);
204 static void terminal_window_action_paste_selection (GtkAction *action,
205 TerminalWindow *window);
206 static void terminal_window_action_select_all (GtkAction *action,
207 TerminalWindow *window);
208 static void terminal_window_action_copy_input (GtkAction *action,
209 TerminalWindow *window);
210 static void terminal_window_action_prefs (GtkAction *action,
211 TerminalWindow *window);
212 static void terminal_window_action_show_toolbar (GtkToggleAction *action,
213 TerminalWindow *window);
214 static void terminal_window_action_show_borders (GtkToggleAction *action,
215 TerminalWindow *window);
216 static void terminal_window_action_fullscreen (GtkToggleAction *action,
217 TerminalWindow *window);
218 static void terminal_window_action_readonly (GtkToggleAction *action,
219 TerminalWindow *window);
220 static void terminal_window_action_scroll_on_output (GtkToggleAction *action,
221 TerminalWindow *window);
222 static void terminal_window_action_zoom_in (GtkAction *action,
223 TerminalWindow *window);
224 static void terminal_window_action_zoom_out (GtkAction *action,
225 TerminalWindow *window);
226 static void terminal_window_action_zoom_reset (GtkAction *action,
227 TerminalWindow *window);
228 static void terminal_window_action_prev_tab (GtkAction *action,
229 TerminalWindow *window);
230 static void terminal_window_action_next_tab (GtkAction *action,
231 TerminalWindow *window);
232 static void terminal_window_action_last_active_tab (GtkAction *action,
233 TerminalWindow *window);
234 static void terminal_window_action_move_tab_left (GtkAction *action,
235 TerminalWindow *window);
236 static void terminal_window_action_move_tab_right (GtkAction *action,
237 TerminalWindow *window);
238 static void terminal_window_action_goto_tab (GtkRadioAction *action,
239 GtkNotebook *notebook);
240 static void terminal_window_action_set_title (GtkAction *action,
241 TerminalWindow *window);
242 static void terminal_window_action_set_title_color (GtkAction *action,
243 TerminalWindow *window);
244 static void terminal_window_action_search (GtkAction *action,
245 TerminalWindow *window);
246 static void terminal_window_action_search_next (GtkAction *action,
247 TerminalWindow *window);
248 static void terminal_window_action_search_prev (GtkAction *action,
249 TerminalWindow *window);
250 static void terminal_window_action_save_contents (GtkAction *action,
251 TerminalWindow *window);
252 static void terminal_window_action_reset (GtkAction *action,
253 TerminalWindow *window);
254 static void terminal_window_action_reset_and_clear (GtkAction *action,
255 TerminalWindow *window);
256 static void terminal_window_action_contents (GtkAction *action,
257 TerminalWindow *window);
258 static void terminal_window_action_about (GtkAction *action,
259 TerminalWindow *window);
260 static void terminal_window_zoom_update_screens (TerminalWindow *window);
261 static void terminal_window_switch_tab (GtkNotebook *notebook,
262 gboolean switch_left);
263 static void terminal_window_move_tab (GtkNotebook *notebook,
264 gboolean move_left);
265 static void terminal_window_toggle_menubar (GtkWidget *widget,
266 TerminalWindow *window);
267 static void terminal_window_menubar_deactivate (GtkWidget *widget,
268 TerminalWindow *window);
269 static void title_popover_close (GtkWidget *popover,
270 TerminalWindow *window);
271 static void terminal_window_do_close_tab (TerminalScreen *screen,
272 TerminalWindow *window);
273
274
275
276 struct _TerminalWindowPrivate
277 {
278 GtkUIManager *ui_manager;
279
280 GtkWidget *vbox;
281 GtkWidget *notebook;
282 GtkWidget *menubar;
283 GtkWidget *toolbar;
284
285 /* for the drop-down to keep open with dialogs */
286 guint n_child_windows;
287
288 guint tabs_menu_merge_id;
289 GSList *tabs_menu_actions;
290
291 TerminalPreferences *preferences;
292 GtkWidget *preferences_dialog;
293
294 GtkActionGroup *action_group;
295
296 GtkWidget *search_dialog;
297 GtkWidget *title_popover;
298
299 /* pushed size of screen */
300 glong grid_width;
301 glong grid_height;
302
303 GtkAction *encoding_action;
304
305 TerminalScreen *active;
306 TerminalScreen *last_active;
307
308 /* cached actions to avoid lookups */
309 GtkAction *action_undo_close_tab;
310 GtkAction *action_detach_tab;
311 GtkAction *action_close_other_tabs;
312 GtkAction *action_prev_tab;
313 GtkAction *action_next_tab;
314 GtkAction *action_last_active_tab;
315 GtkAction *action_move_tab_left;
316 GtkAction *action_move_tab_right;
317 GtkAction *action_copy;
318 GtkAction *action_search_next;
319 GtkAction *action_search_prev;
320 GtkAction *action_fullscreen;
321
322 GQueue *closed_tabs_list;
323
324 gchar *font;
325
326 TerminalVisibility scrollbar_visibility;
327 TerminalZoomLevel zoom;
328
329 GSList *tab_key_accels;
330
331 /* if this is a TerminalWindowDropdown */
332 guint drop_down : 1;
333 };
334
335 static guint window_signals[LAST_SIGNAL];
336 static gchar *window_notebook_group = PACKAGE_NAME;
337 static GQuark tabs_menu_action_quark = 0;
338
339
340
341 static const GtkActionEntry action_entries[] =
342 {
343 { "file-menu", NULL, N_ ("_File"), NULL, NULL, NULL, },
344 { "new-tab", "tab-new", N_ ("Open _Tab"), "<control><shift>t", N_ ("Open a new terminal tab"), G_CALLBACK (terminal_window_action_new_tab), },
345 { "new-window", "window-new", N_ ("Open T_erminal"), "<control><shift>n", N_ ("Open a new terminal window"), G_CALLBACK (terminal_window_action_new_window), },
346 { "undo-close-tab", "document-revert", N_ ("_Undo Close Tab"), NULL, NULL, G_CALLBACK (terminal_window_action_undo_close_tab), },
347 { "detach-tab", NULL, N_ ("_Detach Tab"), "<control><shift>d", NULL, G_CALLBACK (terminal_window_action_detach_tab), },
348 { "close-tab", "window-close", N_ ("Close T_ab"), "<control><shift>w", NULL, G_CALLBACK (terminal_window_action_close_tab), },
349 { "close-other-tabs", "edit-clear", N_ ("Close Other Ta_bs"), NULL, NULL, G_CALLBACK (terminal_window_action_close_other_tabs), },
350 { "close-window", "application-exit", N_ ("Close _Window"), "<control><shift>q", NULL, G_CALLBACK (terminal_window_action_close_window), },
351 { "edit-menu", NULL, N_ ("_Edit"), NULL, NULL, NULL, },
352 { "copy", "edit-copy", N_ ("_Copy"), "<control><shift>c", N_ ("Copy to clipboard"), G_CALLBACK (terminal_window_action_copy), },
353 #if VTE_CHECK_VERSION (0, 49, 2)
354 { "copy-html", "edit-copy", N_ ("Copy as _HTML"), NULL, N_ ("Copy to clipboard as HTML"), G_CALLBACK (terminal_window_action_copy_html), },
355 #endif
356 { "paste", "edit-paste", N_ ("_Paste"), "<control><shift>v", N_ ("Paste from clipboard"), G_CALLBACK (terminal_window_action_paste), },
357 { "paste-selection", NULL, N_ ("Paste _Selection"), NULL, NULL, G_CALLBACK (terminal_window_action_paste_selection), },
358 { "select-all", "edit-select-all", N_ ("Select _All"), "<control><shift>a", NULL, G_CALLBACK (terminal_window_action_select_all), },
359 { "copy-input", NULL, N_ ("Copy _Input To All Tabs..."), NULL, NULL, G_CALLBACK (terminal_window_action_copy_input), },
360 { "preferences", "preferences-system", N_ ("Pr_eferences..."), NULL, N_ ("Open the preferences dialog"), G_CALLBACK (terminal_window_action_prefs), },
361 { "view-menu", NULL, N_ ("_View"), NULL, NULL, NULL, },
362 { "zoom-in", "zoom-in", N_ ("Zoom _In"), "<control>plus", N_ ("Zoom in with larger font"), G_CALLBACK (terminal_window_action_zoom_in), },
363 { "zoom-out", "zoom-out", N_ ("Zoom _Out"), "<control>minus", N_ ("Zoom out with smaller font"), G_CALLBACK (terminal_window_action_zoom_out), },
364 { "zoom-reset", "zoom-original", N_ ("_Normal Size"), "<control>0", N_ ("Zoom to default size"), G_CALLBACK (terminal_window_action_zoom_reset), },
365 { "terminal-menu", NULL, N_ ("_Terminal"), NULL, NULL, NULL, },
366 { "set-title", NULL, N_ ("_Set Title..."), "<control><shift>s", NULL, G_CALLBACK (terminal_window_action_set_title), },
367 { "set-title-color", NULL, N_ ("Set Title Co_lor..."), NULL, NULL, G_CALLBACK (terminal_window_action_set_title_color), },
368 { "search", "edit-find", N_ ("_Find..."), "<control><shift>f", N_ ("Search terminal contents"), G_CALLBACK (terminal_window_action_search), },
369 { "search-next", NULL, N_ ("Find Ne_xt"), NULL, NULL, G_CALLBACK (terminal_window_action_search_next), },
370 { "search-prev", NULL, N_ ("Find Pre_vious"), NULL, NULL, G_CALLBACK (terminal_window_action_search_prev), },
371 { "save-contents", "document-save-as", N_ ("Sa_ve Contents..."), NULL, NULL, G_CALLBACK (terminal_window_action_save_contents), },
372 { "reset", NULL, N_ ("_Reset"), NULL, NULL, G_CALLBACK (terminal_window_action_reset), },
373 { "reset-and-clear", NULL, N_ ("_Clear Scrollback and Reset"), NULL, NULL, G_CALLBACK (terminal_window_action_reset_and_clear), },
374 { "tabs-menu", NULL, N_ ("T_abs"), NULL, NULL, NULL, },
375 { "prev-tab", "go-previous", N_ ("_Previous Tab"), "<control>Page_Up", N_ ("Switch to previous tab"), G_CALLBACK (terminal_window_action_prev_tab), },
376 { "next-tab", "go-next", N_ ("_Next Tab"), "<control>Page_Down", N_ ("Switch to next tab"), G_CALLBACK (terminal_window_action_next_tab), },
377 { "last-active-tab", NULL, N_ ("Last _Active Tab"), NULL, N_ ("Switch to last active tab"), G_CALLBACK (terminal_window_action_last_active_tab), },
378 { "move-tab-left", NULL, N_ ("Move Tab _Left"), "<control><shift>Page_Up", NULL, G_CALLBACK (terminal_window_action_move_tab_left), },
379 { "move-tab-right", NULL, N_ ("Move Tab _Right"), "<control><shift>Page_Down", NULL, G_CALLBACK (terminal_window_action_move_tab_right), },
380 { "help-menu", NULL, N_ ("_Help"), NULL, NULL, NULL, },
381 { "contents", "help-browser", N_ ("_Contents"), "F1", N_ ("Display help contents"), G_CALLBACK (terminal_window_action_contents), },
382 { "about", "help-about", N_ ("_About"), NULL, NULL, G_CALLBACK (terminal_window_action_about), },
383 { "zoom-menu", NULL, N_ ("_Zoom"), NULL, NULL, NULL, },
384 };
385
386 static const GtkToggleActionEntry toggle_action_entries[] =
387 {
388 { "show-menubar", NULL, N_ ("Show _Menubar"), NULL, N_ ("Show/hide the menubar"), G_CALLBACK (terminal_window_action_show_menubar), FALSE, },
389 { "show-toolbar", NULL, N_ ("Show _Toolbar"), NULL, N_ ("Show/hide the toolbar"), G_CALLBACK (terminal_window_action_show_toolbar), FALSE, },
390 { "show-borders", NULL, N_ ("Show Window _Borders"), NULL, N_ ("Show/hide the window decorations"), G_CALLBACK (terminal_window_action_show_borders), TRUE, },
391 { "fullscreen", "view-fullscreen", N_ ("_Fullscreen"), "F11", N_ ("Toggle fullscreen mode"), G_CALLBACK (terminal_window_action_fullscreen), FALSE, },
392 { "read-only", NULL, N_ ("_Read-Only"), NULL, N_ ("Toggle read-only mode"), G_CALLBACK (terminal_window_action_readonly), FALSE, },
393 { "scroll-on-output", NULL, N_ ("Scroll on _Output"), NULL, N_ ("Toggle scroll on output"), G_CALLBACK (terminal_window_action_scroll_on_output), FALSE, },
394 };
395
396
397
G_DEFINE_TYPE_WITH_CODE(TerminalWindow,terminal_window,GTK_TYPE_WINDOW,G_ADD_PRIVATE (TerminalWindow))398 G_DEFINE_TYPE_WITH_CODE (TerminalWindow, terminal_window, GTK_TYPE_WINDOW, G_ADD_PRIVATE (TerminalWindow))
399
400
401
402 static void
403 terminal_window_class_init (TerminalWindowClass *klass)
404 {
405 GtkWidgetClass *gtkwidget_class;
406 GObjectClass *gobject_class;
407
408 gobject_class = G_OBJECT_CLASS (klass);
409 gobject_class->finalize = terminal_window_finalize;
410
411 gtkwidget_class = GTK_WIDGET_CLASS (klass);
412 gtkwidget_class->window_state_event = terminal_window_state_event;
413 gtkwidget_class->delete_event = terminal_window_delete_event;
414 gtkwidget_class->style_set = terminal_window_style_set;
415 gtkwidget_class->scroll_event = terminal_window_scroll_event;
416 gtkwidget_class->map_event = terminal_window_map_event;
417 gtkwidget_class->focus_in_event = terminal_window_focus_in_event;
418 gtkwidget_class->key_press_event = terminal_window_key_press_event;
419
420 /**
421 * TerminalWindow::new-window
422 **/
423 window_signals[NEW_WINDOW] =
424 g_signal_new (I_("new-window"),
425 G_TYPE_FROM_CLASS (gobject_class),
426 G_SIGNAL_RUN_LAST,
427 0, NULL, NULL,
428 g_cclosure_marshal_VOID__STRING,
429 G_TYPE_NONE, 1,
430 G_TYPE_STRING);
431
432 /**
433 * TerminalWindow::new-window-with-screen:
434 **/
435 window_signals[NEW_WINDOW_WITH_SCREEN] =
436 g_signal_new (I_("new-window-with-screen"),
437 G_TYPE_FROM_CLASS (gobject_class),
438 G_SIGNAL_RUN_FIRST,
439 0, NULL, NULL,
440 _terminal_marshal_VOID__OBJECT_INT_INT,
441 G_TYPE_NONE, 3,
442 G_TYPE_OBJECT,
443 G_TYPE_INT, G_TYPE_INT);
444
445 /* initialize quark */
446 tabs_menu_action_quark = g_quark_from_static_string ("tabs-menu-item");
447 }
448
449
450
451 static void
terminal_window_init(TerminalWindow * window)452 terminal_window_init (TerminalWindow *window)
453 {
454 GtkAccelGroup *accel_group;
455 gboolean always_show_tabs;
456 GdkScreen *screen;
457 GdkVisual *visual;
458 GtkStyleContext *context;
459
460 GClosure *toggle_menubar_closure = g_cclosure_new (G_CALLBACK (terminal_window_toggle_menubar), window, NULL);
461
462 window->priv = terminal_window_get_instance_private (window);
463
464 window->priv->preferences = terminal_preferences_get ();
465
466 window->priv->font = NULL;
467 window->priv->zoom = TERMINAL_ZOOM_LEVEL_DEFAULT;
468 window->priv->closed_tabs_list = g_queue_new ();
469
470 /* try to set the rgba colormap so vte can use real transparency */
471 screen = gtk_window_get_screen (GTK_WINDOW (window));
472 visual = gdk_screen_get_rgba_visual (screen);
473 if (visual != NULL)
474 gtk_widget_set_visual (GTK_WIDGET (window), visual);
475
476 /* required for vte transparency support: see https://bugzilla.gnome.org/show_bug.cgi?id=729884 */
477 gtk_widget_set_app_paintable (GTK_WIDGET (window), TRUE);
478
479 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
480 window->priv->action_group = gtk_action_group_new ("terminal-window");
481 gtk_action_group_set_translation_domain (window->priv->action_group,
482 GETTEXT_PACKAGE);
483 gtk_action_group_add_actions (window->priv->action_group,
484 action_entries,
485 G_N_ELEMENTS (action_entries),
486 GTK_WIDGET (window));
487 gtk_action_group_add_toggle_actions (window->priv->action_group,
488 toggle_action_entries,
489 G_N_ELEMENTS (toggle_action_entries),
490 GTK_WIDGET (window));
491
492 window->priv->ui_manager = gtk_ui_manager_new ();
493 gtk_ui_manager_insert_action_group (window->priv->ui_manager, window->priv->action_group, 0);
494 #if VTE_CHECK_VERSION (0, 49, 2)
495 {
496 /* add "Copy as HTML" to Edit and context menus */
497 const gchar *p1 = strstr (terminal_window_ui, "<menuitem action=\"paste\"/>"); // Edit menu
498 const gchar *p2 = strstr (p1 + 1, "<menuitem action=\"paste\"/>"); // context menu
499 const guint length_new = terminal_window_ui_length + 2 * strlen ("<menuitem action=\"copy-html\"/>");
500 gchar *ui_new = g_new0 (gchar, length_new + 1);
501 memcpy (ui_new, terminal_window_ui, p1 - terminal_window_ui);
502 strcat (ui_new, "<menuitem action=\"copy-html\"/>");
503 memcpy (ui_new + strlen (ui_new), p1, p2 - p1);
504 strcat (ui_new, "<menuitem action=\"copy-html\"/>");
505 strcat (ui_new, p2);
506 gtk_ui_manager_add_ui_from_string (window->priv->ui_manager, ui_new, length_new, NULL);
507 g_free (ui_new);
508 }
509 #else
510 gtk_ui_manager_add_ui_from_string (window->priv->ui_manager, terminal_window_ui, terminal_window_ui_length, NULL);
511 #endif
512
513 accel_group = gtk_ui_manager_get_accel_group (window->priv->ui_manager);
514 G_GNUC_END_IGNORE_DEPRECATIONS
515 gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
516
517 gtk_accel_group_connect_by_path (accel_group, "<Actions>/terminal-window/toggle-menubar", toggle_menubar_closure);
518
519 window->priv->vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
520 gtk_container_add (GTK_CONTAINER (window), window->priv->vbox);
521
522 /* avoid transparent widgets, such as menubar or tabbar */
523 context = gtk_widget_get_style_context (window->priv->vbox);
524 gtk_style_context_add_class (context, GTK_STYLE_CLASS_BACKGROUND);
525
526 /* allocate the notebook for the terminal screens */
527 g_object_get (G_OBJECT (window->priv->preferences), "misc-always-show-tabs", &always_show_tabs, NULL);
528 window->priv->notebook = g_object_new (GTK_TYPE_NOTEBOOK,
529 "scrollable", TRUE,
530 "show-border", FALSE,
531 "show-tabs", always_show_tabs,
532 NULL);
533 gtk_widget_add_events (window->priv->notebook, GDK_SCROLL_MASK);
534
535 /* set the notebook group id */
536 gtk_notebook_set_group_name (GTK_NOTEBOOK (window->priv->notebook), window_notebook_group);
537
538 /* set notebook tabs style */
539 gtk_widget_set_name (window->priv->notebook, NOTEBOOK_NAME);
540 terminal_window_update_slim_tabs (window);
541
542 /* signals */
543 g_signal_connect (G_OBJECT (window->priv->notebook), "switch-page",
544 G_CALLBACK (terminal_window_notebook_page_switched), window);
545 g_signal_connect (G_OBJECT (window->priv->notebook), "page-reordered",
546 G_CALLBACK (terminal_window_notebook_page_reordered), window);
547 g_signal_connect (G_OBJECT (window->priv->notebook), "page-removed",
548 G_CALLBACK (terminal_window_notebook_page_removed), window);
549 g_signal_connect (G_OBJECT (window->priv->notebook), "page-added",
550 G_CALLBACK (terminal_window_notebook_page_added), window);
551 g_signal_connect (G_OBJECT (window->priv->notebook), "create-window",
552 G_CALLBACK (terminal_window_notebook_create_window), window);
553 g_signal_connect (G_OBJECT (window->priv->notebook), "button-press-event",
554 G_CALLBACK (terminal_window_notebook_button_press_event), window);
555 g_signal_connect (G_OBJECT (window->priv->notebook), "button-release-event",
556 G_CALLBACK (terminal_window_notebook_button_release_event), window);
557 g_signal_connect (G_OBJECT (window->priv->notebook), "scroll-event",
558 G_CALLBACK (terminal_window_notebook_scroll_event), window);
559
560 gtk_box_pack_start (GTK_BOX (window->priv->vbox), window->priv->notebook, TRUE, TRUE, 0);
561 gtk_widget_show_all (window->priv->vbox);
562
563 /* create encoding action */
564 window->priv->encoding_action = terminal_encoding_action_new ("set-encoding", _("Set _Encoding"));
565 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
566 gtk_action_group_add_action (window->priv->action_group, window->priv->encoding_action);
567 G_GNUC_END_IGNORE_DEPRECATIONS
568 g_signal_connect (G_OBJECT (window->priv->encoding_action), "encoding-changed",
569 G_CALLBACK (terminal_window_action_set_encoding), window);
570
571 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
572 window->priv->menubar = gtk_ui_manager_get_widget (window->priv->ui_manager, "/main-menu");
573 G_GNUC_END_IGNORE_DEPRECATIONS
574 gtk_box_pack_start (GTK_BOX (window->priv->vbox), window->priv->menubar, FALSE, FALSE, 0);
575 gtk_box_reorder_child (GTK_BOX (window->priv->vbox), window->priv->menubar, 0);
576 /* don't show menubar by default */
577 gtk_widget_hide (window->priv->menubar);
578 /* auto-hide menubar if it was shown temporarily */
579 g_signal_connect (G_OBJECT (window->priv->menubar), "deactivate",
580 G_CALLBACK (terminal_window_menubar_deactivate), window);
581
582 /* cache action pointers */
583 window->priv->action_undo_close_tab = terminal_window_get_action (window, "undo-close-tab");
584 window->priv->action_detach_tab = terminal_window_get_action (window, "detach-tab");
585 window->priv->action_close_other_tabs = terminal_window_get_action (window, "close-other-tabs");
586 window->priv->action_prev_tab = terminal_window_get_action (window, "prev-tab");
587 window->priv->action_next_tab = terminal_window_get_action (window, "next-tab");
588 window->priv->action_last_active_tab = terminal_window_get_action (window, "last-active-tab");
589 window->priv->action_move_tab_left = terminal_window_get_action (window, "move-tab-left");
590 window->priv->action_move_tab_right = terminal_window_get_action (window, "move-tab-right");
591 window->priv->action_copy = terminal_window_get_action (window, "copy");
592 window->priv->action_search_next = terminal_window_get_action (window, "search-next");
593 window->priv->action_search_prev = terminal_window_get_action (window, "search-prev");
594 window->priv->action_fullscreen = terminal_window_get_action (window, "fullscreen");
595
596 /* monitor the scrolling-on-output setting */
597 g_signal_connect_swapped (G_OBJECT (window->priv->preferences), "notify::scrolling-on-output",
598 G_CALLBACK (terminal_window_update_scroll_on_output), window);
599
600 /* monitor the shortcuts-no-mnemonics setting */
601 terminal_window_update_mnemonic_modifier (window);
602 g_signal_connect_swapped (G_OBJECT (window->priv->preferences), "notify::shortcuts-no-mnemonics",
603 G_CALLBACK (terminal_window_update_mnemonic_modifier), window);
604
605 #if defined(GDK_WINDOWING_X11)
606 if (GDK_IS_X11_SCREEN (screen))
607 {
608 /* setup fullscreen mode */
609 if (!gdk_x11_screen_supports_net_wm_hint (screen, gdk_atom_intern ("_NET_WM_STATE_FULLSCREEN", FALSE)))
610 {
611 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
612 gtk_action_set_sensitive (window->priv->action_fullscreen, FALSE);
613 G_GNUC_END_IGNORE_DEPRECATIONS
614 }
615 }
616 #endif
617 }
618
619
620
621 static void
terminal_window_finalize(GObject * object)622 terminal_window_finalize (GObject *object)
623 {
624 TerminalWindow *window = TERMINAL_WINDOW (object);
625
626 /* disconnect scrolling-on-output and shortcuts-no-mnemonics watches */
627 g_signal_handlers_disconnect_by_func (G_OBJECT (window->priv->preferences),
628 G_CALLBACK (terminal_window_update_scroll_on_output), window);
629 g_signal_handlers_disconnect_by_func (G_OBJECT (window->priv->preferences),
630 G_CALLBACK (terminal_window_update_mnemonic_modifier), window);
631
632 if (window->priv->preferences_dialog != NULL)
633 gtk_widget_destroy (window->priv->preferences_dialog);
634 g_object_unref (G_OBJECT (window->priv->preferences));
635 g_object_unref (G_OBJECT (window->priv->action_group));
636 g_object_unref (G_OBJECT (window->priv->ui_manager));
637 g_object_unref (G_OBJECT (window->priv->encoding_action));
638
639 g_slist_free (window->priv->tabs_menu_actions);
640 g_free (window->priv->font);
641 g_queue_free_full (window->priv->closed_tabs_list, (GDestroyNotify) terminal_tab_attr_free);
642
643 (*G_OBJECT_CLASS (terminal_window_parent_class)->finalize) (object);
644 }
645
646
647
648 static gboolean
terminal_window_delete_event(GtkWidget * widget,GdkEventAny * event)649 terminal_window_delete_event (GtkWidget *widget,
650 GdkEventAny *event)
651 {
652 TerminalWindow *window = TERMINAL_WINDOW (widget);
653 GtkWidget *child;
654 gint n_pages, i, response;
655
656 response = terminal_window_confirm_close (NULL, window);
657
658 /* disconnect remove signal if we're closing the window */
659 if (response == CONFIRMED_CLOSE_WINDOW)
660 {
661 /* disconnect handlers for closing Set Title dialog */
662 if (window->priv->title_popover != NULL)
663 {
664 n_pages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->priv->notebook));
665 for (i = 0; i < n_pages; i++)
666 {
667 child = gtk_notebook_get_nth_page (GTK_NOTEBOOK (window->priv->notebook), i);
668 g_signal_handlers_disconnect_by_func (G_OBJECT (child),
669 G_CALLBACK (title_popover_close), window);
670 }
671 }
672
673 /* avoid a lot of page remove calls */
674 g_signal_handlers_disconnect_by_func (G_OBJECT (window->priv->notebook),
675 G_CALLBACK (terminal_window_notebook_page_removed), window);
676
677 /* let gtk close the window */
678 if (GTK_WIDGET_CLASS (terminal_window_parent_class)->delete_event != NULL)
679 return (*GTK_WIDGET_CLASS (terminal_window_parent_class)->delete_event) (widget, event);
680
681 return FALSE;
682 }
683 else if (response == CONFIRMED_CLOSE_TAB)
684 terminal_window_do_close_tab (window->priv->active, window);
685
686 return TRUE;
687 }
688
689
690
691 static gboolean
terminal_window_state_event(GtkWidget * widget,GdkEventWindowState * event)692 terminal_window_state_event (GtkWidget *widget,
693 GdkEventWindowState *event)
694 {
695 TerminalWindow *window = TERMINAL_WINDOW (widget);
696 gboolean fullscreen;
697
698 terminal_return_val_if_fail (TERMINAL_IS_WINDOW (window), FALSE);
699
700 /* update the fullscreen action if the fullscreen state changed by the wm */
701 if ((event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) != 0
702 && gtk_widget_get_visible (widget))
703 {
704 fullscreen = (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) != 0;
705 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
706 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (window->priv->action_fullscreen)) != fullscreen)
707 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (window->priv->action_fullscreen), fullscreen);
708 G_GNUC_END_IGNORE_DEPRECATIONS
709
710 /* update drop-down window geometry, otherwise it'll be incorrect */
711 if (!fullscreen && window->priv->drop_down)
712 terminal_window_dropdown_update_geometry (TERMINAL_WINDOW_DROPDOWN (window));
713 }
714
715 if (GTK_WIDGET_CLASS (terminal_window_parent_class)->window_state_event != NULL)
716 return (*GTK_WIDGET_CLASS (terminal_window_parent_class)->window_state_event) (widget, event);
717
718 return FALSE;
719 }
720
721
722
723 static void
terminal_window_style_set(GtkWidget * widget,GtkStyle * previous_style)724 terminal_window_style_set (GtkWidget *widget,
725 GtkStyle *previous_style)
726 {
727 TerminalWindow *window = TERMINAL_WINDOW (widget);
728
729 if (previous_style != NULL)
730 terminal_window_size_push (window);
731
732 (*GTK_WIDGET_CLASS (terminal_window_parent_class)->style_set) (widget, previous_style);
733
734 /* delay the pop until after size allocate */
735 if (previous_style != NULL)
736 gdk_threads_add_idle (terminal_window_size_pop, window);
737 }
738
739
740
741 static gboolean
terminal_window_scroll_event(GtkWidget * widget,GdkEventScroll * event)742 terminal_window_scroll_event (GtkWidget *widget,
743 GdkEventScroll *event)
744 {
745 TerminalWindow *window = TERMINAL_WINDOW (widget);
746 gboolean mouse_wheel_zoom;
747
748 g_object_get (G_OBJECT (window->priv->preferences),
749 "misc-mouse-wheel-zoom", &mouse_wheel_zoom, NULL);
750
751 if (mouse_wheel_zoom && event->state == (GDK_SHIFT_MASK | GDK_CONTROL_MASK)
752 && event->direction == GDK_SCROLL_UP)
753 {
754 terminal_window_action_zoom_in (NULL, window);
755 return TRUE;
756 }
757
758 if (mouse_wheel_zoom && event->state == (GDK_SHIFT_MASK | GDK_CONTROL_MASK)
759 && event->direction == GDK_SCROLL_DOWN)
760 {
761 terminal_window_action_zoom_out (NULL, window);
762 return TRUE;
763 }
764
765 return FALSE;
766 }
767
768
769
770 static gboolean
terminal_window_map_event(GtkWidget * widget,GdkEventAny * event)771 terminal_window_map_event (GtkWidget *widget,
772 GdkEventAny *event)
773 {
774 TerminalWindow *window = TERMINAL_WINDOW (widget);
775 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
776 gboolean fullscreen = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (window->priv->action_fullscreen));
777 G_GNUC_END_IGNORE_DEPRECATIONS
778
779 if (fullscreen)
780 gtk_window_fullscreen (GTK_WINDOW (widget));
781
782 return FALSE;
783 }
784
785
786
787 static gboolean
terminal_window_focus_in_event(GtkWidget * widget,GdkEventFocus * event)788 terminal_window_focus_in_event (GtkWidget *widget,
789 GdkEventFocus *event)
790 {
791 TerminalWindow *window = TERMINAL_WINDOW (widget);
792
793 /* reset activity indicator for the active tab when focusing window */
794 terminal_screen_reset_activity (window->priv->active);
795
796 return (*GTK_WIDGET_CLASS (terminal_window_parent_class)->focus_in_event) (widget, event);
797 }
798
799
800
801 static gboolean
terminal_window_key_press_event(GtkWidget * widget,GdkEventKey * event)802 terminal_window_key_press_event (GtkWidget *widget,
803 GdkEventKey *event)
804 {
805 TerminalWindow *window = TERMINAL_WINDOW (widget);
806 const guint modifiers = event->state & gtk_accelerator_get_default_mod_mask ();
807
808 /* support shortcuts that contain the Tab key
809 Tab sometimes becomes ISO_Left_Tab (e.g. in Ctrl+Shift+Tab) so check both here */
810 if (G_UNLIKELY (window->priv->tab_key_accels != NULL
811 && (event->keyval == GDK_KEY_Tab || event->keyval == GDK_KEY_ISO_Left_Tab)))
812 {
813 GSList *lp;
814 for (lp = window->priv->tab_key_accels; lp != NULL; lp = lp->next)
815 {
816 TerminalAccel *accel = lp->data;
817 if (accel->mods == modifiers)
818 {
819 GtkAction *action = terminal_window_get_action (window, accel->path);
820 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
821 if (G_LIKELY (GTK_IS_ACTION (action)))
822 {
823 gtk_action_activate (action);
824 return TRUE;
825 }
826 G_GNUC_END_IGNORE_DEPRECATIONS
827 }
828 }
829 }
830
831 /* handle Ctrl+Shift+Ins (paste clipboard) and Shift+Ins (paste selection) */
832 if (event->keyval == GDK_KEY_Insert || event->keyval == GDK_KEY_KP_Insert)
833 {
834 if (modifiers == (GDK_CONTROL_MASK | GDK_SHIFT_MASK))
835 {
836 terminal_window_action_paste (NULL, window);
837 return TRUE;
838 }
839 else if (modifiers == GDK_SHIFT_MASK)
840 {
841 terminal_window_action_paste_selection (NULL, window);
842 return TRUE;
843 }
844 }
845
846 return (*GTK_WIDGET_CLASS (terminal_window_parent_class)->key_press_event) (widget, event);
847 }
848
849
850
851 static gint
terminal_window_confirm_close(TerminalScreen * screen,TerminalWindow * window)852 terminal_window_confirm_close (TerminalScreen *screen,
853 TerminalWindow *window)
854 {
855 GtkWidget *dialog;
856 GtkWidget *button;
857 GtkWidget *hbox;
858 GtkWidget *image;
859 GtkWidget *vbox;
860 GtkWidget *label;
861 GtkWidget *checkbox;
862 const gchar *title;
863 gchar *message;
864 gchar *markup;
865 gint response;
866 gint i, n_tabs;
867 gboolean confirm_close;
868
869 g_object_get (G_OBJECT (window->priv->preferences), "misc-confirm-close", &confirm_close, NULL);
870 if (!confirm_close)
871 return (screen != NULL) ? CONFIRMED_CLOSE_TAB : CONFIRMED_CLOSE_WINDOW;
872
873 n_tabs = gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->priv->notebook));
874 confirm_close = FALSE;
875 for (i = 0; i < n_tabs; ++i)
876 {
877 TerminalScreen *tab = TERMINAL_SCREEN (gtk_notebook_get_nth_page (GTK_NOTEBOOK (window->priv->notebook), i));
878 if ((screen == NULL || screen == tab) && terminal_screen_has_foreground_process (tab))
879 {
880 confirm_close = TRUE;
881 break;
882 }
883 }
884
885 if ((screen != NULL || n_tabs < 2) && !confirm_close)
886 return (screen != NULL) ? CONFIRMED_CLOSE_TAB : CONFIRMED_CLOSE_WINDOW;
887
888 dialog = gtk_dialog_new ();
889 gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (window));
890 gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE);
891 gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
892 gtk_window_set_title (GTK_WINDOW (dialog), _("Warning"));
893
894 button = xfce_gtk_button_new_mixed ("gtk-cancel", _("_Cancel"));
895 gtk_dialog_add_action_widget (GTK_DIALOG (dialog), button, GTK_RESPONSE_CANCEL);
896
897 if (screen == NULL && n_tabs > 1)
898 {
899 /* closing window with multiple tabs */
900 if (confirm_close)
901 {
902 /* and process running */
903 message = g_strdup (_("There are still processes running in some tabs.\n"
904 "Closing this window will kill all of them."));
905 }
906 else
907 {
908 /* and no process running */
909 message = g_strdup_printf (_("This window has %d tabs open. Closing this window\n"
910 "will also close all its tabs."), n_tabs);
911 }
912
913 title = _("Close all tabs?");
914 }
915 else
916 {
917 if (screen != NULL)
918 {
919 /* closing a tab, and process running */
920 message = g_strdup (_("There is still a process running.\n"
921 "Closing this tab will kill it."));
922 title = _("Close tab?");
923 }
924 else
925 {
926 /* closing a single tab window, and process running */
927 message = g_strdup (_("There is still a process running.\n"
928 "Closing this window will kill it."));
929 title = _("Close window?");
930 }
931 }
932
933 if (screen != NULL || n_tabs > 1)
934 {
935 button = xfce_gtk_button_new_mixed ("window-close", _("Close T_ab"));
936 gtk_dialog_add_action_widget (GTK_DIALOG (dialog), button, GTK_RESPONSE_CLOSE);
937 gtk_widget_grab_focus (button);
938 }
939
940 if (screen == NULL)
941 {
942 button = xfce_gtk_button_new_mixed ("application-exit", _("Close _Window"));
943 gtk_dialog_add_action_widget (GTK_DIALOG (dialog), button, GTK_RESPONSE_YES);
944 gtk_widget_grab_focus (button);
945 }
946
947 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
948 gtk_container_set_border_width (GTK_CONTAINER (hbox), 8);
949 gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), hbox, TRUE, TRUE, 0);
950
951 image = gtk_image_new_from_icon_name ("dialog-warning", GTK_ICON_SIZE_DIALOG);
952 gtk_widget_set_halign (image, GTK_ALIGN_CENTER);
953 gtk_widget_set_valign (image, GTK_ALIGN_START);
954 gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
955
956 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
957 gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
958
959 markup = g_strdup_printf ("<span weight=\"bold\" size=\"larger\">%s</span>\n\n%s", title, message);
960 g_free (message);
961
962 label = g_object_new (GTK_TYPE_LABEL,
963 "label", markup,
964 "use-markup", TRUE,
965 "xalign", 0.0,
966 NULL);
967 gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0);
968
969 g_free (markup);
970
971 checkbox = gtk_check_button_new_with_mnemonic (_("Do _not ask me again"));
972 gtk_box_pack_start (GTK_BOX (vbox), checkbox, FALSE, FALSE, 0);
973
974 gtk_widget_show_all (dialog);
975
976 response = gtk_dialog_run (GTK_DIALOG (dialog));
977 if (response == GTK_RESPONSE_YES)
978 {
979 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (checkbox)))
980 {
981 g_object_set (G_OBJECT (window->priv->preferences),
982 "misc-confirm-close", FALSE,
983 NULL);
984 }
985 }
986
987 gtk_widget_destroy (dialog);
988
989 if (response == GTK_RESPONSE_YES)
990 return CONFIRMED_CLOSE_WINDOW;
991 if (response == GTK_RESPONSE_CLOSE)
992 return CONFIRMED_CLOSE_TAB;
993 return CONFIRMED_NONE;
994 }
995
996
997
998 static void
terminal_window_size_push(TerminalWindow * window)999 terminal_window_size_push (TerminalWindow *window)
1000 {
1001 terminal_return_if_fail (TERMINAL_IS_WINDOW (window));
1002
1003 if (window->priv->active != NULL)
1004 {
1005 terminal_screen_get_size (window->priv->active,
1006 &window->priv->grid_width,
1007 &window->priv->grid_height);
1008 }
1009 }
1010
1011
1012
1013 static gboolean
terminal_window_size_pop(gpointer data)1014 terminal_window_size_pop (gpointer data)
1015 {
1016 TerminalWindow *window = TERMINAL_WINDOW (data);
1017
1018 terminal_return_val_if_fail (TERMINAL_IS_WINDOW (window), FALSE);
1019
1020 if (window->priv->active != NULL)
1021 {
1022 terminal_window_set_size_force_grid (window, window->priv->active,
1023 window->priv->grid_width,
1024 window->priv->grid_height);
1025 }
1026
1027 return FALSE;
1028 }
1029
1030
1031
1032 static void
terminal_window_set_size_force_grid(TerminalWindow * window,TerminalScreen * screen,glong force_grid_width,glong force_grid_height)1033 terminal_window_set_size_force_grid (TerminalWindow *window,
1034 TerminalScreen *screen,
1035 glong force_grid_width,
1036 glong force_grid_height)
1037 {
1038 GdkWindow *gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
1039
1040 terminal_return_if_fail (TERMINAL_IS_WINDOW (window));
1041 terminal_return_if_fail (TERMINAL_IS_SCREEN (screen));
1042
1043 /* required to get the char height/width right */
1044 if (gtk_widget_get_realized (GTK_WIDGET (screen))
1045 && gdk_window != NULL
1046 && (gdk_window_get_state (gdk_window) & (GDK_WINDOW_STATE_FULLSCREEN | WINDOW_STATE_TILED)) == 0
1047 && !window->priv->drop_down )
1048 {
1049 terminal_screen_force_resize_window (screen, GTK_WINDOW (window),
1050 force_grid_width, force_grid_height);
1051 }
1052 }
1053
1054
1055
1056 static void
terminal_window_update_actions(TerminalWindow * window)1057 terminal_window_update_actions (TerminalWindow *window)
1058 {
1059 GtkNotebook *notebook = GTK_NOTEBOOK (window->priv->notebook);
1060 GtkAction *action;
1061 gboolean cycle_tabs;
1062 gint page_num;
1063 gint n_pages;
1064
1065 /* determine the number of pages */
1066 n_pages = gtk_notebook_get_n_pages (notebook);
1067
1068 /* "Detach Tab" and "Close Other Tabs" are sensitive if we have at least two pages.
1069 * "Undo Close" is sensitive if there is a tab to unclose. */
1070 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
1071 gtk_action_set_sensitive (window->priv->action_detach_tab, (n_pages > 1));
1072 gtk_action_set_sensitive (window->priv->action_close_other_tabs, n_pages > 1);
1073
1074 gtk_action_set_sensitive (window->priv->action_undo_close_tab, !g_queue_is_empty (window->priv->closed_tabs_list));
1075 G_GNUC_END_IGNORE_DEPRECATIONS
1076
1077 /* update the actions for the current terminal screen */
1078 if (G_LIKELY (window->priv->active != NULL))
1079 {
1080 gboolean can_go_left, can_go_right, can_search, input_enabled;
1081
1082 page_num = gtk_notebook_page_num (notebook, GTK_WIDGET (window->priv->active));
1083
1084 g_object_get (G_OBJECT (window->priv->preferences),
1085 "misc-cycle-tabs", &cycle_tabs,
1086 NULL);
1087
1088 can_go_left = (cycle_tabs && n_pages > 1) || (page_num > 0);
1089 can_go_right = (cycle_tabs && n_pages > 1) || (page_num < n_pages - 1);
1090
1091 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
1092 gtk_action_set_sensitive (window->priv->action_prev_tab, can_go_left);
1093 gtk_action_set_sensitive (window->priv->action_move_tab_left, can_go_left);
1094 gtk_action_set_sensitive (window->priv->action_next_tab, can_go_right);
1095 gtk_action_set_sensitive (window->priv->action_move_tab_right, can_go_right);
1096 gtk_action_set_sensitive (window->priv->action_last_active_tab, window->priv->last_active != NULL);
1097
1098 gtk_action_set_sensitive (window->priv->action_copy,
1099 terminal_screen_has_selection (window->priv->active));
1100 #if VTE_CHECK_VERSION (0, 49, 2)
1101 gtk_action_set_sensitive (terminal_window_get_action (window, "copy-html"),
1102 terminal_screen_has_selection (window->priv->active));
1103 #endif
1104
1105 can_search = terminal_screen_search_has_gregex (window->priv->active);
1106 gtk_action_set_sensitive (window->priv->action_search_next, can_search);
1107 gtk_action_set_sensitive (window->priv->action_search_prev, can_search);
1108
1109 /* update read-only mode */
1110 input_enabled = terminal_screen_get_input_enabled (window->priv->active);
1111 action = terminal_window_get_action (window, "read-only");
1112 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), !input_enabled);
1113
1114 /* update "Paste" actions */
1115 action = terminal_window_get_action (window, "paste");
1116 gtk_action_set_sensitive (action, input_enabled);
1117 action = terminal_window_get_action (window, "paste-selection");
1118 gtk_action_set_sensitive (action, input_enabled);
1119
1120 /* update scroll on output mode */
1121 action = terminal_window_get_action (window, "scroll-on-output");
1122 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1123 terminal_screen_get_scroll_on_output (window->priv->active));
1124
1125 /* update the "Go" menu */
1126 action = g_object_get_qdata (G_OBJECT (window->priv->active), tabs_menu_action_quark);
1127 if (G_LIKELY (action != NULL))
1128 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1129 G_GNUC_END_IGNORE_DEPRECATIONS
1130 }
1131 }
1132
1133
1134
1135 static void
terminal_window_update_slim_tabs(TerminalWindow * window)1136 terminal_window_update_slim_tabs (TerminalWindow *window)
1137 {
1138 GdkScreen *screen = gtk_window_get_screen (GTK_WINDOW (window));
1139 GtkCssProvider *provider;
1140 gboolean slim_tabs;
1141
1142 g_object_get (G_OBJECT (window->priv->preferences),
1143 "misc-slim-tabs", &slim_tabs,
1144 NULL);
1145 if (slim_tabs)
1146 {
1147 provider = gtk_css_provider_new ();
1148 gtk_style_context_add_provider_for_screen (screen,
1149 GTK_STYLE_PROVIDER (provider),
1150 GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
1151 gtk_css_provider_load_from_data (provider, CSS_SLIM_TABS, -1, NULL);
1152 g_object_unref (provider);
1153 }
1154 }
1155
1156
1157
1158 static void
terminal_window_update_scroll_on_output(TerminalWindow * window)1159 terminal_window_update_scroll_on_output (TerminalWindow *window)
1160 {
1161 GtkAction *action;
1162 gboolean scroll;
1163
1164 g_object_get (G_OBJECT (window->priv->preferences),
1165 "scrolling-on-output", &scroll,
1166 NULL);
1167 action = terminal_window_get_action (window, "scroll-on-output");
1168 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
1169 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), scroll);
1170 G_GNUC_END_IGNORE_DEPRECATIONS
1171 }
1172
1173
1174
1175 static void
terminal_window_update_mnemonic_modifier(TerminalWindow * window)1176 terminal_window_update_mnemonic_modifier (TerminalWindow *window)
1177 {
1178 gboolean no_mnemonics;
1179
1180 g_object_get (G_OBJECT (window->priv->preferences),
1181 "shortcuts-no-mnemonics", &no_mnemonics,
1182 NULL);
1183 if (no_mnemonics)
1184 gtk_window_set_mnemonic_modifier (GTK_WINDOW (window), GDK_MODIFIER_MASK & ~GDK_RELEASE_MASK);
1185 else
1186 gtk_window_set_mnemonic_modifier (GTK_WINDOW (window), GDK_MOD1_MASK);
1187 }
1188
1189
1190
1191 static void
terminal_window_notebook_page_switched(GtkNotebook * notebook,GtkWidget * page,guint page_num,TerminalWindow * window)1192 terminal_window_notebook_page_switched (GtkNotebook *notebook,
1193 GtkWidget *page,
1194 guint page_num,
1195 TerminalWindow *window)
1196 {
1197 TerminalScreen *active = TERMINAL_SCREEN (page);
1198 const gchar *encoding;
1199
1200 terminal_return_if_fail (TERMINAL_IS_WINDOW (window));
1201 terminal_return_if_fail (active == NULL || TERMINAL_IS_SCREEN (active));
1202
1203 /* only update when really changed */
1204 if (G_LIKELY (window->priv->active != active))
1205 {
1206 /* store last and set new active tab */
1207 window->priv->last_active = window->priv->active;
1208 window->priv->active = active;
1209
1210 /* set the new window title */
1211 terminal_window_notify_title (active, NULL, window);
1212
1213 /* reset the activity counter */
1214 terminal_screen_reset_activity (active);
1215
1216 /* set charset for menu */
1217 encoding = terminal_screen_get_encoding (window->priv->active);
1218 terminal_encoding_action_set_charset (window->priv->encoding_action, encoding);
1219 }
1220
1221 /* update actions in the window */
1222 terminal_window_update_actions (window);
1223 }
1224
1225
1226
1227 static void
terminal_window_notebook_page_reordered(GtkNotebook * notebook,GtkWidget * child,guint page_num,TerminalWindow * window)1228 terminal_window_notebook_page_reordered (GtkNotebook *notebook,
1229 GtkWidget *child,
1230 guint page_num,
1231 TerminalWindow *window)
1232 {
1233 /* Regenerate the "Go" menu and update actions */
1234 terminal_window_rebuild_tabs_menu (window);
1235 terminal_window_update_actions (window);
1236 }
1237
1238
1239
1240 static void
terminal_window_close_tab_request(TerminalScreen * screen,TerminalWindow * window)1241 terminal_window_close_tab_request (TerminalScreen *screen,
1242 TerminalWindow *window)
1243 {
1244 if (terminal_window_confirm_close (screen, window) == CONFIRMED_CLOSE_TAB)
1245 terminal_window_do_close_tab (screen, window);
1246 }
1247
1248
1249
1250 static void
terminal_window_notebook_page_added(GtkNotebook * notebook,GtkWidget * child,guint page_num,TerminalWindow * window)1251 terminal_window_notebook_page_added (GtkNotebook *notebook,
1252 GtkWidget *child,
1253 guint page_num,
1254 TerminalWindow *window)
1255 {
1256 TerminalScreen *screen = TERMINAL_SCREEN (child);
1257 glong w, h;
1258
1259 terminal_return_if_fail (TERMINAL_IS_SCREEN (child));
1260 terminal_return_if_fail (TERMINAL_IS_WINDOW (window));
1261 terminal_return_if_fail (GTK_IS_NOTEBOOK (notebook));
1262 terminal_return_if_fail (window->priv->notebook == GTK_WIDGET (notebook));
1263
1264 /* connect screen signals */
1265 g_signal_connect (G_OBJECT (screen), "get-context-menu",
1266 G_CALLBACK (terminal_window_get_context_menu), window);
1267 g_signal_connect (G_OBJECT (screen), "notify::title",
1268 G_CALLBACK (terminal_window_notify_title), window);
1269 g_signal_connect_swapped (G_OBJECT (screen), "selection-changed",
1270 G_CALLBACK (terminal_window_update_actions), window);
1271 g_signal_connect (G_OBJECT (screen), "close-tab-request",
1272 G_CALLBACK (terminal_window_close_tab_request), window);
1273 g_signal_connect (G_OBJECT (screen), "drag-data-received",
1274 G_CALLBACK (terminal_window_notebook_drag_data_received), window);
1275
1276 /* release to the grid size applies */
1277 gtk_widget_realize (GTK_WIDGET (screen));
1278
1279 /* match zoom and font */
1280 if (window->priv->font || window->priv->zoom != TERMINAL_ZOOM_LEVEL_DEFAULT)
1281 terminal_screen_update_font (screen);
1282
1283 if (G_LIKELY (window->priv->active != NULL))
1284 {
1285 /* match the size of the active screen */
1286 terminal_screen_get_size (window->priv->active, &w, &h);
1287 terminal_screen_set_size (screen, w, h);
1288
1289 /* show the tabs when needed */
1290 terminal_window_notebook_show_tabs (window);
1291 }
1292 else if (G_UNLIKELY (window->priv->drop_down))
1293 {
1294 /* try to calculate a decent grid size based on the info we have now */
1295 terminal_window_dropdown_get_size (TERMINAL_WINDOW_DROPDOWN (window), screen, &w, &h);
1296 terminal_screen_set_size (screen, w, h);
1297 }
1298
1299 /* regenerate the "Go" menu */
1300 terminal_window_rebuild_tabs_menu (window);
1301 }
1302
1303
1304
1305 static void
terminal_window_notebook_page_removed(GtkNotebook * notebook,GtkWidget * child,guint page_num,TerminalWindow * window)1306 terminal_window_notebook_page_removed (GtkNotebook *notebook,
1307 GtkWidget *child,
1308 guint page_num,
1309 TerminalWindow *window)
1310 {
1311 GtkWidget *new_page;
1312 gint new_page_num;
1313 gint npages;
1314
1315 terminal_return_if_fail (TERMINAL_IS_SCREEN (child));
1316 terminal_return_if_fail (TERMINAL_IS_WINDOW (window));
1317
1318 /* unset the go menu item */
1319 g_object_set_qdata (G_OBJECT (child), tabs_menu_action_quark, NULL);
1320
1321 /* disconnect signals */
1322 g_signal_handlers_disconnect_by_func (G_OBJECT (child),
1323 terminal_window_get_context_menu, window);
1324 g_signal_handlers_disconnect_by_func (G_OBJECT (child),
1325 terminal_window_notify_title, window);
1326 g_signal_handlers_disconnect_by_func (G_OBJECT (child),
1327 terminal_window_update_actions, window);
1328 g_signal_handlers_disconnect_by_func (G_OBJECT (child),
1329 terminal_window_close_tab_request, window);
1330 g_signal_handlers_disconnect_by_func (G_OBJECT (child),
1331 terminal_window_notebook_drag_data_received, window);
1332
1333 /* set tab visibility */
1334 npages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->priv->notebook));
1335 if (G_UNLIKELY (npages == 0))
1336 {
1337 /* no tabs, destroy the window */
1338 gtk_widget_destroy (GTK_WIDGET (window));
1339 return;
1340 }
1341
1342 /* clear last_active tab if it has just been closed */
1343 if (child == GTK_WIDGET (window->priv->last_active))
1344 window->priv->last_active = NULL;
1345
1346 /* show the tabs when needed */
1347 terminal_window_notebook_show_tabs (window);
1348
1349 /* regenerate the "Go" menu */
1350 terminal_window_rebuild_tabs_menu (window);
1351
1352 /* send a signal about switching to another tab */
1353 new_page_num = gtk_notebook_get_current_page (GTK_NOTEBOOK (window->priv->notebook));
1354 new_page = gtk_notebook_get_nth_page (GTK_NOTEBOOK (window->priv->notebook), new_page_num);
1355 terminal_window_notebook_page_switched (notebook, new_page, new_page_num, window);
1356 }
1357
1358
1359
1360 static gboolean
terminal_window_notebook_event_in_allocation(gint event_x,gint event_y,GtkWidget * widget)1361 terminal_window_notebook_event_in_allocation (gint event_x,
1362 gint event_y,
1363 GtkWidget *widget)
1364 {
1365 GtkAllocation allocation;
1366
1367 gtk_widget_get_allocation (widget, &allocation);
1368
1369 if (event_x >= allocation.x && event_x <= allocation.x + allocation.width
1370 && event_y >= allocation.y && event_y <= allocation.y + allocation.height)
1371 {
1372 return TRUE;
1373 }
1374
1375 return FALSE;
1376 }
1377
1378
1379
1380 static gboolean
terminal_window_notebook_button_press_event(GtkNotebook * notebook,GdkEventButton * event,TerminalWindow * window)1381 terminal_window_notebook_button_press_event (GtkNotebook *notebook,
1382 GdkEventButton *event,
1383 TerminalWindow *window)
1384 {
1385 GtkWidget *page, *label, *menu;
1386 gint page_num = 0;
1387 gboolean close_middle_click;
1388 gint x, y;
1389
1390 terminal_return_val_if_fail (TERMINAL_IS_WINDOW (window), FALSE);
1391 terminal_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
1392
1393 gdk_window_get_position (event->window, &x, &y);
1394 x += event->x;
1395 y += event->y;
1396
1397 if (event->button == 1)
1398 {
1399 if (event->type == GDK_2BUTTON_PRESS)
1400 {
1401 /* check if the user double-clicked on the label */
1402 label = gtk_notebook_get_tab_label (notebook, GTK_WIDGET (window->priv->active));
1403 if (terminal_window_notebook_event_in_allocation (x, y, label))
1404 {
1405 terminal_window_action_set_title (NULL, window);
1406 return TRUE;
1407 }
1408 }
1409 }
1410 else if (event->type == GDK_BUTTON_PRESS && event->button <= 3)
1411 {
1412 /* select the page the user clicked on */
1413 while ((page = gtk_notebook_get_nth_page (notebook, page_num)) != NULL)
1414 {
1415 label = gtk_notebook_get_tab_label (notebook, page);
1416 if (terminal_window_notebook_event_in_allocation (x, y, label))
1417 break;
1418 page_num++;
1419 }
1420
1421 /* leave if somehow no tab was found */
1422 if (G_UNLIKELY (page == NULL))
1423 return FALSE;
1424
1425 if (event->button == 2)
1426 {
1427 /* close the tab on middle click */
1428 g_object_get (G_OBJECT (window->priv->preferences),
1429 "misc-tab-close-middle-click", &close_middle_click, NULL);
1430 if (close_middle_click)
1431 terminal_window_close_tab_request (TERMINAL_SCREEN (page), window);
1432 }
1433 else
1434 {
1435 /* update the current tab before we show the menu */
1436 gtk_notebook_set_current_page (notebook, page_num);
1437
1438 /* show the tab menu */
1439 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
1440 menu = gtk_ui_manager_get_widget (window->priv->ui_manager, "/tab-menu");
1441 G_GNUC_END_IGNORE_DEPRECATIONS
1442 gtk_menu_popup_at_pointer (GTK_MENU (menu), NULL);
1443 }
1444
1445 return TRUE;
1446 }
1447
1448 return FALSE;
1449 }
1450
1451
1452
1453 static gboolean
terminal_window_notebook_button_release_event(GtkNotebook * notebook,GdkEventButton * event,TerminalWindow * window)1454 terminal_window_notebook_button_release_event (GtkNotebook *notebook,
1455 GdkEventButton *event,
1456 TerminalWindow *window)
1457 {
1458 terminal_return_val_if_fail (TERMINAL_IS_WINDOW (window), FALSE);
1459 terminal_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
1460
1461 if (G_LIKELY (window->priv->active != NULL))
1462 terminal_screen_focus (window->priv->active);
1463
1464 return FALSE;
1465 }
1466
1467
1468
1469 static gboolean
terminal_window_notebook_scroll_event(GtkNotebook * notebook,GdkEventScroll * event,TerminalWindow * window)1470 terminal_window_notebook_scroll_event (GtkNotebook *notebook,
1471 GdkEventScroll *event,
1472 TerminalWindow *window)
1473 {
1474 terminal_return_val_if_fail (TERMINAL_IS_WINDOW (window), FALSE);
1475 terminal_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
1476
1477 if ((event->state & gtk_accelerator_get_default_mod_mask ()) != 0)
1478 return FALSE;
1479
1480 switch (event->direction) {
1481 case GDK_SCROLL_RIGHT:
1482 case GDK_SCROLL_DOWN:
1483 gtk_notebook_next_page (notebook);
1484 return TRUE;
1485
1486 case GDK_SCROLL_LEFT:
1487 case GDK_SCROLL_UP:
1488 gtk_notebook_prev_page (notebook);
1489 return TRUE;
1490
1491 default: /* GDK_SCROLL_SMOOTH */
1492 switch (gtk_notebook_get_tab_pos (notebook)) {
1493 case GTK_POS_LEFT:
1494 case GTK_POS_RIGHT:
1495 if (event->delta_y > 0)
1496 gtk_notebook_next_page (notebook);
1497 else if (event->delta_y < 0)
1498 gtk_notebook_prev_page (notebook);
1499 break;
1500
1501 default: /* GTK_POS_TOP or GTK_POS_BOTTOM */
1502 if (event->delta_x > 0)
1503 gtk_notebook_next_page (notebook);
1504 else if (event->delta_x < 0)
1505 gtk_notebook_prev_page (notebook);
1506 break;
1507 }
1508 return TRUE;
1509 }
1510
1511 return FALSE;
1512 }
1513
1514
1515
1516 static void
terminal_window_notebook_drag_data_received(GtkWidget * widget,GdkDragContext * context,gint x,gint y,GtkSelectionData * selection_data,guint info,guint time,TerminalWindow * window)1517 terminal_window_notebook_drag_data_received (GtkWidget *widget,
1518 GdkDragContext *context,
1519 gint x,
1520 gint y,
1521 GtkSelectionData *selection_data,
1522 guint info,
1523 guint time,
1524 TerminalWindow *window)
1525 {
1526 GtkWidget *notebook;
1527 GtkWidget *screen;
1528 gint i, n_pages;
1529 gboolean succeed = FALSE;
1530
1531 terminal_return_if_fail (TERMINAL_IS_WINDOW (window));
1532 terminal_return_if_fail (TERMINAL_IS_SCREEN (widget));
1533
1534 /* check */
1535 if (G_LIKELY (info == TARGET_GTK_NOTEBOOK_TAB))
1536 {
1537 /* get the source notebook (other window) */
1538 notebook = gtk_drag_get_source_widget (context);
1539 terminal_return_if_fail (GTK_IS_NOTEBOOK (notebook));
1540
1541 /* get the dragged screen: selection_data's data is a (GtkWidget **) screen */
1542 memcpy (&screen, gtk_selection_data_get_data (selection_data), sizeof (screen));
1543 if (!TERMINAL_IS_SCREEN (screen))
1544 goto leave;
1545
1546 /* leave if we dropped in the same screen and there is only one
1547 * page in the notebook (window will close before we insert) */
1548 if (gtk_notebook_get_n_pages (GTK_NOTEBOOK (notebook)) < 2 && screen == widget)
1549 goto leave;
1550
1551 /* figure out where to insert the tab in the notebook */
1552 n_pages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->priv->notebook));
1553 for (i = 0; i < n_pages; i++)
1554 {
1555 /* get the child label */
1556 GtkAllocation allocation;
1557 GtkWidget *child = gtk_notebook_get_nth_page (GTK_NOTEBOOK (window->priv->notebook), i);
1558 GtkWidget *label = gtk_notebook_get_tab_label (GTK_NOTEBOOK (window->priv->notebook), child);
1559 gtk_widget_get_allocation (label, &allocation);
1560
1561 /* break if we have a matching drop position */
1562 if (x < (allocation.x + allocation.width / 2))
1563 break;
1564 }
1565
1566 if (notebook == window->priv->notebook)
1567 {
1568 /* if we're in the same notebook, don't risk anything and do a
1569 * simple reorder */
1570 gtk_notebook_reorder_child (GTK_NOTEBOOK (notebook), screen, i);
1571 }
1572 else
1573 {
1574 /* take a reference */
1575 g_object_ref (G_OBJECT (screen));
1576 g_object_ref (G_OBJECT (window));
1577
1578 /* remove the document from the source notebook */
1579 gtk_notebook_detach_tab (GTK_NOTEBOOK (notebook), screen);
1580
1581 /* add the screen to the new window */
1582 terminal_window_add (window, TERMINAL_SCREEN (screen));
1583
1584 /* move the child to the correct position */
1585 gtk_notebook_reorder_child (GTK_NOTEBOOK (window->priv->notebook), screen, i);
1586
1587 /* release reference */
1588 g_object_unref (G_OBJECT (screen));
1589 g_object_unref (G_OBJECT (window));
1590 }
1591
1592 /* looks like everything worked out */
1593 succeed = TRUE;
1594 }
1595
1596 /* finish the drag */
1597 leave:
1598 gtk_drag_finish (context, succeed, FALSE, time);
1599 }
1600
1601
1602
1603 static GtkNotebook*
terminal_window_notebook_create_window(GtkNotebook * notebook,GtkWidget * child,gint x,gint y,TerminalWindow * window)1604 terminal_window_notebook_create_window (GtkNotebook *notebook,
1605 GtkWidget *child,
1606 gint x,
1607 gint y,
1608 TerminalWindow *window)
1609 {
1610 terminal_return_val_if_fail (TERMINAL_IS_WINDOW (window), NULL);
1611 terminal_return_val_if_fail (TERMINAL_IS_SCREEN (child), NULL);
1612 terminal_return_val_if_fail (notebook == GTK_NOTEBOOK (window->priv->notebook), NULL);
1613
1614 /* only create new window when there are more then 2 tabs (bug #2686) */
1615 if (gtk_notebook_get_n_pages (notebook) >= 2)
1616 {
1617 /* take a reference */
1618 g_object_ref (G_OBJECT (child));
1619
1620 /* remove screen from active window */
1621 gtk_notebook_detach_tab (notebook, child);
1622
1623 /* create new window with the screen */
1624 g_signal_emit (G_OBJECT (window), window_signals[NEW_WINDOW_WITH_SCREEN], 0, TERMINAL_SCREEN (child), x, y);
1625
1626 /* release our reference */
1627 g_object_unref (G_OBJECT (child));
1628
1629 /* update actions */
1630 terminal_window_update_actions (window);
1631 }
1632
1633 return NULL;
1634 }
1635
1636
1637
1638 static GtkWidget*
terminal_window_get_context_menu(TerminalScreen * screen,TerminalWindow * window)1639 terminal_window_get_context_menu (TerminalScreen *screen,
1640 TerminalWindow *window)
1641 {
1642 GtkWidget *popup = NULL;
1643
1644 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
1645 if (G_LIKELY (screen == window->priv->active))
1646 popup = gtk_ui_manager_get_widget (window->priv->ui_manager, "/popup-menu");
1647 G_GNUC_END_IGNORE_DEPRECATIONS
1648
1649 return popup;
1650 }
1651
1652
1653
1654 static void
terminal_window_notify_title(TerminalScreen * screen,GParamSpec * pspec,TerminalWindow * window)1655 terminal_window_notify_title (TerminalScreen *screen,
1656 GParamSpec *pspec,
1657 TerminalWindow *window)
1658 {
1659 gchar *title;
1660
1661 /* update window title */
1662 if (screen == window->priv->active)
1663 {
1664 title = terminal_screen_get_title (window->priv->active);
1665 gtk_window_set_title (GTK_WINDOW (window), title);
1666 g_free (title);
1667 }
1668 }
1669
1670
1671
1672 static void
terminal_window_action_set_encoding(GtkAction * action,const gchar * charset,TerminalWindow * window)1673 terminal_window_action_set_encoding (GtkAction *action,
1674 const gchar *charset,
1675 TerminalWindow *window)
1676 {
1677 const gchar *new;
1678
1679 if (G_LIKELY (window->priv->active != NULL))
1680 {
1681 /* set the charset */
1682 terminal_screen_set_encoding (window->priv->active, charset);
1683
1684 /* update menu */
1685 new = terminal_screen_get_encoding (window->priv->active);
1686 terminal_encoding_action_set_charset (action, new);
1687 }
1688 }
1689
1690
1691
1692 static gchar*
terminal_window_get_working_directory(TerminalWindow * window)1693 terminal_window_get_working_directory (TerminalWindow *window)
1694 {
1695 gchar *default_dir;
1696 gboolean use_default_dir;
1697
1698 g_object_get (G_OBJECT (window->priv->preferences),
1699 "use-default-working-dir", &use_default_dir,
1700 "default-working-dir", &default_dir,
1701 NULL);
1702
1703 if (use_default_dir && g_strcmp0 (default_dir, "") != 0)
1704 return default_dir;
1705
1706 if (G_LIKELY (window->priv->active != NULL))
1707 return g_strdup (terminal_screen_get_working_directory (window->priv->active));
1708
1709 return NULL;
1710 }
1711
1712
1713
1714 static void
terminal_window_action_new_tab(GtkAction * action,TerminalWindow * window)1715 terminal_window_action_new_tab (GtkAction *action,
1716 TerminalWindow *window)
1717 {
1718 TerminalScreen *terminal = TERMINAL_SCREEN (g_object_new (TERMINAL_TYPE_SCREEN, NULL));
1719 gchar *directory = terminal_window_get_working_directory (window);
1720
1721 if (directory != NULL)
1722 {
1723 terminal_screen_set_working_directory (terminal, directory);
1724 g_free (directory);
1725 }
1726
1727 terminal_window_add (window, terminal);
1728 terminal_screen_launch_child (terminal);
1729 }
1730
1731
1732
1733 static void
terminal_window_action_new_window(GtkAction * action,TerminalWindow * window)1734 terminal_window_action_new_window (GtkAction *action,
1735 TerminalWindow *window)
1736 {
1737 gchar *directory = terminal_window_get_working_directory (window);
1738
1739 if (directory != NULL)
1740 {
1741 g_signal_emit (G_OBJECT (window), window_signals[NEW_WINDOW], 0, directory);
1742 g_free (directory);
1743 }
1744 }
1745
1746
1747
1748 static void
terminal_window_action_undo_close_tab(GtkAction * action,TerminalWindow * window)1749 terminal_window_action_undo_close_tab (GtkAction *action,
1750 TerminalWindow *window)
1751 {
1752 TerminalScreen *terminal;
1753 TerminalTabAttr *tab_attr;
1754 GtkWidget *current = GTK_WIDGET (window->priv->active);
1755
1756 if (G_UNLIKELY (g_queue_is_empty (window->priv->closed_tabs_list)))
1757 return;
1758
1759 /* get info on the last closed tab and remove it from the list */
1760 tab_attr = g_queue_pop_tail (window->priv->closed_tabs_list);
1761
1762 terminal = terminal_screen_new (tab_attr, window->priv->grid_width, window->priv->grid_height);
1763 terminal_window_add (window, terminal);
1764
1765 /* restore tab title color */
1766 if (tab_attr->color_title != NULL)
1767 terminal_screen_set_custom_title_color (terminal, tab_attr->color_title);
1768
1769 /* restore tab position */
1770 gtk_notebook_reorder_child (GTK_NOTEBOOK (window->priv->notebook), GTK_WIDGET (terminal), tab_attr->position);
1771
1772 /* restore tab focus if the unclosed one wasn't active when it was closed */
1773 if (!tab_attr->active)
1774 {
1775 gint page_num = gtk_notebook_page_num (GTK_NOTEBOOK (window->priv->notebook), current);
1776 gtk_notebook_set_current_page (GTK_NOTEBOOK (window->priv->notebook), page_num);
1777 }
1778
1779 /* free info */
1780 terminal_tab_attr_free (tab_attr);
1781
1782 terminal_window_update_actions (window);
1783 terminal_screen_launch_child (terminal);
1784 }
1785
1786
1787
1788 static void
terminal_window_action_detach_tab(GtkAction * action,TerminalWindow * window)1789 terminal_window_action_detach_tab (GtkAction *action,
1790 TerminalWindow *window)
1791 {
1792 if (G_LIKELY (window->priv->active != NULL))
1793 terminal_window_notebook_create_window (GTK_NOTEBOOK (window->priv->notebook),
1794 GTK_WIDGET (window->priv->active),
1795 -1, -1, window);
1796 }
1797
1798
1799
1800 static void
terminal_window_action_close_tab(GtkAction * action,TerminalWindow * window)1801 terminal_window_action_close_tab (GtkAction *action,
1802 TerminalWindow *window)
1803 {
1804 if (G_LIKELY (window->priv->active != NULL))
1805 terminal_window_close_tab_request (window->priv->active, window);
1806 }
1807
1808
1809
1810 static void
terminal_window_action_close_other_tabs(GtkAction * action,TerminalWindow * window)1811 terminal_window_action_close_other_tabs (GtkAction *action,
1812 TerminalWindow *window)
1813 {
1814 GtkNotebook *notebook = GTK_NOTEBOOK (window->priv->notebook);
1815 gint npages, n;
1816
1817 /* move current page to the beginning */
1818 gtk_notebook_reorder_child (notebook, GTK_WIDGET (window->priv->active), 0);
1819
1820 /* remove the others */
1821 npages = gtk_notebook_get_n_pages (notebook);
1822 for (n = npages - 1; n > 0; n--)
1823 terminal_window_close_tab_request (TERMINAL_SCREEN (gtk_notebook_get_nth_page (notebook, n)), window);
1824 }
1825
1826
1827
1828 static void
terminal_window_action_close_window(GtkAction * action,TerminalWindow * window)1829 terminal_window_action_close_window (GtkAction *action,
1830 TerminalWindow *window)
1831 {
1832 /* this will invoke the "delete-event" handler */
1833 gtk_window_close (GTK_WINDOW (window));
1834 }
1835
1836
1837
1838 static void
terminal_window_action_copy(GtkAction * action,TerminalWindow * window)1839 terminal_window_action_copy (GtkAction *action,
1840 TerminalWindow *window)
1841 {
1842 if (G_LIKELY (window->priv->active != NULL))
1843 terminal_screen_copy_clipboard (window->priv->active);
1844 }
1845
1846
1847
1848 #if VTE_CHECK_VERSION (0, 49, 2)
1849 static void
terminal_window_action_copy_html(GtkAction * action,TerminalWindow * window)1850 terminal_window_action_copy_html (GtkAction *action,
1851 TerminalWindow *window)
1852 {
1853 if (G_LIKELY (window->priv->active != NULL))
1854 terminal_screen_copy_clipboard_html (window->priv->active);
1855 }
1856 #endif
1857
1858
1859
1860 static void
terminal_window_action_paste(GtkAction * action,TerminalWindow * window)1861 terminal_window_action_paste (GtkAction *action,
1862 TerminalWindow *window)
1863 {
1864 if (G_LIKELY (window->priv->active != NULL))
1865 terminal_screen_paste_clipboard (window->priv->active);
1866 }
1867
1868
1869
1870 static void
terminal_window_action_paste_selection(GtkAction * action,TerminalWindow * window)1871 terminal_window_action_paste_selection (GtkAction *action,
1872 TerminalWindow *window)
1873 {
1874 if (G_LIKELY (window->priv->active != NULL))
1875 terminal_screen_paste_primary (window->priv->active);
1876 }
1877
1878
1879
1880 static void
terminal_window_action_select_all(GtkAction * action,TerminalWindow * window)1881 terminal_window_action_select_all (GtkAction *action,
1882 TerminalWindow *window)
1883 {
1884 if (G_LIKELY (window->priv->active != NULL))
1885 terminal_screen_select_all (window->priv->active);
1886 }
1887
1888
1889
1890 static void
copy_input_popover_close(GtkWidget * popover,TerminalWindow * window)1891 copy_input_popover_close (GtkWidget *popover,
1892 TerminalWindow *window)
1893 {
1894 /* need for hiding on focus */
1895 if (window->priv->drop_down)
1896 terminal_util_activate_window (GTK_WINDOW (window));
1897
1898 /* close the dialog */
1899 gtk_widget_destroy (popover);
1900
1901 /* focus the terminal */
1902 if (TERMINAL_IS_SCREEN (window->priv->active))
1903 terminal_screen_focus (window->priv->active);
1904 }
1905
1906
1907
1908 static void
copy_input_popover_do_copy(GtkWidget * popover,GtkWidget * entry)1909 copy_input_popover_do_copy (GtkWidget *popover,
1910 GtkWidget *entry)
1911 {
1912 TerminalWindow *window = TERMINAL_WINDOW (gtk_widget_get_toplevel (popover));
1913 GtkNotebook *notebook = GTK_NOTEBOOK (window->priv->notebook);
1914 gint n, npages = gtk_notebook_get_n_pages (notebook);
1915
1916 /* copy the input to all tabs */
1917 for (n = 0; n < npages; n++)
1918 {
1919 TerminalScreen *screen = TERMINAL_SCREEN (gtk_notebook_get_nth_page (notebook, n));
1920 terminal_screen_feed_text (screen, gtk_entry_get_text (GTK_ENTRY (entry)));
1921 }
1922 }
1923
1924
1925
1926 static void
terminal_window_action_copy_input(GtkAction * action,TerminalWindow * window)1927 terminal_window_action_copy_input (GtkAction *action,
1928 TerminalWindow *window)
1929 {
1930 GtkWidget *popover, *button, *box, *label, *entry;
1931
1932 popover = gtk_popover_new (GTK_WIDGET (window->priv->menubar));
1933 gtk_popover_set_position (GTK_POPOVER (popover), GTK_POS_BOTTOM);
1934
1935 box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
1936 gtk_container_set_border_width (GTK_CONTAINER (box), 6);
1937 gtk_container_add (GTK_CONTAINER (popover), box);
1938
1939 label = gtk_label_new_with_mnemonic (_("Copy _Input:"));
1940 gtk_container_add (GTK_CONTAINER (box), label);
1941
1942 entry = gtk_entry_new ();
1943 gtk_widget_set_tooltip_text (entry, _("Enter the text to be copied to all tabs"));
1944 gtk_container_add (GTK_CONTAINER (box), entry);
1945 gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
1946 gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry);
1947 g_signal_connect (G_OBJECT (entry), "activate", G_CALLBACK (copy_input_popover_do_copy), entry);
1948
1949 button = gtk_button_new_from_icon_name ("edit-copy-symbolic", GTK_ICON_SIZE_BUTTON);
1950 gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
1951 gtk_widget_set_tooltip_text (button, _("Copy input"));
1952 gtk_container_add (GTK_CONTAINER (box), button);
1953 g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (copy_input_popover_do_copy), entry);
1954
1955 g_signal_connect (G_OBJECT (popover), "closed", G_CALLBACK (copy_input_popover_close), window);
1956
1957 gtk_widget_show_all (popover);
1958 }
1959
1960
1961
1962 static void
terminal_window_action_prefs_died(gpointer user_data,GObject * where_the_object_was)1963 terminal_window_action_prefs_died (gpointer user_data,
1964 GObject *where_the_object_was)
1965 {
1966 TerminalWindow *window = TERMINAL_WINDOW (user_data);
1967
1968 window->priv->preferences_dialog = NULL;
1969 window->priv->n_child_windows--;
1970
1971 if (window->priv->drop_down)
1972 terminal_util_activate_window (GTK_WINDOW (window));
1973 }
1974
1975
1976
1977 static void
terminal_window_action_prefs(GtkAction * action,TerminalWindow * window)1978 terminal_window_action_prefs (GtkAction *action,
1979 TerminalWindow *window)
1980 {
1981 if (window->priv->preferences_dialog == NULL)
1982 {
1983 window->priv->preferences_dialog = terminal_preferences_dialog_new (window->priv->drop_down, window->priv->drop_down);
1984 if (G_LIKELY (window->priv->preferences_dialog != NULL))
1985 {
1986 window->priv->n_child_windows++;
1987 g_object_weak_ref (G_OBJECT (window->priv->preferences_dialog),
1988 terminal_window_action_prefs_died, window);
1989 }
1990 }
1991
1992 if (window->priv->preferences_dialog != NULL)
1993 {
1994 gtk_window_set_transient_for (GTK_WINDOW (window->priv->preferences_dialog), GTK_WINDOW (window));
1995 gtk_window_present (GTK_WINDOW (window->priv->preferences_dialog));
1996 }
1997 }
1998
1999
2000
2001 static void
terminal_window_action_show_toolbar(GtkToggleAction * action,TerminalWindow * window)2002 terminal_window_action_show_toolbar (GtkToggleAction *action,
2003 TerminalWindow *window)
2004 {
2005 gboolean show;
2006
2007 terminal_return_if_fail (GTK_IS_UI_MANAGER (window->priv->ui_manager));
2008 terminal_return_if_fail (GTK_IS_ACTION_GROUP (window->priv->action_group));
2009
2010 terminal_window_size_push (window);
2011
2012 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
2013 show = gtk_toggle_action_get_active (action);
2014 G_GNUC_END_IGNORE_DEPRECATIONS
2015 if (show)
2016 {
2017 if (window->priv->toolbar == NULL)
2018 {
2019 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
2020 window->priv->toolbar = gtk_ui_manager_get_widget (window->priv->ui_manager, "/main-toolbar");
2021 G_GNUC_END_IGNORE_DEPRECATIONS
2022 gtk_box_pack_start (GTK_BOX (window->priv->vbox), window->priv->toolbar, FALSE, FALSE, 0);
2023 gtk_box_reorder_child (GTK_BOX (window->priv->vbox),
2024 window->priv->toolbar,
2025 window->priv->menubar != NULL ? 1 : 0);
2026 }
2027
2028 gtk_widget_show (window->priv->toolbar);
2029 }
2030 else if (window->priv->toolbar != NULL)
2031 {
2032 gtk_widget_hide (window->priv->toolbar);
2033 }
2034
2035 terminal_window_size_pop (window);
2036 }
2037
2038
2039
2040 static void
terminal_window_action_show_borders(GtkToggleAction * action,TerminalWindow * window)2041 terminal_window_action_show_borders (GtkToggleAction *action,
2042 TerminalWindow *window)
2043 {
2044 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
2045 gboolean decorated = gtk_toggle_action_get_active (action);
2046 G_GNUC_END_IGNORE_DEPRECATIONS
2047
2048 gtk_window_set_decorated (GTK_WINDOW (window), decorated);
2049 }
2050
2051
2052
2053 static void
terminal_window_action_fullscreen(GtkToggleAction * action,TerminalWindow * window)2054 terminal_window_action_fullscreen (GtkToggleAction *action,
2055 TerminalWindow *window)
2056 {
2057 gboolean fullscreen;
2058
2059 if (gtk_widget_get_visible (GTK_WIDGET (window)))
2060 {
2061 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
2062 fullscreen = gtk_toggle_action_get_active (action);
2063 G_GNUC_END_IGNORE_DEPRECATIONS
2064 if (fullscreen)
2065 gtk_window_fullscreen (GTK_WINDOW (window));
2066 else
2067 gtk_window_unfullscreen (GTK_WINDOW (window));
2068 }
2069 }
2070
2071
2072
2073 static void
terminal_window_action_readonly(GtkToggleAction * action,TerminalWindow * window)2074 terminal_window_action_readonly (GtkToggleAction *action,
2075 TerminalWindow *window)
2076 {
2077 gboolean input_enabled;
2078
2079 terminal_return_if_fail (window->priv->active != NULL);
2080
2081 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
2082 input_enabled = !gtk_toggle_action_get_active (action);
2083 if (terminal_screen_get_input_enabled (window->priv->active) != input_enabled)
2084 {
2085 gtk_action_set_sensitive (terminal_window_get_action (window, "reset"), input_enabled);
2086 gtk_action_set_sensitive (terminal_window_get_action (window, "reset-and-clear"), input_enabled);
2087 gtk_action_set_sensitive (terminal_window_get_action (window, "paste"), input_enabled);
2088 gtk_action_set_sensitive (terminal_window_get_action (window, "paste-selection"), input_enabled);
2089 terminal_screen_set_input_enabled (window->priv->active, input_enabled);
2090 }
2091 G_GNUC_END_IGNORE_DEPRECATIONS
2092 }
2093
2094
2095
2096 static void
terminal_window_action_scroll_on_output(GtkToggleAction * action,TerminalWindow * window)2097 terminal_window_action_scroll_on_output (GtkToggleAction *action,
2098 TerminalWindow *window)
2099 {
2100 gboolean scroll_enabled;
2101
2102 terminal_return_if_fail (window->priv->active != NULL);
2103
2104 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
2105 scroll_enabled = gtk_toggle_action_get_active (action);
2106 if (terminal_screen_get_scroll_on_output (window->priv->active) != scroll_enabled)
2107 terminal_screen_set_scroll_on_output (window->priv->active, scroll_enabled);
2108 G_GNUC_END_IGNORE_DEPRECATIONS
2109 }
2110
2111
2112
2113 static void
terminal_window_action_zoom_in(GtkAction * action,TerminalWindow * window)2114 terminal_window_action_zoom_in (GtkAction *action,
2115 TerminalWindow *window)
2116 {
2117 terminal_return_if_fail (window->priv->active != NULL);
2118
2119 if (window->priv->zoom < TERMINAL_ZOOM_LEVEL_MAXIMUM)
2120 {
2121 ++window->priv->zoom;
2122 terminal_window_zoom_update_screens (window);
2123 }
2124 }
2125
2126
2127
2128 static void
terminal_window_action_zoom_out(GtkAction * action,TerminalWindow * window)2129 terminal_window_action_zoom_out (GtkAction *action,
2130 TerminalWindow *window)
2131 {
2132 terminal_return_if_fail (window->priv->active != NULL);
2133
2134 if (window->priv->zoom > TERMINAL_ZOOM_LEVEL_MINIMUM)
2135 {
2136 --window->priv->zoom;
2137 terminal_window_zoom_update_screens (window);
2138 }
2139 }
2140
2141
2142
2143 static void
terminal_window_action_zoom_reset(GtkAction * action,TerminalWindow * window)2144 terminal_window_action_zoom_reset (GtkAction *action,
2145 TerminalWindow *window)
2146 {
2147 terminal_return_if_fail (window->priv->active != NULL);
2148
2149 if (window->priv->zoom != TERMINAL_ZOOM_LEVEL_DEFAULT)
2150 {
2151 window->priv->zoom = TERMINAL_ZOOM_LEVEL_DEFAULT;
2152 terminal_window_zoom_update_screens (window);
2153 }
2154 }
2155
2156
2157
2158 static void
terminal_window_action_prev_tab(GtkAction * action,TerminalWindow * window)2159 terminal_window_action_prev_tab (GtkAction *action,
2160 TerminalWindow *window)
2161 {
2162 terminal_window_switch_tab (GTK_NOTEBOOK (window->priv->notebook), TRUE);
2163 terminal_window_update_actions (window);
2164 }
2165
2166
2167
2168 static void
terminal_window_action_next_tab(GtkAction * action,TerminalWindow * window)2169 terminal_window_action_next_tab (GtkAction *action,
2170 TerminalWindow *window)
2171 {
2172 terminal_window_switch_tab (GTK_NOTEBOOK (window->priv->notebook), FALSE);
2173 terminal_window_update_actions (window);
2174 }
2175
2176
2177
2178 static void
terminal_window_action_last_active_tab(GtkAction * action,TerminalWindow * window)2179 terminal_window_action_last_active_tab (GtkAction *action,
2180 TerminalWindow *window)
2181 {
2182 if (window->priv->last_active != NULL)
2183 {
2184 GtkNotebook *notebook = GTK_NOTEBOOK (window->priv->notebook);
2185 gint page_num = gtk_notebook_page_num (notebook, GTK_WIDGET (window->priv->last_active));
2186 gtk_notebook_set_current_page (notebook, page_num);
2187 terminal_window_update_actions (window);
2188 }
2189 }
2190
2191
2192
2193 static void
terminal_window_action_move_tab_left(GtkAction * action,TerminalWindow * window)2194 terminal_window_action_move_tab_left (GtkAction *action,
2195 TerminalWindow *window)
2196 {
2197 terminal_window_move_tab (GTK_NOTEBOOK (window->priv->notebook), TRUE);
2198 terminal_window_update_actions (window);
2199 }
2200
2201
2202
2203 static void
terminal_window_action_move_tab_right(GtkAction * action,TerminalWindow * window)2204 terminal_window_action_move_tab_right (GtkAction *action,
2205 TerminalWindow *window)
2206 {
2207 terminal_window_move_tab (GTK_NOTEBOOK (window->priv->notebook), FALSE);
2208 terminal_window_update_actions (window);
2209 }
2210
2211
2212
2213 static void
terminal_window_action_goto_tab(GtkRadioAction * action,GtkNotebook * notebook)2214 terminal_window_action_goto_tab (GtkRadioAction *action,
2215 GtkNotebook *notebook)
2216 {
2217 gint page;
2218
2219 terminal_return_if_fail (GTK_IS_NOTEBOOK (notebook));
2220 terminal_return_if_fail (GTK_IS_RADIO_ACTION (action));
2221
2222 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
2223 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2224 {
2225 /* switch to the new page */
2226 page = gtk_radio_action_get_current_value (action);
2227 gtk_notebook_set_current_page (notebook, page);
2228 }
2229 G_GNUC_END_IGNORE_DEPRECATIONS
2230 }
2231
2232
2233
2234 static void
title_popover_close(GtkWidget * popover,TerminalWindow * window)2235 title_popover_close (GtkWidget *popover,
2236 TerminalWindow *window)
2237 {
2238 terminal_return_if_fail (window->priv->title_popover != NULL);
2239
2240 /* need for hiding on focus */
2241 if (window->priv->drop_down)
2242 terminal_util_activate_window (GTK_WINDOW (window));
2243
2244 /* close the dialog */
2245 gtk_widget_destroy (window->priv->title_popover);
2246 window->priv->title_popover = NULL;
2247
2248 /* focus the terminal: bug #13754 */
2249 if (TERMINAL_IS_SCREEN (window->priv->active))
2250 terminal_screen_focus (window->priv->active);
2251 }
2252
2253
2254
2255 static void
title_popover_help(GtkWidget * popover,TerminalWindow * window)2256 title_popover_help (GtkWidget *popover,
2257 TerminalWindow *window)
2258 {
2259 /* open the "Set Title" paragraph in the "Usage" section */
2260 xfce_dialog_show_help (GTK_WINDOW (window), "terminal", "usage#to_change_the_terminal_title", NULL);
2261 }
2262
2263
2264
2265 static void
title_popover_clear(GtkWidget * entry,GtkEntryIconPosition icon_pos)2266 title_popover_clear (GtkWidget *entry,
2267 GtkEntryIconPosition icon_pos)
2268 {
2269 if (icon_pos == GTK_ENTRY_ICON_SECONDARY)
2270 gtk_entry_set_text (GTK_ENTRY (entry), "");
2271 }
2272
2273
2274
2275 static void
terminal_window_action_set_title(GtkAction * action,TerminalWindow * window)2276 terminal_window_action_set_title (GtkAction *action,
2277 TerminalWindow *window)
2278 {
2279 GtkWidget *button;
2280 GtkWidget *box;
2281 GtkWidget *label;
2282 GtkWidget *entry;
2283
2284 terminal_return_if_fail (window->priv->active != NULL);
2285
2286 if (window->priv->title_popover == NULL)
2287 {
2288 if (gtk_notebook_get_show_tabs (GTK_NOTEBOOK (window->priv->notebook)))
2289 {
2290 window->priv->title_popover =
2291 gtk_popover_new (gtk_notebook_get_tab_label (GTK_NOTEBOOK (window->priv->notebook),
2292 GTK_WIDGET (window->priv->active)));
2293 }
2294 else
2295 {
2296 window->priv->title_popover = gtk_popover_new (GTK_WIDGET (window->priv->menubar));
2297 gtk_popover_set_position (GTK_POPOVER (window->priv->title_popover), GTK_POS_BOTTOM);
2298 }
2299
2300 box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
2301 gtk_container_set_border_width (GTK_CONTAINER (box), 6);
2302 gtk_container_add (GTK_CONTAINER (window->priv->title_popover), box);
2303
2304 label = gtk_label_new_with_mnemonic (_("_Title:"));
2305 gtk_box_pack_start (GTK_BOX (box), label, FALSE, TRUE, 0);
2306
2307 entry = gtk_entry_new ();
2308 gtk_widget_set_tooltip_text (entry, _("Enter the title for the current terminal tab"));
2309 gtk_box_pack_start (GTK_BOX (box), entry, TRUE, TRUE, 0);
2310 gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
2311 gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry);
2312 gtk_entry_set_icon_from_icon_name (GTK_ENTRY (entry), GTK_ENTRY_ICON_SECONDARY, "edit-clear");
2313 gtk_entry_set_icon_tooltip_text (GTK_ENTRY (entry), GTK_ENTRY_ICON_SECONDARY, _("Reset"));
2314 g_signal_connect (G_OBJECT (entry), "icon-release", G_CALLBACK (title_popover_clear), NULL);
2315 g_signal_connect (G_OBJECT (entry), "activate", G_CALLBACK (title_popover_close), window);
2316
2317 g_object_bind_property (G_OBJECT (window->priv->active), "custom-title",
2318 G_OBJECT (entry), "text",
2319 G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
2320
2321 button = gtk_button_new_from_icon_name ("help-browser", GTK_ICON_SIZE_BUTTON);
2322 gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
2323 gtk_widget_set_tooltip_text (button, _("Help"));
2324 g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (title_popover_help), window);
2325 gtk_box_pack_start (GTK_BOX (box), button, TRUE, TRUE, 0);
2326
2327 button = gtk_button_new_from_icon_name ("window-close-symbolic", GTK_ICON_SIZE_BUTTON);
2328 gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
2329 gtk_widget_set_tooltip_text (button, _("Close"));
2330 g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (title_popover_close), window);
2331 gtk_box_pack_start (GTK_BOX (box), button, TRUE, TRUE, 0);
2332
2333 g_signal_connect (G_OBJECT (window->priv->title_popover), "closed",
2334 G_CALLBACK (title_popover_close), window);
2335 }
2336
2337 gtk_widget_show_all (window->priv->title_popover);
2338 }
2339
2340
2341
2342 static void
terminal_window_action_set_title_color(GtkAction * action,TerminalWindow * window)2343 terminal_window_action_set_title_color (GtkAction *action,
2344 TerminalWindow *window)
2345 {
2346 GtkWidget *dialog;
2347 gchar *color_string;
2348 GdkRGBA color;
2349 int response;
2350
2351 dialog = gtk_color_chooser_dialog_new (_("Choose title color"), GTK_WINDOW (window));
2352 gtk_dialog_add_button (GTK_DIALOG (dialog), _("_Reset"), GTK_RESPONSE_NO);
2353 response = gtk_dialog_run (GTK_DIALOG (dialog));
2354
2355 if (response == GTK_RESPONSE_OK)
2356 {
2357 gtk_color_chooser_get_rgba (GTK_COLOR_CHOOSER (dialog), &color);
2358 color_string = gdk_rgba_to_string (&color);
2359 terminal_screen_set_custom_title_color (window->priv->active, color_string);
2360 g_free (color_string);
2361 }
2362 else if (response == GTK_RESPONSE_NO)
2363 terminal_screen_set_custom_title_color (window->priv->active, NULL);
2364
2365 gtk_widget_destroy (dialog);
2366 }
2367
2368
2369
2370 static void
terminal_window_action_search_response(GtkWidget * dialog,gint response_id,TerminalWindow * window)2371 terminal_window_action_search_response (GtkWidget *dialog,
2372 gint response_id,
2373 TerminalWindow *window)
2374 {
2375 gboolean can_search;
2376
2377 terminal_return_if_fail (TERMINAL_IS_WINDOW (window));
2378 terminal_return_if_fail (TERMINAL_IS_SEARCH_DIALOG (dialog));
2379 terminal_return_if_fail (TERMINAL_IS_SCREEN (window->priv->active));
2380 terminal_return_if_fail (window->priv->search_dialog == dialog);
2381
2382 if (response_id == TERMINAL_RESPONSE_SEARCH_NEXT)
2383 terminal_window_action_search_next (NULL, window);
2384 else if (response_id == TERMINAL_RESPONSE_SEARCH_PREV)
2385 terminal_window_action_search_prev (NULL, window);
2386 else
2387 {
2388 /* need for hiding on focus */
2389 if (window->priv->drop_down)
2390 terminal_util_activate_window (GTK_WINDOW (window));
2391
2392 /* hide dialog */
2393 window->priv->n_child_windows--;
2394 gtk_widget_hide (dialog);
2395 }
2396
2397 /* update actions */
2398 can_search = terminal_screen_search_has_gregex (window->priv->active);
2399 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
2400 gtk_action_set_sensitive (window->priv->action_search_next, can_search);
2401 gtk_action_set_sensitive (window->priv->action_search_prev, can_search);
2402 G_GNUC_END_IGNORE_DEPRECATIONS
2403 }
2404
2405
2406
2407 static void
terminal_window_action_search(GtkAction * action,TerminalWindow * window)2408 terminal_window_action_search (GtkAction *action,
2409 TerminalWindow *window)
2410 {
2411 if (window->priv->search_dialog == NULL)
2412 {
2413 window->priv->search_dialog = terminal_search_dialog_new (GTK_WINDOW (window));
2414 g_signal_connect (G_OBJECT (window->priv->search_dialog), "response",
2415 G_CALLBACK (terminal_window_action_search_response), window);
2416 g_signal_connect (G_OBJECT (window->priv->search_dialog), "delete-event",
2417 G_CALLBACK (gtk_widget_hide_on_delete), NULL);
2418 }
2419
2420 /* increase child counter */
2421 if (!gtk_widget_get_visible (window->priv->search_dialog))
2422 window->priv->n_child_windows++;
2423
2424 terminal_search_dialog_present (TERMINAL_SEARCH_DIALOG (window->priv->search_dialog));
2425 }
2426
2427
2428
2429 static gboolean
prepare_regex(TerminalWindow * window)2430 prepare_regex (TerminalWindow *window)
2431 {
2432 VteRegex *regex;
2433 GError *error = NULL;
2434 gboolean wrap_around;
2435
2436 regex = terminal_search_dialog_get_regex (TERMINAL_SEARCH_DIALOG (window->priv->search_dialog), &error);
2437 if (G_LIKELY (error == NULL))
2438 {
2439 wrap_around = terminal_search_dialog_get_wrap_around (TERMINAL_SEARCH_DIALOG (window->priv->search_dialog));
2440 terminal_screen_search_set_gregex (window->priv->active, regex, wrap_around);
2441 if (regex != NULL)
2442 vte_regex_unref (regex);
2443
2444 return TRUE;
2445 }
2446
2447 xfce_dialog_show_error (GTK_WINDOW (window->priv->search_dialog), error,
2448 _("Failed to create the regular expression"));
2449 g_error_free (error);
2450
2451 return FALSE;
2452 }
2453
2454
2455
2456 static void
terminal_window_action_search_next(GtkAction * action,TerminalWindow * window)2457 terminal_window_action_search_next (GtkAction *action,
2458 TerminalWindow *window)
2459 {
2460 if (prepare_regex (window))
2461 terminal_screen_search_find_next (window->priv->active);
2462 }
2463
2464
2465
2466 static void
terminal_window_action_search_prev(GtkAction * action,TerminalWindow * window)2467 terminal_window_action_search_prev (GtkAction *action,
2468 TerminalWindow *window)
2469 {
2470 if (prepare_regex (window))
2471 terminal_screen_search_find_previous (window->priv->active);
2472 }
2473
2474
2475
2476 static void
terminal_window_action_save_contents(GtkAction * action,TerminalWindow * window)2477 terminal_window_action_save_contents (GtkAction *action,
2478 TerminalWindow *window)
2479 {
2480 GtkWidget *dialog;
2481 GFile *file;
2482 GOutputStream *stream;
2483 GError *error = NULL;
2484 gchar *filename_uri;
2485 gint response;
2486
2487 terminal_return_if_fail (window->priv->active != NULL);
2488
2489 dialog = gtk_file_chooser_dialog_new (_("Save contents..."),
2490 GTK_WINDOW (window),
2491 GTK_FILE_CHOOSER_ACTION_SAVE,
2492 _("_Cancel"), GTK_RESPONSE_CANCEL,
2493 _("_Save"), GTK_RESPONSE_ACCEPT,
2494 NULL);
2495 gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
2496
2497 /* save to current working directory */
2498 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog),
2499 terminal_screen_get_working_directory (TERMINAL_SCREEN (window->priv->active)));
2500
2501 gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (window));
2502 gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
2503 gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE);
2504
2505 gtk_widget_show_all (dialog);
2506
2507 response = gtk_dialog_run (GTK_DIALOG (dialog));
2508 if (response != GTK_RESPONSE_ACCEPT)
2509 {
2510 gtk_widget_destroy (dialog);
2511 return;
2512 }
2513
2514 filename_uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog));
2515 gtk_widget_destroy (dialog);
2516
2517 if (filename_uri == NULL)
2518 return;
2519
2520 file = g_file_new_for_uri (filename_uri);
2521 stream = G_OUTPUT_STREAM (g_file_replace (file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, &error));
2522 if (stream)
2523 {
2524 terminal_screen_save_contents (TERMINAL_SCREEN (window->priv->active), stream, error);
2525 g_object_unref (stream);
2526 }
2527
2528 if (error)
2529 {
2530 xfce_dialog_show_error (GTK_WINDOW (window), error, _("Failed to save terminal contents"));
2531 g_error_free (error);
2532 }
2533
2534 g_object_unref (file);
2535 g_free (filename_uri);
2536 }
2537
2538
2539
2540 static void
terminal_window_action_reset(GtkAction * action,TerminalWindow * window)2541 terminal_window_action_reset (GtkAction *action,
2542 TerminalWindow *window)
2543 {
2544 if (G_LIKELY (window->priv->active != NULL))
2545 terminal_screen_reset (window->priv->active, FALSE);
2546 }
2547
2548
2549
2550 static void
terminal_window_action_reset_and_clear(GtkAction * action,TerminalWindow * window)2551 terminal_window_action_reset_and_clear (GtkAction *action,
2552 TerminalWindow *window)
2553 {
2554 if (G_LIKELY (window->priv->active != NULL))
2555 {
2556 terminal_screen_reset (window->priv->active, TRUE);
2557 terminal_window_update_actions (window);
2558 }
2559 }
2560
2561
2562
2563 static void
terminal_window_action_contents(GtkAction * action,TerminalWindow * window)2564 terminal_window_action_contents (GtkAction *action,
2565 TerminalWindow *window)
2566 {
2567 /* open the Terminal user manual */
2568 xfce_dialog_show_help (GTK_WINDOW (window), "terminal", NULL, NULL);
2569 }
2570
2571
2572
2573 static void
terminal_window_action_about(GtkAction * action,TerminalWindow * window)2574 terminal_window_action_about (GtkAction *action,
2575 TerminalWindow *window)
2576 {
2577 /* display the about dialog */
2578 terminal_util_show_about_dialog (GTK_WINDOW (window));
2579 }
2580
2581
2582
2583 static void
terminal_window_zoom_update_screens(TerminalWindow * window)2584 terminal_window_zoom_update_screens (TerminalWindow *window)
2585 {
2586 gint npages, n;
2587 TerminalScreen *screen;
2588 GtkAction *action;
2589
2590 terminal_return_if_fail (GTK_IS_NOTEBOOK (window->priv->notebook));
2591
2592 /* walk the tabs */
2593 npages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->priv->notebook));
2594 for (n = 0; n < npages; n++)
2595 {
2596 screen = TERMINAL_SCREEN (gtk_notebook_get_nth_page (GTK_NOTEBOOK (window->priv->notebook), n));
2597 terminal_screen_update_font (screen);
2598 }
2599
2600 /* update zoom actions */
2601 action = terminal_window_get_action (window, "zoom-in");
2602 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
2603 if (window->priv->zoom == TERMINAL_ZOOM_LEVEL_MAXIMUM)
2604 gtk_action_set_sensitive (action, FALSE);
2605 else if (!gtk_action_is_sensitive (action))
2606 gtk_action_set_sensitive (action, TRUE);
2607
2608 action = terminal_window_get_action (window, "zoom-out");
2609 if (window->priv->zoom == TERMINAL_ZOOM_LEVEL_MINIMUM)
2610 gtk_action_set_sensitive (action, FALSE);
2611 else if (!gtk_action_is_sensitive (action))
2612 gtk_action_set_sensitive (action, TRUE);
2613 G_GNUC_END_IGNORE_DEPRECATIONS
2614 }
2615
2616
2617
2618 static void
terminal_window_switch_tab(GtkNotebook * notebook,gboolean switch_left)2619 terminal_window_switch_tab (GtkNotebook *notebook,
2620 gboolean switch_left)
2621 {
2622 gint page_num;
2623 gint n_pages;
2624
2625 page_num = gtk_notebook_get_current_page (notebook);
2626 n_pages = gtk_notebook_get_n_pages (notebook);
2627 gtk_notebook_set_current_page (notebook,
2628 (switch_left ? page_num - 1 : page_num + 1) % n_pages);
2629 }
2630
2631
2632
2633 static void
terminal_window_move_tab(GtkNotebook * notebook,gboolean move_left)2634 terminal_window_move_tab (GtkNotebook *notebook,
2635 gboolean move_left)
2636 {
2637 gint page_num;
2638 gint last_page;
2639 GtkWidget *page;
2640
2641 page_num = gtk_notebook_get_current_page (notebook);
2642 last_page = gtk_notebook_get_n_pages (notebook) - 1;
2643 page = gtk_notebook_get_nth_page (notebook, page_num);
2644
2645 if (move_left)
2646 gtk_notebook_reorder_child (notebook, page,
2647 page_num == 0 ? last_page : page_num - 1);
2648 else
2649 gtk_notebook_reorder_child (notebook, page,
2650 page_num == last_page ? 0 : page_num + 1);
2651 }
2652
2653
2654
2655 static void
terminal_window_toggle_menubar(GtkWidget * widget,TerminalWindow * window)2656 terminal_window_toggle_menubar (GtkWidget *widget,
2657 TerminalWindow *window)
2658 {
2659 terminal_return_if_fail (TERMINAL_IS_WINDOW (window));
2660
2661 terminal_window_size_push (window);
2662 if (terminal_window_get_menubar_height (window) == 0)
2663 gtk_widget_show (window->priv->menubar);
2664 terminal_window_size_pop (window);
2665 }
2666
2667
2668
2669 static void
terminal_window_menubar_deactivate(GtkWidget * widget,TerminalWindow * window)2670 terminal_window_menubar_deactivate (GtkWidget *widget,
2671 TerminalWindow *window)
2672 {
2673 GtkAction *action;
2674
2675 terminal_return_if_fail (TERMINAL_IS_WINDOW (window));
2676
2677 action = terminal_window_get_action (window, "show-menubar");
2678 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
2679 terminal_window_action_show_menubar (GTK_TOGGLE_ACTION (action), window);
2680 G_GNUC_END_IGNORE_DEPRECATIONS
2681 }
2682
2683
2684
2685 static void
terminal_window_do_close_tab(TerminalScreen * screen,TerminalWindow * window)2686 terminal_window_do_close_tab (TerminalScreen *screen,
2687 TerminalWindow *window)
2688 {
2689 GtkNotebook *notebook = GTK_NOTEBOOK (window->priv->notebook);
2690
2691 /* store attrs of the tab being closed */
2692 TerminalTabAttr *tab_attr = terminal_tab_attr_new ();
2693 tab_attr->active = (screen == window->priv->active);
2694 tab_attr->position = gtk_notebook_page_num (notebook, GTK_WIDGET (screen));
2695 tab_attr->directory = g_strdup (terminal_screen_get_working_directory (screen));
2696 if (IS_STRING (terminal_screen_get_custom_title (screen)))
2697 tab_attr->title = g_strdup (terminal_screen_get_custom_title (screen));
2698 if (IS_STRING (terminal_screen_get_custom_fg_color (screen)))
2699 tab_attr->color_text = g_strdup (terminal_screen_get_custom_fg_color (screen));
2700 if (IS_STRING (terminal_screen_get_custom_bg_color (screen)))
2701 tab_attr->color_bg = g_strdup (terminal_screen_get_custom_bg_color (screen));
2702 if (IS_STRING (terminal_screen_get_custom_title_color (screen)))
2703 tab_attr->color_title = g_strdup (terminal_screen_get_custom_title_color (screen));
2704 g_queue_push_tail (window->priv->closed_tabs_list, tab_attr);
2705
2706 /* switch to the previously active tab */
2707 if (screen == window->priv->active && window->priv->last_active != NULL)
2708 {
2709 gint page_num = gtk_notebook_page_num (notebook, GTK_WIDGET (window->priv->last_active));
2710 gtk_notebook_set_current_page (notebook, page_num);
2711 }
2712
2713 gtk_widget_destroy (GTK_WIDGET (screen));
2714 }
2715
2716
2717
2718 /**
2719 * terminal_window_new:
2720 * @fullscreen: Whether to set the window to fullscreen.
2721 * @menubar : Visibility setting for the menubar.
2722 * @borders : Visibility setting for the window borders.
2723 * @toolbar : Visibility setting for the toolbar.
2724 *
2725 * Return value:
2726 **/
2727 GtkWidget*
terminal_window_new(const gchar * role,gboolean fullscreen,TerminalVisibility menubar,TerminalVisibility borders,TerminalVisibility toolbar)2728 terminal_window_new (const gchar *role,
2729 gboolean fullscreen,
2730 TerminalVisibility menubar,
2731 TerminalVisibility borders,
2732 TerminalVisibility toolbar)
2733 {
2734 TerminalWindow *window;
2735 GtkAction *action;
2736 gboolean show_menubar;
2737 gboolean show_toolbar;
2738 gboolean show_borders;
2739
2740 window = g_object_new (TERMINAL_TYPE_WINDOW, "role", role, NULL);
2741
2742 /* read default preferences */
2743 g_object_get (G_OBJECT (window->priv->preferences),
2744 "misc-menubar-default", &show_menubar,
2745 "misc-toolbar-default", &show_toolbar,
2746 "misc-borders-default", &show_borders,
2747 NULL);
2748
2749 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
2750 /* setup full screen */
2751 if (fullscreen && gtk_action_is_sensitive (window->priv->action_fullscreen))
2752 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (window->priv->action_fullscreen), TRUE);
2753
2754 /* setup menubar visibility */
2755 if (G_LIKELY (menubar != TERMINAL_VISIBILITY_DEFAULT))
2756 show_menubar = (menubar == TERMINAL_VISIBILITY_SHOW);
2757 action = terminal_window_get_action (window, "show-menubar");
2758 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), show_menubar);
2759 terminal_window_action_show_menubar (GTK_TOGGLE_ACTION (action), window);
2760
2761 /* setup toolbar visibility */
2762 if (G_LIKELY (toolbar != TERMINAL_VISIBILITY_DEFAULT))
2763 show_toolbar = (toolbar == TERMINAL_VISIBILITY_SHOW);
2764 action = terminal_window_get_action (window, "show-toolbar");
2765 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), show_toolbar);
2766
2767 /* setup borders visibility */
2768 if (G_LIKELY (borders != TERMINAL_VISIBILITY_DEFAULT))
2769 show_borders = (borders == TERMINAL_VISIBILITY_SHOW);
2770 action = terminal_window_get_action (window, "show-borders");
2771 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), show_borders);
2772 G_GNUC_END_IGNORE_DEPRECATIONS
2773
2774 /* property that is not suitable for init */
2775 g_object_bind_property (G_OBJECT (window->priv->preferences), "misc-tab-position",
2776 G_OBJECT (window->priv->notebook), "tab-pos",
2777 G_BINDING_SYNC_CREATE);
2778
2779 return GTK_WIDGET (window);
2780 }
2781
2782
2783
2784 /**
2785 * terminal_window_add:
2786 * @window : A #TerminalWindow.
2787 * @screen : A #TerminalScreen.
2788 **/
2789 void
terminal_window_add(TerminalWindow * window,TerminalScreen * screen)2790 terminal_window_add (TerminalWindow *window,
2791 TerminalScreen *screen)
2792 {
2793 GtkWidget *label;
2794 gint page, position = -1;
2795 gboolean adjacent;
2796
2797 terminal_return_if_fail (TERMINAL_IS_WINDOW (window));
2798 terminal_return_if_fail (TERMINAL_IS_SCREEN (screen));
2799
2800 /* show the terminal screen first: see bug #13263*/
2801 gtk_widget_show (GTK_WIDGET (screen));
2802
2803 /* create the tab label */
2804 label = terminal_screen_get_tab_label (screen);
2805
2806 /* determine the tab position */
2807 g_object_get (G_OBJECT (window->priv->preferences), "misc-new-tab-adjacent", &adjacent, NULL);
2808 if (G_UNLIKELY (adjacent))
2809 position = gtk_notebook_page_num (GTK_NOTEBOOK (window->priv->notebook), GTK_WIDGET (window->priv->active)) + 1;
2810
2811 page = gtk_notebook_insert_page (GTK_NOTEBOOK (window->priv->notebook), GTK_WIDGET (screen), label, position);
2812 gtk_container_child_set (GTK_CONTAINER (window->priv->notebook), GTK_WIDGET (screen), "tab-expand", TRUE, NULL);
2813 gtk_container_child_set (GTK_CONTAINER (window->priv->notebook), GTK_WIDGET (screen), "tab-fill", TRUE, NULL);
2814
2815 /* allow tab sorting and dnd */
2816 gtk_notebook_set_tab_reorderable (GTK_NOTEBOOK (window->priv->notebook), GTK_WIDGET (screen), TRUE);
2817 gtk_notebook_set_tab_detachable (GTK_NOTEBOOK (window->priv->notebook), GTK_WIDGET (screen), TRUE);
2818
2819 /* update scrollbar visibility */
2820 if (window->priv->scrollbar_visibility != TERMINAL_VISIBILITY_DEFAULT)
2821 terminal_screen_update_scrolling_bar (screen);
2822
2823 /* switch to the new tab */
2824 gtk_notebook_set_current_page (GTK_NOTEBOOK (window->priv->notebook), page);
2825
2826 /* focus the terminal */
2827 terminal_screen_focus (screen);
2828 }
2829
2830
2831
2832 /**
2833 * terminal_window_get_active:
2834 * @window : a #TerminalWindow.
2835 *
2836 * Returns the active #TerminalScreen for @window
2837 * or %NULL.
2838 *
2839 * Return value: the active #TerminalScreen for @window.
2840 **/
2841 TerminalScreen*
terminal_window_get_active(TerminalWindow * window)2842 terminal_window_get_active (TerminalWindow *window)
2843 {
2844 terminal_return_val_if_fail (TERMINAL_IS_WINDOW (window), NULL);
2845 return window->priv->active;
2846 }
2847
2848
2849
2850 /**
2851 * terminal_window_notebook_show_tabs:
2852 * @window : A #TerminalWindow.
2853 **/
2854 void
terminal_window_notebook_show_tabs(TerminalWindow * window)2855 terminal_window_notebook_show_tabs (TerminalWindow *window)
2856 {
2857 GtkNotebook *notebook = GTK_NOTEBOOK (window->priv->notebook);
2858 gboolean show_tabs = TRUE;
2859 gint npages;
2860
2861 terminal_return_if_fail (TERMINAL_IS_WINDOW (window));
2862
2863 /* check preferences */
2864 npages = gtk_notebook_get_n_pages (notebook);
2865 if (npages < 2)
2866 {
2867 g_object_get (G_OBJECT (window->priv->preferences),
2868 window->priv->drop_down ? "dropdown-always-show-tabs" :
2869 "misc-always-show-tabs", &show_tabs, NULL);
2870 }
2871
2872 /* set the visibility of the tabs */
2873 if (gtk_notebook_get_show_tabs (notebook) != show_tabs)
2874 {
2875 /* store size */
2876 terminal_window_size_push (window);
2877
2878 /* show or hide the tabs */
2879 gtk_notebook_set_show_tabs (notebook, show_tabs);
2880
2881 /* update the window geometry */
2882 terminal_window_size_pop (window);
2883 }
2884 }
2885
2886
2887
2888 /**
2889 * terminal_window_get_restart_command:
2890 * @window : A #TerminalWindow.
2891 *
2892 * Return value: A list of strings, which are required to
2893 * restart the window properly with all tabs
2894 * and settings. The strings and the list itself
2895 * need to be freed afterwards.
2896 **/
2897 GSList*
terminal_window_get_restart_command(TerminalWindow * window)2898 terminal_window_get_restart_command (TerminalWindow *window)
2899 {
2900 const gchar *role;
2901 GtkAction *action;
2902 GdkScreen *gscreen;
2903 GList *children, *lp;
2904 GSList *result = NULL;
2905 glong w;
2906 glong h;
2907
2908 terminal_return_val_if_fail (TERMINAL_IS_WINDOW (window), NULL);
2909
2910 if (G_LIKELY (window->priv->active != NULL))
2911 {
2912 terminal_screen_get_size (window->priv->active, &w, &h);
2913 result = g_slist_prepend (result, g_strdup_printf ("--geometry=%ldx%ld", w, h));
2914 }
2915
2916 gscreen = gtk_window_get_screen (GTK_WINDOW (window));
2917 if (G_LIKELY (gscreen != NULL))
2918 {
2919 result = g_slist_prepend (result, g_strdup ("--display"));
2920 result = g_slist_prepend (result, g_strdup (gdk_display_get_name (gdk_screen_get_display (gscreen))));
2921 }
2922
2923 role = gtk_window_get_role (GTK_WINDOW (window));
2924 if (G_LIKELY (role != NULL))
2925 result = g_slist_prepend (result, g_strdup_printf ("--role=%s", role));
2926
2927 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
2928 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (window->priv->action_fullscreen)))
2929 result = g_slist_prepend (result, g_strdup ("--fullscreen"));
2930
2931 action = terminal_window_get_action (window, "show-menubar");
2932 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2933 result = g_slist_prepend (result, g_strdup ("--show-menubar"));
2934 else
2935 result = g_slist_prepend (result, g_strdup ("--hide-menubar"));
2936
2937 action = terminal_window_get_action (window, "show-borders");
2938 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2939 result = g_slist_prepend (result, g_strdup ("--show-borders"));
2940 else
2941 result = g_slist_prepend (result, g_strdup ("--hide-borders"));
2942
2943 action = terminal_window_get_action (window, "show-toolbar");
2944 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2945 result = g_slist_prepend (result, g_strdup ("--show-toolbar"));
2946 else
2947 result = g_slist_prepend (result, g_strdup ("--hide-toolbar"));
2948 G_GNUC_END_IGNORE_DEPRECATIONS
2949
2950 if (window->priv->zoom != TERMINAL_ZOOM_LEVEL_DEFAULT)
2951 result = g_slist_prepend (result, g_strdup_printf ("--zoom=%d", window->priv->zoom));
2952 if (window->priv->font != NULL)
2953 result = g_slist_prepend (result, g_strdup_printf ("--font=%s", window->priv->font));
2954
2955 /* set restart commands of the tabs */
2956 children = gtk_container_get_children (GTK_CONTAINER (window->priv->notebook));
2957 for (lp = children; lp != NULL; lp = lp->next)
2958 {
2959 if (lp != children)
2960 result = g_slist_prepend (result, g_strdup ("--tab"));
2961 if (window->priv->active == lp->data)
2962 result = g_slist_prepend (result, g_strdup ("--active-tab"));
2963 result = g_slist_concat (terminal_screen_get_restart_command (lp->data), result);
2964 }
2965 g_list_free (children);
2966
2967 return g_slist_reverse (result);
2968 }
2969
2970
2971
2972 /**
2973 * terminal_window_set_grid_size:
2974 * @window : A #TerminalWindow.
2975 * @width : Window width.
2976 * @height : Window height.
2977 **/
2978 void
terminal_window_set_grid_size(TerminalWindow * window,glong width,glong height)2979 terminal_window_set_grid_size (TerminalWindow *window,
2980 glong width,
2981 glong height)
2982 {
2983 window->priv->grid_width = width;
2984 window->priv->grid_height = height;
2985 }
2986
2987
2988
2989 /**
2990 * terminal_window_has_children:
2991 * @window : A #TerminalWindow.
2992 **/
2993 gboolean
terminal_window_has_children(TerminalWindow * window)2994 terminal_window_has_children (TerminalWindow *window)
2995 {
2996 return window->priv->n_child_windows != 0;
2997 }
2998
2999
3000
3001 /**
3002 * terminal_window_get_preferences:
3003 * @window : A #TerminalWindow.
3004 **/
3005 GObject*
terminal_window_get_preferences(TerminalWindow * window)3006 terminal_window_get_preferences (TerminalWindow *window)
3007 {
3008 return G_OBJECT (window->priv->preferences);
3009 }
3010
3011
3012
3013 /**
3014 * terminal_window_get_vbox:
3015 * @window : A #TerminalWindow.
3016 **/
3017 GtkWidget*
terminal_window_get_vbox(TerminalWindow * window)3018 terminal_window_get_vbox (TerminalWindow *window)
3019 {
3020 return window->priv->vbox;
3021 }
3022
3023
3024
3025 /**
3026 * terminal_window_get_notebook:
3027 * @window : A #TerminalWindow.
3028 **/
3029 GtkWidget*
terminal_window_get_notebook(TerminalWindow * window)3030 terminal_window_get_notebook (TerminalWindow *window)
3031 {
3032 return window->priv->notebook;
3033 }
3034
3035
3036
3037 /**
3038 * terminal_window_get_preferences_dialog:
3039 * @window : A #TerminalWindow.
3040 **/
3041 GtkWidget*
terminal_window_get_preferences_dialog(TerminalWindow * window)3042 terminal_window_get_preferences_dialog (TerminalWindow *window)
3043 {
3044 return window->priv->preferences_dialog;
3045 }
3046
3047
3048
3049 /**
3050 * terminal_window_get_action:
3051 * @window : A #TerminalWindow.
3052 * @action_name : Name of action.
3053 **/
3054 GtkAction*
terminal_window_get_action(TerminalWindow * window,const gchar * action_name)3055 terminal_window_get_action (TerminalWindow *window,
3056 const gchar *action_name)
3057 {
3058 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
3059 return gtk_action_group_get_action (window->priv->action_group, action_name);
3060 G_GNUC_END_IGNORE_DEPRECATIONS
3061 }
3062
3063
3064
3065 /**
3066 * terminal_window_get_font:
3067 * @window : A #TerminalWindow.
3068 **/
3069 const gchar*
terminal_window_get_font(TerminalWindow * window)3070 terminal_window_get_font (TerminalWindow *window)
3071 {
3072 return window->priv->font;
3073 }
3074
3075
3076
3077 /**
3078 * terminal_window_set_font:
3079 * @window : A #TerminalWindow.
3080 **/
3081 void
terminal_window_set_font(TerminalWindow * window,const gchar * font)3082 terminal_window_set_font (TerminalWindow *window,
3083 const gchar *font)
3084 {
3085 terminal_return_if_fail (font != NULL);
3086 g_free (window->priv->font);
3087 window->priv->font = g_strdup (font);
3088 }
3089
3090
3091
3092 /**
3093 * terminal_window_get_scrollbar_visibility:
3094 * @window : A #TerminalWindow.
3095 **/
3096 TerminalVisibility
terminal_window_get_scrollbar_visibility(TerminalWindow * window)3097 terminal_window_get_scrollbar_visibility (TerminalWindow *window)
3098 {
3099 return window->priv->scrollbar_visibility;
3100 }
3101
3102
3103
3104 /**
3105 * terminal_window_set_scrollbar_visibility:
3106 * @window : A #TerminalWindow.
3107 * @scrollbar : Scrollbar visibility.
3108 **/
3109 void
terminal_window_set_scrollbar_visibility(TerminalWindow * window,TerminalVisibility scrollbar)3110 terminal_window_set_scrollbar_visibility (TerminalWindow *window,
3111 TerminalVisibility scrollbar)
3112 {
3113 window->priv->scrollbar_visibility = scrollbar;
3114 }
3115
3116
3117
3118 /**
3119 * terminal_window_get_zoom_level:
3120 * @window : A #TerminalWindow.
3121 **/
3122 TerminalZoomLevel
terminal_window_get_zoom_level(TerminalWindow * window)3123 terminal_window_get_zoom_level (TerminalWindow *window)
3124 {
3125 return window->priv->zoom;
3126 }
3127
3128
3129
3130 /**
3131 * terminal_window_set_zoom_level:
3132 * @window : A #TerminalWindow.
3133 * @zoom : Zoom level.
3134 **/
3135 void
terminal_window_set_zoom_level(TerminalWindow * window,TerminalZoomLevel zoom)3136 terminal_window_set_zoom_level (TerminalWindow *window,
3137 TerminalZoomLevel zoom)
3138 {
3139 window->priv->zoom = zoom;
3140 }
3141
3142
3143
3144 /**
3145 * terminal_window_is_drop_down:
3146 * @window : A #TerminalWindow.
3147 **/
3148 gboolean
terminal_window_is_drop_down(TerminalWindow * window)3149 terminal_window_is_drop_down (TerminalWindow *window)
3150 {
3151 return window->priv->drop_down != 0;
3152 }
3153
3154
3155
3156 /**
3157 * terminal_window_set_drop_down:
3158 * @window : A #TerminalWindow.
3159 * @drop_down : Whether the window is drop-down.
3160 **/
3161 void
terminal_window_set_drop_down(TerminalWindow * window,gboolean drop_down)3162 terminal_window_set_drop_down (TerminalWindow *window,
3163 gboolean drop_down)
3164 {
3165 window->priv->drop_down = drop_down;
3166 }
3167
3168
3169
3170 /**
3171 * terminal_window_get_menubar_height:
3172 * @window : A #TerminalWindow.
3173 **/
3174 gint
terminal_window_get_menubar_height(TerminalWindow * window)3175 terminal_window_get_menubar_height (TerminalWindow *window)
3176 {
3177 GtkRequisition req;
3178
3179 req.height = 0;
3180
3181 if (window->priv->menubar != NULL && gtk_widget_get_visible (window->priv->menubar))
3182 gtk_widget_get_preferred_size (window->priv->menubar, &req, NULL);
3183
3184 return req.height;
3185 }
3186
3187
3188
3189 /**
3190 * terminal_window_get_toolbar_height:
3191 * @window : A #TerminalWindow.
3192 **/
3193 gint
terminal_window_get_toolbar_height(TerminalWindow * window)3194 terminal_window_get_toolbar_height (TerminalWindow *window)
3195 {
3196 GtkRequisition req;
3197
3198 req.height = 0;
3199
3200 if (window->priv->toolbar != NULL && gtk_widget_get_visible (window->priv->toolbar))
3201 gtk_widget_get_preferred_size (window->priv->toolbar, &req, NULL);
3202
3203 return req.height;
3204 }
3205
3206
3207
3208 /**
3209 * terminal_window_rebuild_tabs_menu:
3210 * @window : A #TerminalWindow.
3211 **/
3212 void
terminal_window_rebuild_tabs_menu(TerminalWindow * window)3213 terminal_window_rebuild_tabs_menu (TerminalWindow *window)
3214 {
3215 gint npages, n;
3216 GtkWidget *page;
3217 GSList *group = NULL;
3218 GtkRadioAction *radio_action;
3219 gchar name[50], buf[100];
3220 GSList *lp;
3221 GtkAccelKey key = {0};
3222
3223 if (window->priv->tabs_menu_merge_id != 0)
3224 {
3225 /* remove merge id */
3226 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
3227 gtk_ui_manager_remove_ui (window->priv->ui_manager, window->priv->tabs_menu_merge_id);
3228 G_GNUC_END_IGNORE_DEPRECATIONS
3229
3230 /* drop all the old accels from the action group */
3231 for (lp = window->priv->tabs_menu_actions; lp != NULL; lp = lp->next)
3232 {
3233 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
3234 gtk_action_group_remove_action (window->priv->action_group, GTK_ACTION (lp->data));
3235 G_GNUC_END_IGNORE_DEPRECATIONS
3236 }
3237
3238 g_slist_free (window->priv->tabs_menu_actions);
3239 window->priv->tabs_menu_actions = NULL;
3240 }
3241
3242 /* create a new merge id */
3243 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
3244 window->priv->tabs_menu_merge_id = gtk_ui_manager_new_merge_id (window->priv->ui_manager);
3245 G_GNUC_END_IGNORE_DEPRECATIONS
3246 terminal_assert (window->priv->tabs_menu_actions == NULL);
3247
3248 /* walk the tabs */
3249 npages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->priv->notebook));
3250 for (n = 0; n < npages; n++)
3251 {
3252 page = gtk_notebook_get_nth_page (GTK_NOTEBOOK (window->priv->notebook), n);
3253
3254 g_snprintf (name, sizeof (name), "goto-tab-%d", n + 1);
3255
3256 /* create action */
3257 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
3258 radio_action = gtk_radio_action_new (name, NULL, NULL, NULL, n);
3259 gtk_action_set_sensitive (GTK_ACTION (radio_action), npages > 1);
3260 g_object_bind_property (G_OBJECT (page), "title",
3261 G_OBJECT (radio_action), "label",
3262 G_BINDING_SYNC_CREATE);
3263 gtk_radio_action_set_group (radio_action, group);
3264 group = gtk_radio_action_get_group (radio_action);
3265 gtk_action_group_add_action (window->priv->action_group, GTK_ACTION (radio_action));
3266 G_GNUC_END_IGNORE_DEPRECATIONS
3267 g_signal_connect (G_OBJECT (radio_action), "activate",
3268 G_CALLBACK (terminal_window_action_goto_tab), window->priv->notebook);
3269
3270 /* connect action to the page so we can active it when a tab is switched */
3271 g_object_set_qdata_full (G_OBJECT (page), tabs_menu_action_quark,
3272 radio_action, g_object_unref);
3273
3274 /* set an accelerator path */
3275 g_snprintf (buf, sizeof (buf), "<Actions>/terminal-window/%s", name);
3276 if (gtk_accel_map_lookup_entry (buf, &key) && key.accel_key != 0)
3277 {
3278 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
3279 gtk_action_set_accel_path (GTK_ACTION (radio_action), buf);
3280 G_GNUC_END_IGNORE_DEPRECATIONS
3281 }
3282
3283 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
3284 /* add action in the menu */
3285 gtk_ui_manager_add_ui (window->priv->ui_manager, window->priv->tabs_menu_merge_id,
3286 "/main-menu/tabs-menu/placeholder-tab-items",
3287 name, name, GTK_UI_MANAGER_MENUITEM, FALSE);
3288 /* allow underscore to be shown */
3289 g_snprintf (buf, sizeof (buf), "/main-menu/tabs-menu/placeholder-tab-items/%s", name);
3290 gtk_menu_item_set_use_underline (GTK_MENU_ITEM (gtk_ui_manager_get_widget (window->priv->ui_manager, buf)), FALSE);
3291 G_GNUC_END_IGNORE_DEPRECATIONS
3292
3293 if (npages > 1)
3294 {
3295 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
3296 /* add to right-click tab menu */
3297 gtk_ui_manager_add_ui (window->priv->ui_manager, window->priv->tabs_menu_merge_id,
3298 "/tab-menu/tabs-menu/placeholder-tab-items",
3299 name, name, GTK_UI_MANAGER_MENUITEM, FALSE);
3300 /* allow underscore to be shown */
3301 g_snprintf (buf, sizeof (buf), "/tab-menu/tabs-menu/placeholder-tab-items/%s", name);
3302 gtk_menu_item_set_use_underline (GTK_MENU_ITEM (gtk_ui_manager_get_widget (window->priv->ui_manager, buf)), FALSE);
3303 G_GNUC_END_IGNORE_DEPRECATIONS
3304 }
3305
3306 /* store */
3307 window->priv->tabs_menu_actions = g_slist_prepend (window->priv->tabs_menu_actions, radio_action);
3308 }
3309 }
3310
3311
3312
3313 /**
3314 * terminal_window_action_show_menubar:
3315 * @action : A toggle action.
3316 * @window : A #TerminalWindow.
3317 **/
3318 void
terminal_window_action_show_menubar(GtkToggleAction * action,TerminalWindow * window)3319 terminal_window_action_show_menubar (GtkToggleAction *action,
3320 TerminalWindow *window)
3321 {
3322 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
3323 gboolean show = gtk_toggle_action_get_active (action);
3324 G_GNUC_END_IGNORE_DEPRECATIONS
3325
3326 /* don't do anything if the menubar is already in the desired state (shown/hidden) */
3327 if (gtk_widget_is_visible (window->priv->menubar) != show)
3328 {
3329 terminal_window_size_push (window);
3330
3331 if (show)
3332 gtk_widget_show (window->priv->menubar);
3333 else
3334 gtk_widget_hide (window->priv->menubar);
3335
3336 terminal_window_size_pop (window);
3337 }
3338 }
3339
3340
3341
3342 /**
3343 * terminal_window_update_tab_key_accels:
3344 * @window : A #TerminalWindow.
3345 * @tab_key_accels : A list of Tab key accelerators.
3346 **/
3347 void
terminal_window_update_tab_key_accels(TerminalWindow * window,GSList * tab_key_accels)3348 terminal_window_update_tab_key_accels (TerminalWindow *window,
3349 GSList *tab_key_accels)
3350 {
3351 window->priv->tab_key_accels = tab_key_accels;
3352 }
3353