Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion terminatorlib/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,8 @@
'previous_profile' : '',
'preferences' : '',
'preferences_keybindings' : '<Control><Shift>k',
'help' : 'F1'
'help' : 'F1',
'detach_tab' : '<Shift><Control>d'
},
'profiles': {
'default': {
Expand Down
32 changes: 25 additions & 7 deletions terminatorlib/notebook.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ def __init__(self, window):
self.connect('switch-page', self.deferred_on_tab_switch)
self.connect('scroll-event', self.on_scroll_event)
self.connect('create-window', self.create_window_detach)
self.connect_after('drag-failed', self.on_tab_drag_failed)
self.configure()

self.set_can_focus(False)
Expand Down Expand Up @@ -79,21 +80,37 @@ def configure(self):
self.last_active_term = {}

def create_window_detach(self, notebook, widget, x, y):
"""Create a window to contain a detached tab"""
dbg('creating window for detached tab: %s' % widget)
maker = Factory()
"""Defer detaching a dropped tab until the drag has ended"""
dbg('deferring detach of dropped tab: %s' % widget)
GObject.idle_add(self.detach_tab_to_new_window, widget, x, y)

def detach_tab_to_new_window(self, widget, x=None, y=None):
"""Detach the tab containing widget into a newly created window"""
child = self.find_tab_root(widget)
if self.page_num(child) == -1:
err('could not find tab to detach for %s' % widget)
return False

dbg('detaching tab into new window: %s' % child)
maker = Factory()
window = maker.make('Window')
window.move(x, y)
if x is not None and y is not None:
window.move(x, y)
size = self.window.get_size()
window.resize(size.width, size.height)

self.detach_tab(widget)
self.disconnect_child(widget)
self.detach_tab(child)
self.disconnect_child(child)
self.hoover()
window.add(widget)
window.add(child)

window.show_all()
return False

def on_tab_drag_failed(self, notebook, context, result):
"""Re-allocate after a failed tab drag so the label repaints"""
GObject.idle_add(self.queue_resize)
return False

def create_layout(self, layout):
"""Apply layout configuration"""
Expand Down Expand Up @@ -290,6 +307,7 @@ def newtab(self, debugtab=False, widget=None, cwd=None, metadata=None, profile=N
'group-tab-toggle': top_window.group_tab_toggle,
'ungroup-tab': top_window.ungroup_tab,
'move-tab': top_window.move_tab,
'detach-tab': top_window.detach_tab_to_new_window,
'tab-new': [top_window.tab_new, widget],
'navigate': top_window.navigate_terminal,
'zoom': top_window.zoom,
Expand Down
1 change: 1 addition & 0 deletions terminatorlib/paned.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ def add(self, widget, metadata=None):
'group-tab-toggle': top_window.group_tab_toggle,
'ungroup-tab': top_window.ungroup_tab,
'move-tab': top_window.move_tab,
'detach-tab': top_window.detach_tab_to_new_window,
'maximise': [top_window.zoom, False],
'tab-new': [top_window.tab_new, widget],
'navigate': top_window.navigate_terminal,
Expand Down
1 change: 1 addition & 0 deletions terminatorlib/prefseditor.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ class PrefsEditor:
'resize_right' : _('Resize the terminal right'),
'move_tab_right' : _('Move the tab right'),
'move_tab_left' : _('Move the tab left'),
'detach_tab' : _('Detach the tab into a new window'),
'toggle_zoom' : _('Maximize terminal'),
'scaled_zoom' : _('Zoom terminal'),
'next_tab' : _('Switch to the next tab'),
Expand Down
4 changes: 4 additions & 0 deletions terminatorlib/terminal.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ class Terminal(Gtk.VBox):
'group-all-toggle': (GObject.SignalFlags.RUN_LAST, None, ()),
'move-tab': (GObject.SignalFlags.RUN_LAST, None,
(GObject.TYPE_STRING,)),
'detach-tab': (GObject.SignalFlags.RUN_LAST, None, ()),
'group-win': (GObject.SignalFlags.RUN_LAST, None, ()),
'group-win-toggle': (GObject.SignalFlags.RUN_LAST, None, ()),
'ungroup-win': (GObject.SignalFlags.RUN_LAST, None, ()),
Expand Down Expand Up @@ -2088,6 +2089,9 @@ def key_move_tab_right(self):
def key_move_tab_left(self):
self.emit('move-tab', 'left')

def key_detach_tab(self):
self.emit('detach-tab')

def key_toggle_zoom(self):
if self.is_zoomed():
self.unzoom()
Expand Down
7 changes: 7 additions & 0 deletions terminatorlib/terminal_popup_menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,13 @@ def show(self, widget, event=None):
terminal.emit('tab-new', True, terminal))
menu.append(item)

if isinstance(terminal.get_toplevel().get_child(), Gtk.Notebook):
item = self.menu_item(Gtk.MenuItem, 'detach_tab',
_('Detach Ta_b'))
item.connect('activate', lambda x:
terminal.emit('detach-tab'))
menu.append(item)

menu.append(Gtk.SeparatorMenuItem())

item = self.menu_item(Gtk.ImageMenuItem, 'close_term', _('_Close'))
Expand Down
15 changes: 15 additions & 0 deletions terminatorlib/window.py
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,7 @@ def add(self, widget, metadata=None):
'group-tab-toggle': self.group_tab_toggle,
'ungroup-tab': self.ungroup_tab,
'move-tab': self.move_tab,
'detach-tab': self.detach_tab_to_new_window,
'tab-new': [self.tab_new, widget],
'navigate': self.navigate_terminal,
'rotate-cw': [self.rotate, True],
Expand Down Expand Up @@ -1035,6 +1036,20 @@ def move_tab(self, widget, direction):

notebook.reorder_child(child, page)

def detach_tab_to_new_window(self, widget):
"""Detach the tab containing widget into a new window"""
if self.is_zoomed():
self.unzoom()

maker = Factory()
notebook = self.get_child()

if not maker.isinstance(notebook, 'Notebook'):
dbg('not in a notebook, refusing to detach tab')
return

notebook.detach_tab_to_new_window(widget)

def navigate_terminal(self, terminal, direction):
"""Navigate around terminals"""
if self.is_zoomed():
Expand Down
18 changes: 9 additions & 9 deletions tests/test_prefseditor_keybindings.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,17 +68,17 @@ def test_non_empty_default_keybinding_accels_are_distinct():
"accel_params,expected",
[
# 1) 'edit_tab_title' Ctrl+Alt+A
(("9", 97, CONTROL_ALT_MOD, 38), False,),
(("10", 97, CONTROL_ALT_MOD, 38), False,),
# 2) 'edit_terminal_title' Ctrl+Alt+A
(("10", 97, CONTROL_ALT_MOD, 38), True,),
(("11", 97, CONTROL_ALT_MOD, 38), True,),
# 3) 'edit_window_title' F11
(("11", 65480, Gdk.ModifierType(0), 95), True,),
(("12", 65480, Gdk.ModifierType(0), 95), True,),
# 4) 'zoom_in' Shift+Ctrl+Z
(("70", 122, CONTROL_SHIFT_MOD, 52), True,),
(("71", 122, CONTROL_SHIFT_MOD, 52), True,),
# 5) 'close_terminal' Ctrl+Alt+{
(("3", 123, CONTROL_ALT_SHIFT_MOD, 34), False,),
# 6) 'zoom_in' Shift+Ctrl+B
(("70", 98, CONTROL_SHIFT_MOD, 56), False,),
(("71", 98, CONTROL_SHIFT_MOD, 56), False,),
],
)
def test_message_dialog_is_shown_on_duplicate_accel_assignment(
Expand Down Expand Up @@ -120,13 +120,13 @@ def test_message_dialog_is_shown_on_duplicate_accel_assignment(
"accel_params",
[
# 1) 'edit_tab_title' Ctrl+Alt+A
("9", 97, CONTROL_ALT_MOD, 38),
# 2) 'edit_terminal_title' Ctrl+Alt+A
("10", 97, CONTROL_ALT_MOD, 38),
# 2) 'edit_terminal_title' Ctrl+Alt+A
("11", 97, CONTROL_ALT_MOD, 38),
# 3) 'edit_window_title' F11
("11", 65480, Gdk.ModifierType(0), 95),
("12", 65480, Gdk.ModifierType(0), 95),
# 4) 'zoom_in' Shift+Ctrl+Z
("70", 122, CONTROL_SHIFT_MOD, 52),
("71", 122, CONTROL_SHIFT_MOD, 52),
],
)
def test_duplicate_accels_not_possible_to_set(accel_params):
Expand Down
Loading