diff options
Diffstat (limited to 'src/terminal-window.c')
-rw-r--r-- | src/terminal-window.c | 245 |
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) |