joaquinlpereyra
joaquinlpereyra

Reputation: 966

GTK+: Add custom accelerator to VTE

I have a problem adding accelerators to a menu that appears on a Gtk.EventBox() that contains only a Vte.Terminal(). The menu appears OK, and copy and paste work fine, but the accelerators just don't seem to work. They are grabbed by VTE before they get to my eventBox (weirdly, 'cause my eventbox is above the vte widget) and, for example, Ctrl+Shift+C works as Ctrl+C on a terminal and just interrupts the current process. Any ideas on how to go about this?

The relevant association of menuitem-accelerator is the comment code.

def terminalBox(self, terminal):
    """Given a terminal, creates an EventBox for the Box that has as
    a children said terminal"""
    eventTerminalBox = Gtk.EventBox()
    terminalBox = Gtk.Box()
    terminalBox.pack_start(terminal, True, True, 0)
    eventTerminalBox.connect("button_press_event", self.right_click)
    eventTerminalBox.add(terminalBox)
    return eventTerminalBox

def right_click(self, eventbox, event):
    """Defines the menu created when a user rightclicks on the
    terminal eventbox"""
    menu = Gtk.Menu()
    copy = Gtk.MenuItem("Copy")
    paste = Gtk.MenuItem("Paste")
    menu.append(paste)
    menu.append(copy)

    # TODO: make accelerators for copy paste work. add accel for paste
    #accelgroup = Gtk.AccelGroup()
    #self.add_accel_group(accelgroup)
    #accellabel = Gtk.AccelLabel("Copy/Paste")
    #accellabel.set_hexpand(True)
    #copy.add_accelerator("activate",
    #                     accelgroup,
    #                     Gdk.keyval_from_name("c"),
    #                     Gdk.ModifierType.SHIFT_MASK |
    #                     Gdk.ModifierType.CONTROL_MASK,
    #                     Gtk.AccelFlags.VISIBLE)

    copy.connect("activate", self.copy_text)
    paste.connect("activate", self.paste_text)

    copy.show()
    paste.show()
    menu.popup(None, None, None, None, event.button, event.time)

def copy_text(self, button):
    """What happens when the user copies text"""
    content = self.selection_clipboard.wait_for_text()
    self.clipboard.set_text(content, -1)

def paste_text(self, button):
    """What happens when the user pastes text"""
    currentTerminal = self.getCurrentFocusedTerminal()
    currentTerminal.paste_clipboard()

Upvotes: 2

Views: 425

Answers (1)

joaquinlpereyra
joaquinlpereyra

Reputation: 966

OK, in case anyone else needs help with this. I gave up with GTK menu accelerators, so instead I turned to my Vte Widget. There, I connected the key_press_event signal to a method which detects which keys are pressed, and in case it finds the combination of Ctrl+Shift it returns. The return is important because that's what blocks VTE from actually doing something else with the shorcut, like killing the process on Ctrl+Shift+C.

class Terminal(Vte.Terminal):
    """Defines a simple terminal"""
    def __init__(self, CONF):
        super(Vte.Terminal, self).__init__()

        self.pty = self.pty_new_sync(Vte.PtyFlags.DEFAULT, None)
        self.set_pty(self.pty)
        self.connect("key_press_event", self.copy_or_paste)

        self.set_scrollback_lines(-1)
        self.set_audible_bell(0)

    def copy_or_paste(self, widget, event):
        """Decides if the Ctrl+Shift is pressed, in which case returns True.
        If Ctrl+Shift+C or Ctrl+Shift+V are pressed, copies or pastes,
        acordingly. Return necesary so it doesn't perform other action,
        like killing the process, on Ctrl+C.
        """

        control_key = Gdk.ModifierType.CONTROL_MASK
        shift_key = Gdk.ModifierType.SHIFT_MASK
        if event.type == Gdk.EventType.KEY_PRESS:
            if event.state == shift_key | control_key: #both shift  and control
                if event.keyval == 67: # that's the C key
                    self.copy_clipboard()
                elif event.keyval == 86: # and that's the V key
                    self.paste_clipboard()
                return True

Upvotes: 1

Related Questions