Skip to content

Patch to Add PuTTY-like Right-Click Paste to Gnome Terminal in Ubuntu22 or 20

License

Notifications You must be signed in to change notification settings

NiceAsiv/ubuntu-gnome-terminal-patch

Repository files navigation

Terminal selection copy and right-click paste function

Based on personal-testing,this method is applicable to gnome-terminal versions 3.36 to 3.44 in ubuntu22.

Chinese 简体中文

0x01.Get the gnome terminal source code

sudo apt-get update
apt-get source gnome-terminal

0x02.Install GNOME development environment

sudo apt-get build-dep gnome-terminal

If any third-party libraries are missing, please install them.

the only file that needs to be modified is gnome-terminal-3.44.0/src/terminal-screen.c(the version of GNOME Terminal used by me)

0x03.Define event functions

Add a release event after the press event.

static gboolean terminal_screen_popup_menu (GtkWidget *widget);
static gboolean terminal_screen_button_press (GtkWidget *widget,
                                              GdkEventButton *event);
// Add button release event
static gboolean terminal_screen_button_release (GtkWidget *widget,
                                              GdkEventButton *event);
static void terminal_screen_hierarchy_changed (GtkWidget *widget,
                                               GtkWidget *previous_toplevel);

0x04.Bind the execution function for the button press and release events.

add widget_class->button_release_event = terminal_screen_button_release; in fuction static void terminal_screen_class_init (TerminalScreenClass *klass)

terminal_screen_class_init (TerminalScreenClass *klass)
{
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
  VteTerminalClass *terminal_class = VTE_TERMINAL_CLASS (klass);
  GSettings *settings;

  object_class->constructed = terminal_screen_constructed;
  object_class->dispose = terminal_screen_dispose;
  object_class->finalize = terminal_screen_finalize;
  object_class->get_property = terminal_screen_get_property;
  object_class->set_property = terminal_screen_set_property;

  widget_class->realize = terminal_screen_realize;
  widget_class->style_updated = terminal_screen_style_updated;
  widget_class->drag_data_received = terminal_screen_drag_data_received;
  widget_class->button_press_event = terminal_screen_button_press;
//Bind the execution function for button press event
  widget_class->button_release_event = terminal_screen_button_release;
  widget_class->popup_menu = terminal_screen_popup_menu;
  widget_class->hierarchy_changed = terminal_screen_hierarchy_changed;
  terminal_class->child_exited = terminal_screen_child_exited;

0x05.Modify the logic of the right-click event execution function

static gboolean
terminal_screen_button_press (GtkWidget      *widget,
                              GdkEventButton *event)
{
  TerminalScreen *screen = TERMINAL_SCREEN (widget);
  gboolean (* button_press_event) (GtkWidget*, GdkEventButton*) =
    GTK_WIDGET_CLASS (terminal_screen_parent_class)->button_press_event;
  gs_free char *hyperlink = nullptr;
  gs_free char *url = nullptr;
  int url_flavor = 0;
  gs_free char *number_info = nullptr;
  gs_free char *timestamp_info = nullptr;
  guint state;

  state = event->state & gtk_accelerator_get_default_mod_mask ();

  hyperlink = terminal_screen_check_hyperlink (screen, (GdkEvent*)event);
  url = terminal_screen_check_match (screen, (GdkEvent*)event, &url_flavor);
  terminal_screen_check_extra (screen, (GdkEvent*)event, &number_info, &timestamp_info);

  if (hyperlink != nullptr &&
      (event->button == 1 || event->button == 2) &&
      (state & GDK_CONTROL_MASK))
    {
      gboolean handled = FALSE;

      g_signal_emit (screen, signals[MATCH_CLICKED], 0,
                     hyperlink,
                     FLAVOR_AS_IS,
                     state,
                     &handled);
      if (handled)
        return TRUE; /* don't do anything else such as select with the click */
    }

  if (url != nullptr &&
      (event->button == 1 || event->button == 2) &&
      (state & GDK_CONTROL_MASK))
    {
      gboolean handled = FALSE;

      g_signal_emit (screen, signals[MATCH_CLICKED], 0,
                     url,
                     url_flavor,
                     state,
                     &handled);
      if (handled)
        return TRUE; /* don't do anything else such as select with the click */
    }
//Modify here
  if (event->type == GDK_BUTTON_PRESS && event->button == 3)
    {
      if (!(event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK)))
        {
          /* on right-click, we should first try to send the mouse event to
           * the client, and popup only if that's not handled. */
          //if (button_press_event && button_press_event (widget, event))
           // return TRUE;
          //terminal_screen_do_popup (screen, event, hyperlink, url, url_flavor, number_info, timestamp_info);
          // Comment out the above 3 lines of code logic, directly call the paste function
          //add this in version 3.44
          vte_terminal_paste_clipboard (VTE_TERMINAL (screen));
          
          hyperlink = nullptr; /* adopted to the popup info */
          url = nullptr; /* ditto */
          number_info = nullptr; /* ditto */
          timestamp_info = nullptr; /* ditto */
          return TRUE;
        }
      else if (!(event->state & (GDK_CONTROL_MASK | GDK_MOD1_MASK)))
        {
          /* do popup on shift+right-click */
          terminal_screen_do_popup (screen, event, hyperlink, url, url_flavor, number_info, timestamp_info);
          hyperlink = nullptr; /* adopted to the popup info */
          url = nullptr; /* ditto */
          number_info = nullptr; /* ditto */
          timestamp_info = nullptr; /* ditto */
          return TRUE;
        }
    }

0x06.Implement the selection copy function

static gboolean
terminal_screen_button_release (GtkWidget *widget,
                                GdkEventButton *event){
    gboolean ret;
 
    TerminalScreen *screen = TERMINAL_SCREEN (widget);
    gboolean (* button_release_event) (GtkWidget*, GdkEventButton*) =
            GTK_WIDGET_CLASS (terminal_screen_parent_class)->button_release_event;
    ret = FALSE;
    if (button_release_event){
        ret = button_release_event (widget, event);
    }
 
    if (event->button == 1){
        gboolean can_copy;
        can_copy = vte_terminal_get_has_selection (VTE_TERMINAL (screen));
 
        if (can_copy)
            vte_terminal_copy_clipboard (VTE_TERMINAL (screen));
    }
 
    return ret;
}

0x07.Compile and install

After making the necessary changes in the source code, go to the gnome-terminal-3.44.0 directory and execute:

dpkg-buildpackage -us -uc -b

install

sudo dpkg -i gnome-terminal_3.44.0-1ubuntu1_amd64.deb

image-20231028222659981

Enjoy!

Restart the terminal, and you will be able to get Terminal selection copy and right-click paste function

About

Patch to Add PuTTY-like Right-Click Paste to Gnome Terminal in Ubuntu22 or 20

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages