summaryrefslogtreecommitdiff
path: root/src/terminal-window.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/terminal-window.c')
-rw-r--r--src/terminal-window.c245
1 files changed, 178 insertions, 67 deletions
diff --git a/src/terminal-window.c b/src/terminal-window.c
index 2868932..fd50df7 100644
--- a/src/terminal-window.c
+++ b/src/terminal-window.c
@@ -2,6 +2,7 @@
* Copyright © 2001 Havoc Pennington
* Copyright © 2002 Red Hat, Inc.
* Copyright © 2007, 2008, 2009 Christian Persch
+ * Copyright (C) 2012-2021 MATE Developers
*
* Mate-terminal is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -107,7 +108,8 @@ struct _TerminalWindowPrivate
/* Workaround until gtk+ bug #535557 is fixed */
guint icon_title_set : 1;
- time_t focus_time;
+
+ gint64 focus_time;
/* should we copy selection to clibpoard */
int copy_selection;
@@ -517,27 +519,23 @@ escape_underscores (const char *name)
}
static int
-find_tab_num_at_pos (GtkNotebook *notebook,
+find_tab_num_at_pos (GtkNotebook *nb,
int screen_x,
int screen_y)
{
- GtkPositionType tab_pos;
int page_num = 0;
- GtkNotebook *nb = GTK_NOTEBOOK (notebook);
GtkWidget *page;
GtkAllocation tab_allocation;
- tab_pos = gtk_notebook_get_tab_pos (GTK_NOTEBOOK (notebook));
-
while ((page = gtk_notebook_get_nth_page (nb, page_num)))
{
GtkWidget *tab;
- int max_x, max_y, x_root, y_root;
+ int x_root, y_root;
tab = gtk_notebook_get_tab_label (nb, page);
g_return_val_if_fail (tab != NULL, -1);
- if (!gtk_widget_get_mapped (GTK_WIDGET (tab)))
+ if (!gtk_widget_get_mapped (tab))
{
page_num++;
continue;
@@ -546,13 +544,10 @@ find_tab_num_at_pos (GtkNotebook *notebook,
gdk_window_get_origin (gtk_widget_get_window (tab), &x_root, &y_root);
gtk_widget_get_allocation (tab, &tab_allocation);
- max_x = x_root + tab_allocation.x + tab_allocation.width;
- max_y = y_root + tab_allocation.y + tab_allocation.height;
-
- if ((tab_pos == GTK_POS_TOP || tab_pos == GTK_POS_BOTTOM) && screen_x <= max_x)
- return page_num;
-
- if ((tab_pos == GTK_POS_LEFT || tab_pos == GTK_POS_RIGHT) && screen_y <= max_y)
+ if (screen_x >= x_root + tab_allocation.x &&
+ screen_x <= x_root + tab_allocation.x + tab_allocation.width &&
+ screen_y >= y_root + tab_allocation.y &&
+ screen_y <= y_root + tab_allocation.y + tab_allocation.height)
return page_num;
page_num++;
@@ -1364,6 +1359,38 @@ handle_tab_droped_on_desktop (GtkNotebook *source_notebook,
/* Terminal screen popup menu handling */
static void
+popup_open_hyperlink_callback (GtkAction *action,
+ TerminalWindow *window)
+{
+ TerminalWindowPrivate *priv = window->priv;
+ TerminalScreenPopupInfo *info = priv->popup_info;
+
+ if (info == NULL)
+ return;
+
+ terminal_util_open_url (GTK_WIDGET (window), info->hyperlink, FLAVOR_AS_IS,
+ gtk_get_current_event_time ());
+}
+
+static void
+popup_copy_hyperlink_callback (GtkAction *action,
+ TerminalWindow *window)
+{
+ TerminalWindowPrivate *priv = window->priv;
+ TerminalScreenPopupInfo *info = priv->popup_info;
+ GtkClipboard *clipboard;
+
+ if (info == NULL)
+ return;
+
+ if (info->hyperlink == NULL)
+ return;
+
+ clipboard = gtk_widget_get_clipboard (GTK_WIDGET (window), GDK_SELECTION_CLIPBOARD);
+ gtk_clipboard_set_text (clipboard, info->hyperlink, -1);
+}
+
+static void
popup_open_url_callback (GtkAction *action,
TerminalWindow *window)
{
@@ -1373,7 +1400,7 @@ popup_open_url_callback (GtkAction *action,
if (info == NULL)
return;
- terminal_util_open_url (GTK_WIDGET (window), info->string, info->flavour,
+ terminal_util_open_url (GTK_WIDGET (window), info->url, info->flavor,
gtk_get_current_event_time ());
}
@@ -1388,11 +1415,11 @@ popup_copy_url_callback (GtkAction *action,
if (info == NULL)
return;
- if (info->string == NULL)
+ if (info->url == NULL)
return;
clipboard = gtk_widget_get_clipboard (GTK_WIDGET (window), GDK_SELECTION_CLIPBOARD);
- gtk_clipboard_set_text (clipboard, info->string, -1);
+ gtk_clipboard_set_text (clipboard, info->url, -1);
}
static void
@@ -1474,7 +1501,7 @@ popup_clipboard_targets_received_cb (GtkClipboard *clipboard,
TerminalScreen *screen = info->screen;
GtkWidget *popup_menu;
GtkAction *action;
- gboolean can_paste, can_paste_uris, show_link, show_email_link, show_call_link, show_input_method_menu;
+ gboolean can_paste, can_paste_uris, show_hyperlink, show_link, show_email_link, show_call_link, show_input_method_menu;
int n_pages;
if (!gtk_widget_get_realized (GTK_WIDGET (screen)))
@@ -1492,11 +1519,16 @@ popup_clipboard_targets_received_cb (GtkClipboard *clipboard,
can_paste = targets != NULL && gtk_targets_include_text (targets, n_targets);
can_paste_uris = targets != NULL && gtk_targets_include_uri (targets, n_targets);
- show_link = info->string != NULL && (info->flavour == FLAVOR_AS_IS || info->flavour == FLAVOR_DEFAULT_TO_HTTP);
- show_email_link = info->string != NULL && info->flavour == FLAVOR_EMAIL;
- show_call_link = info->string != NULL && info->flavour == FLAVOR_VOIP_CALL;
+ show_hyperlink = info->hyperlink != NULL;
+ show_link = !show_hyperlink && info->url != NULL && (info->flavor == FLAVOR_AS_IS || info->flavor == FLAVOR_DEFAULT_TO_HTTP);
+ show_email_link = !show_hyperlink && info->url != NULL && info->flavor == FLAVOR_EMAIL;
+ show_call_link = !show_hyperlink && info->url != NULL && info->flavor == FLAVOR_VOIP_CALL;
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
+ action = gtk_action_group_get_action (priv->action_group, "PopupOpenHyperlink");
+ gtk_action_set_visible (action, show_hyperlink);
+ action = gtk_action_group_get_action (priv->action_group, "PopupCopyHyperlinkAddress");
+ gtk_action_set_visible (action, show_hyperlink);
action = gtk_action_group_get_action (priv->action_group, "PopupSendEmail");
gtk_action_set_visible (action, show_email_link);
action = gtk_action_group_get_action (priv->action_group, "PopupCopyEmailAddress");
@@ -1553,6 +1585,8 @@ popup_clipboard_targets_received_cb (GtkClipboard *clipboard,
NULL, NULL,
info->button,
info->timestamp);
+ gtk_style_context_add_class(gtk_widget_get_style_context (popup_menu),
+ GTK_STYLE_CLASS_CONTEXT_MENU);
}
static void
@@ -1572,8 +1606,8 @@ screen_show_popup_menu_callback (TerminalScreen *screen,
static gboolean
screen_match_clicked_cb (TerminalScreen *screen,
- const char *match,
- int flavour,
+ const char *url,
+ int url_flavor,
guint state,
TerminalWindow *window)
{
@@ -1582,16 +1616,16 @@ screen_match_clicked_cb (TerminalScreen *screen,
if (screen != priv->active_screen)
return FALSE;
- switch (flavour)
+ switch (url_flavor)
{
#ifdef ENABLE_SKEY
case FLAVOR_SKEY:
- terminal_skey_do_popup (GTK_WINDOW (window), screen, match);
+ terminal_skey_do_popup (GTK_WINDOW (window), screen, url);
break;
#endif
default:
gtk_widget_grab_focus (GTK_WIDGET (screen));
- terminal_util_open_url (GTK_WIDGET (window), match, flavour,
+ terminal_util_open_url (GTK_WIDGET (window), url, url_flavor,
gtk_get_current_event_time ());
break;
}
@@ -1709,6 +1743,39 @@ terminal_window_realize (GtkWidget *widget)
}
static gboolean
+terminal_window_draw (GtkWidget *widget,
+ cairo_t *cr)
+{
+ if (gtk_widget_get_app_paintable(widget))
+ {
+ GtkAllocation child_allocation;
+ GtkStyleContext *context;
+ int width;
+ int height;
+ GtkWidget *child;
+
+ /* Get the *child* allocation, so we don't overwrite window borders */
+ child = gtk_bin_get_child (GTK_BIN (widget));
+ gtk_widget_get_allocation (child, &child_allocation);
+
+ context = gtk_widget_get_style_context (widget);
+ width = gtk_widget_get_allocated_width (widget);
+ height = gtk_widget_get_allocated_height (widget);
+ gtk_render_background (context, cr, 0, 0, width, height);
+ gtk_render_frame (context, cr, 0, 0, width, height);
+
+ gtk_render_background (context, cr,
+ child_allocation.x, child_allocation.y,
+ child_allocation.width, child_allocation.height);
+ gtk_render_frame (context, cr,
+ child_allocation.x, child_allocation.y,
+ child_allocation.width, child_allocation.height);
+ }
+
+ return GTK_WIDGET_CLASS (terminal_window_parent_class)->draw (widget, cr);
+}
+
+static gboolean
terminal_window_map_event (GtkWidget *widget,
GdkEventAny *event)
{
@@ -1740,7 +1807,6 @@ terminal_window_map_event (GtkWidget *widget,
return FALSE;
}
-
static gboolean
terminal_window_state_event (GtkWidget *widget,
GdkEventWindowState *event)
@@ -2081,6 +2147,16 @@ terminal_window_init (TerminalWindow *window)
/* Popup menu */
{
+ "PopupOpenHyperlink", NULL, N_("_Open Hyperlink"), NULL,
+ NULL,
+ G_CALLBACK (popup_open_hyperlink_callback)
+ },
+ {
+ "PopupCopyHyperlinkAddress", NULL, N_("_Copy Hyperlink Address"), NULL,
+ NULL,
+ G_CALLBACK (popup_copy_hyperlink_callback)
+ },
+ {
"PopupSendEmail", NULL, N_("_Send Mail To…"), NULL,
NULL,
G_CALLBACK (popup_open_url_callback)
@@ -2342,6 +2418,7 @@ terminal_window_class_init (TerminalWindowClass *klass)
widget_class->show = terminal_window_show;
widget_class->realize = terminal_window_realize;
+ widget_class->draw = terminal_window_draw;
widget_class->map_event = terminal_window_map_event;
widget_class->window_state_event = terminal_window_state_event;
widget_class->screen_changed = terminal_window_screen_changed;
@@ -2432,7 +2509,7 @@ terminal_window_focus_in_event (GtkWidget *widget,
TerminalWindowPrivate *priv = window->priv;
if (event->in)
- priv->focus_time = time(NULL);
+ priv->focus_time = g_get_real_time () / G_USEC_PER_SEC;
return FALSE;
}
@@ -2535,8 +2612,6 @@ sync_screen_icon_title (TerminalScreen *screen,
return;
gdk_window_set_icon_name (gtk_widget_get_window (GTK_WIDGET (window)), terminal_screen_get_icon_title (screen));
-
- priv->icon_title_set = TRUE;
}
static void
@@ -2549,10 +2624,6 @@ sync_screen_icon_title_set (TerminalScreen *screen,
if (!gtk_widget_get_realized (GTK_WIDGET (window)))
return;
- /* No need to restore the title if we never set an icon title */
- if (!priv->icon_title_set)
- return;
-
if (screen != priv->active_screen)
return;
@@ -2560,16 +2631,28 @@ sync_screen_icon_title_set (TerminalScreen *screen,
return;
/* Need to reset the icon name */
- /* FIXME: Once gtk+ bug 535557 is fixed, use that to unset the icon title. */
-
- g_object_set_qdata (G_OBJECT (gtk_widget_get_window (GTK_WIDGET (window))),
- g_quark_from_static_string ("gdk-icon-name-set"),
- GUINT_TO_POINTER (FALSE));
- priv->icon_title_set = FALSE;
+ gdk_window_set_icon_name (gtk_widget_get_window (GTK_WIDGET (window)), NULL);
/* Re-setting the right title will be done by the notify::title handler which comes after this one */
}
+static void
+screen_hyperlink_hover_uri_changed (TerminalScreen *screen,
+ const char *uri,
+ const GdkRectangle *bbox G_GNUC_UNUSED,
+ TerminalWindow *window G_GNUC_UNUSED)
+{
+ char *label = NULL;
+
+ if (!gtk_widget_get_realized (GTK_WIDGET (screen)))
+ return;
+
+ label = terminal_util_hyperlink_uri_label (uri);
+
+ gtk_widget_set_tooltip_text (GTK_WIDGET (screen), label);
+ g_free(label);
+}
+
/* Notebook callbacks */
static void
@@ -2725,7 +2808,7 @@ terminal_window_set_menubar_visible (TerminalWindow *window,
if (setting == priv->menubar_visible)
return;
- priv->menubar_visible = setting;
+ priv->menubar_visible = (setting != FALSE);
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
action = gtk_action_group_get_action (priv->action_group, "ViewMenubar");
@@ -2965,6 +3048,16 @@ notebook_button_press_cb (GtkWidget *widget,
}
}
+ /* If the event is a double click, display the set title dialog */
+ if (event->type == GDK_DOUBLE_BUTTON_PRESS &&
+ find_tab_num_at_pos (notebook, (int) event->x_root, (int) event->y_root) >= 0)
+ {
+ terminal_set_title_callback (NULL, window);
+
+ /* handle ONLY the double-click event */
+ return TRUE;
+ }
+
if (event->type != GDK_BUTTON_PRESS ||
event->button != 3 ||
(event->state & gtk_accelerator_get_default_mod_mask ()) != 0)
@@ -3174,6 +3267,8 @@ notebook_page_added_callback (GtkWidget *notebook,
G_CALLBACK (sync_screen_icon_title_set), window);
g_signal_connect (screen, "selection-changed",
G_CALLBACK (terminal_window_update_copy_sensitivity), window);
+ g_signal_connect (screen, "hyperlink-hover-uri-changed",
+ G_CALLBACK (screen_hyperlink_hover_uri_changed), window);
g_signal_connect (screen, "show-popup-menu",
G_CALLBACK (screen_show_popup_menu_callback), window);
@@ -3254,6 +3349,10 @@ notebook_page_removed_callback (GtkWidget *notebook,
G_CALLBACK (terminal_window_update_copy_sensitivity),
window);
+ g_signal_handlers_disconnect_by_func (G_OBJECT (screen),
+ G_CALLBACK (screen_hyperlink_hover_uri_changed),
+ window);
+
g_signal_handlers_disconnect_by_func (screen,
G_CALLBACK (screen_show_popup_menu_callback),
window);
@@ -3363,10 +3462,11 @@ terminal_window_update_geometry (TerminalWindow *window)
GtkWidget *widget;
GdkGeometry hints;
GtkBorder padding;
- GtkRequisition toplevel_request, vbox_request, widget_request;
+ GtkRequisition vbox_request;
int grid_width, grid_height;
int char_width, char_height;
int chrome_width, chrome_height;
+ int csd_width = 0, csd_height = 0;
if (priv->active_screen == NULL)
return;
@@ -3397,20 +3497,41 @@ terminal_window_update_geometry (TerminalWindow *window)
_terminal_debug_print (TERMINAL_DEBUG_GEOMETRY, "content area requests %dx%d px\n",
vbox_request.width, vbox_request.height);
- gtk_widget_get_preferred_size (GTK_WIDGET (window), NULL, &toplevel_request);
- _terminal_debug_print (TERMINAL_DEBUG_GEOMETRY, "window requests %dx%d px\n",
- toplevel_request.width, toplevel_request.height);
-
chrome_width = vbox_request.width - (char_width * grid_width);
chrome_height = vbox_request.height - (char_height * grid_height);
_terminal_debug_print (TERMINAL_DEBUG_GEOMETRY, "chrome: %dx%d px\n",
chrome_width, chrome_height);
- gtk_widget_get_preferred_size (widget, NULL, &widget_request);
- _terminal_debug_print (TERMINAL_DEBUG_GEOMETRY, "terminal widget requests %dx%d px\n",
- widget_request.width, widget_request.height);
+ if (gtk_widget_get_realized (GTK_WIDGET (window))) {
+ GtkAllocation toplevel_allocation, vbox_allocation;
+
+ gtk_widget_get_allocation (priv->main_vbox, &vbox_allocation);
+ _terminal_debug_print (TERMINAL_DEBUG_GEOMETRY,
+ "terminal widget allocation %dx%d px\n",
+ vbox_allocation.width, vbox_allocation.height);
+
+ gtk_widget_get_allocation (GTK_WIDGET (window), &toplevel_allocation);
+ _terminal_debug_print (TERMINAL_DEBUG_GEOMETRY, "window allocation %dx%d px\n",
+ toplevel_allocation.width, toplevel_allocation.height);
+
+ csd_width = toplevel_allocation.width - vbox_allocation.width;
+ csd_height = toplevel_allocation.height - vbox_allocation.height;
+ _terminal_debug_print (TERMINAL_DEBUG_GEOMETRY, "CSDs: %dx%d px\n",
+ csd_width, csd_height);
+ }
- if (char_width != priv->old_char_width ||
+ if (!gtk_widget_get_realized (GTK_WIDGET (window)))
+ {
+ /* Don't actually set the geometry hints until we have been realized,
+ * because we don't know how large the client-side decorations are going
+ * to be.
+ *
+ * Similarly, the size request doesn't seem to include the padding
+ * until we've been redrawn at least once. Don't resize the window
+ * until we've done that. */
+ _terminal_debug_print (TERMINAL_DEBUG_GEOMETRY, "not realized yet\n");
+ }
+ else if (char_width != priv->old_char_width ||
char_height != priv->old_char_height ||
padding.left + padding.right != priv->old_padding_width ||
padding.top + padding.bottom != priv->old_padding_height ||
@@ -3418,8 +3539,8 @@ terminal_window_update_geometry (TerminalWindow *window)
chrome_height != priv->old_chrome_height ||
widget != GTK_WIDGET (priv->old_geometry_widget))
{
- hints.base_width = chrome_width;
- hints.base_height = chrome_height;
+ hints.base_width = chrome_width + csd_width;
+ hints.base_height = chrome_height + csd_height;
#define MIN_WIDTH_CHARS 4
#define MIN_HEIGHT_CHARS 1
@@ -3563,14 +3684,11 @@ confirm_close_window_or_tab (TerminalWindow *window,
GtkBuilder *builder;
TerminalWindowPrivate *priv = window->priv;
GtkWidget *dialog;
- gboolean do_confirm;
gboolean has_processes;
int n_tabs;
char *confirm_msg;
- do_confirm = g_settings_get_boolean (settings_global, "confirm-window-close");
-
- if (!do_confirm)
+ if (!g_settings_get_boolean (settings_global, "confirm-window-close"))
return FALSE;
if (screen)
@@ -3582,8 +3700,6 @@ confirm_close_window_or_tab (TerminalWindow *window,
{
GList *tabs, *t;
- do_confirm = FALSE;
-
tabs = terminal_window_list_screen_containers (window);
n_tabs = g_list_length (tabs);
@@ -3599,7 +3715,6 @@ confirm_close_window_or_tab (TerminalWindow *window,
g_list_free (tabs);
}
-
if (has_processes)
{
if (n_tabs > 1)
@@ -3613,7 +3728,6 @@ confirm_close_window_or_tab (TerminalWindow *window,
else
return FALSE;
-
builder = gtk_builder_new_from_resource (TERMINAL_RESOURCES_PATH_PREFIX G_DIR_SEPARATOR_S "ui/confirm-close-dialog.ui");
priv->confirm_close_dialog = dialog = GTK_WIDGET (gtk_builder_get_object (builder, "confirm_close_dialog"));
if (n_tabs > 1) {
@@ -3791,8 +3905,7 @@ clipboard_uris_received_cb (GtkClipboard *clipboard,
}
/* This potentially modifies the strings in |uris| but that's ok */
- if (data->uris_as_paths)
- terminal_util_transform_uris_to_quoted_fuse_paths (uris);
+ terminal_util_transform_uris_to_quoted_fuse_paths (uris);
text = terminal_util_concat_uris (uris, &len);
vte_terminal_feed_child (VTE_TERMINAL (data->screen), text, len);
@@ -3815,7 +3928,7 @@ clipboard_targets_received_cb (GtkClipboard *clipboard,
return;
}
- if (gtk_targets_include_uri (targets, n_targets))
+ if (data->uris_as_paths && gtk_targets_include_uri (targets, n_targets))
{
gtk_clipboard_request_uris (clipboard,
(GtkClipboardURIReceivedFunc) clipboard_uris_received_cb,
@@ -4043,7 +4156,6 @@ view_zoom_normal_callback (GtkAction *action,
terminal_window_update_zoom_sensitivity (window);
}
-
static void
search_find_response_callback (GtkWidget *dialog,
int response,
@@ -4212,6 +4324,7 @@ terminal_set_title_dialog_response_cb (GtkWidget *dialog,
}
gtk_widget_destroy (dialog);
+ gtk_widget_grab_focus (GTK_WIDGET (screen));
}
static void
@@ -4384,7 +4497,6 @@ help_about_callback (GtkAction *action,
gsize data_len, n_authors = 0, n_contributors = 0, n_artists = 0, n_documenters = 0 , i;
GPtrArray *array;
-
bytes = g_resources_lookup_data (TERMINAL_RESOURCES_PATH_PREFIX G_DIR_SEPARATOR_S "ui/terminal.about",
G_RESOURCE_LOOKUP_FLAGS_NONE,
&error);
@@ -4534,7 +4646,6 @@ terminal_window_save_state (TerminalWindow *window,
g_strfreev (tab_names);
}
-
TerminalWindow *
terminal_window_get_latest_focused (TerminalWindow *window1,
TerminalWindow *window2)