From f6ca291bc1c96cf4acb3f92dabb80a3e5f506415 Mon Sep 17 00:00:00 2001 From: Edoardo Batini Date: Tue, 13 May 2008 03:06:16 +0200 Subject: [PATCH 01/19] Initial branch commit --- terminator | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 91 insertions(+), 3 deletions(-) diff --git a/terminator b/terminator index 2f5034cc..fe949a20 100755 --- a/terminator +++ b/terminator @@ -84,6 +84,9 @@ class TerminatorTerm: self.cwd = cwd or os.getcwd(); if not os.path.exists(self.cwd) or not os.path.isdir(self.cwd): self.cwd = pwd.getpwuid(os.getuid ())[5] + # EDO: could be: + # os.environ['PWD'] + self.clipboard = gtk.clipboard_get (gtk.gdk.SELECTION_CLIPBOARD) self.scrollbar_position = self.conf.scrollbar_position @@ -393,6 +396,27 @@ class TerminatorTerm: elif keyname in ('Up', 'Down', 'Left', 'Right'): self.terminator.resizeterm (self, keyname) return (True) + elif keyname == 'K': + print "KEY K pressed" + self.terminator.vertical_full(self, keyname) + return(True) + elif keyname == 'J': + print "KEY J pressed" + self.terminator.vertical_full_up(self, keyname) + return(True) + elif keyname == 'H': + print "KEY H pressed" + self.terminator.horizontal_full(self, keyname) + return(True) + elif keyname == 'L': + print "KEY L pressed" + self.terminator.horizontal_full_dx (self, keyname) + return(True) + elif keyname == 'G': + print "KEY G pressed" + self.terminator.restore_full (self, keyname) + return(True) + if keyname and (keyname == 'Tab' or keyname.endswith('_Tab')): if event.state == gtk.gdk.CONTROL_MASK: @@ -524,6 +548,8 @@ class TerminatorTerm: class Terminator: def __init__ (self, profile, command = None, fullscreen = False, maximise = False, borderless = False): + self.restore = [] + self.profile = profile self.command = command @@ -776,6 +802,10 @@ class Terminator: self.term_list[previous]._vte.grab_focus () def resizeterm (self, widget, keyname): + + print widget + print keyname + vertical = False if keyname in ('Up', 'Down'): vertical = True @@ -783,7 +813,10 @@ class Terminator: vertical = False else: return + parent = self.get_first_parent_paned(widget.get_box (),vertical) + print parent + if parent == None: return @@ -793,18 +826,73 @@ class Terminator: if keyname in ('Up', 'Down'): maxi = parent.get_child1().get_allocation().height + parent.get_child2().get_allocation().height - 1 - + print maxi else: maxi = parent.get_child1().get_allocation().width + parent.get_child2().get_allocation().width - 1 + print maxi + move = 10 + print move if keyname in ('Up', 'Left'): move = -10 + print move - move = max(2, parent.get_position() + move) + parent_position = parent.get_position() + print parent_position + move = max(2, parent_position + move) + print move move = min(maxi, move) - + print move parent.set_position(move) + def vertical_full (self, widget, keyname): + parent = self.get_first_parent_paned (widget.get_box (), True) + + if parent != None: + parent_position = parent.get_position() + + maxi = parent.get_child1().get_allocation().height + parent.get_child2().get_allocation().width - 1 + parent.set_position(maxi) + self.restore.append ((parent, parent_position)) + else: + return + + def horizontal_full (self, widget, keyname): + parent = self.get_first_parent_paned (widget.get_box (), False) + + if parent != None: + parent_position = parent.get_position() + maxi = parent.get_child1().get_allocation().height + parent.get_child2().get_allocation().width - 1 + parent.set_position(maxi) + self.restore.append ((parent, parent_position)) + else: + return + + def vertical_full_up (self, widget, keyname): + parent = self.get_first_parent_paned (widget.get_box (), True) + + if parent != None: + parent_position = parent.get_position() + parent.set_position(0) + self.restore.append ((parent, parent_position)) + else: + return + + def horizontal_full_dx (self, widget, keyname): + parent = self.get_first_parent_paned (widget.get_box (), False) + + if parent != None: + parent_position = parent.get_position() + parent.set_position(0) + self.restore.append ((parent, parent_position)) + else: + return + + def restore_full(self, widget, keyname): + move = self.restore.pop() + move[0].set_position(move[1]) + + def get_first_parent_paned (self, widget, vertical = None): """This method returns the first parent pane of a widget. if vertical is True returns the first VPaned From 559bd4ad3aac02524ea4f1fbf81d61f85afc6478 Mon Sep 17 00:00:00 2001 From: Edoardo Batini Date: Wed, 14 May 2008 02:33:28 +0200 Subject: [PATCH 02/19] - Git branch created --- .bzrignore | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 .bzrignore diff --git a/.bzrignore b/.bzrignore new file mode 100644 index 00000000..ee2b5eb8 --- /dev/null +++ b/.bzrignore @@ -0,0 +1,13 @@ +.git/branches +.git/COMMIT_EDITMSG +.git/config +.git/description +.git/HEAD +.git/hooks +.git/index +.git/info +.git/logs +.git/objects +.git/refs +.git +.gitignore From 01ce8d92fd9f73d42029f7a3c79e62f7cd97b55e Mon Sep 17 00:00:00 2001 From: Edoardo Batini Date: Wed, 14 May 2008 04:19:41 +0200 Subject: [PATCH 03/19] - New proof of concept for Single TerminatorTerm in Full-window - Full-window works, restore to previous layout works improperly --- terminator | 143 +++++++++++++++++++++++++---------------------------- 1 file changed, 68 insertions(+), 75 deletions(-) diff --git a/terminator b/terminator index fe949a20..e374473b 100755 --- a/terminator +++ b/terminator @@ -396,27 +396,6 @@ class TerminatorTerm: elif keyname in ('Up', 'Down', 'Left', 'Right'): self.terminator.resizeterm (self, keyname) return (True) - elif keyname == 'K': - print "KEY K pressed" - self.terminator.vertical_full(self, keyname) - return(True) - elif keyname == 'J': - print "KEY J pressed" - self.terminator.vertical_full_up(self, keyname) - return(True) - elif keyname == 'H': - print "KEY H pressed" - self.terminator.horizontal_full(self, keyname) - return(True) - elif keyname == 'L': - print "KEY L pressed" - self.terminator.horizontal_full_dx (self, keyname) - return(True) - elif keyname == 'G': - print "KEY G pressed" - self.terminator.restore_full (self, keyname) - return(True) - if keyname and (keyname == 'Tab' or keyname.endswith('_Tab')): if event.state == gtk.gdk.CONTROL_MASK: @@ -514,6 +493,20 @@ class TerminatorTerm: item = gtk.MenuItem () menu.append (item) + item = gtk.MenuItem (_("Maximize T_erminal")) + item.connect ("activate", lambda menu_item: self.terminator.hide_all_but_me (self)) + menu.append (item) + + item = gtk.MenuItem () + menu.append (item) + + item = gtk.MenuItem (_("Go B_ack")) + item.connect ("activate", lambda menu_item: self.terminator.show_back_others (self)) + menu.append (item) + + item = gtk.MenuItem () + menu.append (item) + item = gtk.ImageMenuItem (gtk.STOCK_CLOSE) item.connect ("activate", lambda menu_item: self.terminator.closeterm (self)) menu.append (item) @@ -604,7 +597,7 @@ class Terminator: # FIXME: This should be really be decided from some kind of profile term = (TerminatorTerm (self, self.profile, self.command)) self.term_list = [term] - + self.widget_history=[self.window, term] self.window.add (term.get_box ()) self.window.show () @@ -704,6 +697,17 @@ class Terminator: position = (vertical) and parent.allocation.height \ or parent.allocation.width + + # Code needed to store application widget structure. + # + # get widget index, add pane before her in widget_history + # and a terminal after her + + for n in range(len(self.widget_history)): + if self.widget_history[n] == widget: + self.widget_history.insert(n, pane) + self.widget_history.insert(n+2, terminal) + print self.widget_history if isinstance (parent, gtk.Paned): # We are inside a split term @@ -803,9 +807,6 @@ class Terminator: def resizeterm (self, widget, keyname): - print widget - print keyname - vertical = False if keyname in ('Up', 'Down'): vertical = True @@ -815,7 +816,6 @@ class Terminator: return parent = self.get_first_parent_paned(widget.get_box (),vertical) - print parent if parent == None: return @@ -826,73 +826,66 @@ class Terminator: if keyname in ('Up', 'Down'): maxi = parent.get_child1().get_allocation().height + parent.get_child2().get_allocation().height - 1 - print maxi else: maxi = parent.get_child1().get_allocation().width + parent.get_child2().get_allocation().width - 1 - print maxi move = 10 - print move if keyname in ('Up', 'Left'): move = -10 - print move + parent_position = parent.get_position() - print parent_position + move = max(2, parent_position + move) - print move + move = min(maxi, move) - print move + parent.set_position(move) - def vertical_full (self, widget, keyname): - parent = self.get_first_parent_paned (widget.get_box (), True) - - if parent != None: - parent_position = parent.get_position() - - maxi = parent.get_child1().get_allocation().height + parent.get_child2().get_allocation().width - 1 - parent.set_position(maxi) - self.restore.append ((parent, parent_position)) - else: + def hide_all_but_me (self, widget): + """Proof of concept: Maximize an instance of TerminatorTerm + Only first split is kept in memory... + """ + parent = widget.get_box ().get_parent () + ##TRY TO SHOW ONLY ONE AND KEEP PREVIOUS LAYOUT + if isinstance (parent, gtk.Window): + # We have just one term return - - def horizontal_full (self, widget, keyname): - parent = self.get_first_parent_paned (widget.get_box (), False) - - if parent != None: - parent_position = parent.get_position() - maxi = parent.get_child1().get_allocation().height + parent.get_child2().get_allocation().width - 1 - parent.set_position(maxi) - self.restore.append ((parent, parent_position)) else: - return + me = None + for n in self.widget_history: + if n == widget: + me = n + else: + try: + self.window.remove(n) + except: + self.window.remove(n.get_box()) + if me: + me.get_box ().reparent(self.window) - def vertical_full_up (self, widget, keyname): - parent = self.get_first_parent_paned (widget.get_box (), True) - - if parent != None: - parent_position = parent.get_position() - parent.set_position(0) - self.restore.append ((parent, parent_position)) + def show_back_others (self, widget): + """Proof of concept: Go back to previous application + widget structure. + Still positions are not stored in 'widget_history' list. + Maximizing first terminal in and restoring + previous layout works perfectly; maximizing second + terminal doesn't restore properly, yet! + """ + ## HERE TERMINALS AND PANES SHOULD POP BACK! + number_of_widgets = len(self.widget_history) + if number_of_widgets == 2: # just a gtk.Window and a TerminatorTerm + return else: + # Clean Window + for n in self.window.get_children(): + self.window.remove(n) + self.widget_history[1].pack1(self.widget_history[2].get_box()) + self.widget_history[1].pack1(self.widget_history[3].get_box()) + self.window.add(self.widget_history[1]) + self.window.show_all() return - def horizontal_full_dx (self, widget, keyname): - parent = self.get_first_parent_paned (widget.get_box (), False) - - if parent != None: - parent_position = parent.get_position() - parent.set_position(0) - self.restore.append ((parent, parent_position)) - else: - return - - def restore_full(self, widget, keyname): - move = self.restore.pop() - move[0].set_position(move[1]) - - def get_first_parent_paned (self, widget, vertical = None): """This method returns the first parent pane of a widget. if vertical is True returns the first VPaned From 8e2d3e997583ed09c39a0f45dba4148865f13ec4 Mon Sep 17 00:00:00 2001 From: Edoardo Batini Date: Thu, 15 May 2008 02:59:54 +0200 Subject: [PATCH 04/19] - Can maximize one terminal (full-window) and then restore to previous layout. - New pop-up menu items to test the feature --- .bzrignore | 3 ++ terminator | 122 +++++++++++++++++++++++------------------------------ 2 files changed, 55 insertions(+), 70 deletions(-) diff --git a/.bzrignore b/.bzrignore index ee2b5eb8..963f23c6 100644 --- a/.bzrignore +++ b/.bzrignore @@ -11,3 +11,6 @@ .git/refs .git .gitignore +build +build/bzr +status diff --git a/terminator b/terminator index e374473b..9fedd9af 100755 --- a/terminator +++ b/terminator @@ -84,9 +84,6 @@ class TerminatorTerm: self.cwd = cwd or os.getcwd(); if not os.path.exists(self.cwd) or not os.path.isdir(self.cwd): self.cwd = pwd.getpwuid(os.getuid ())[5] - # EDO: could be: - # os.environ['PWD'] - self.clipboard = gtk.clipboard_get (gtk.gdk.SELECTION_CLIPBOARD) self.scrollbar_position = self.conf.scrollbar_position @@ -497,9 +494,6 @@ class TerminatorTerm: item.connect ("activate", lambda menu_item: self.terminator.hide_all_but_me (self)) menu.append (item) - item = gtk.MenuItem () - menu.append (item) - item = gtk.MenuItem (_("Go B_ack")) item.connect ("activate", lambda menu_item: self.terminator.show_back_others (self)) menu.append (item) @@ -541,7 +535,6 @@ class TerminatorTerm: class Terminator: def __init__ (self, profile, command = None, fullscreen = False, maximise = False, borderless = False): - self.restore = [] self.profile = profile self.command = command @@ -597,7 +590,7 @@ class Terminator: # FIXME: This should be really be decided from some kind of profile term = (TerminatorTerm (self, self.profile, self.command)) self.term_list = [term] - self.widget_history=[self.window, term] + self.window.add (term.get_box ()) self.window.show () @@ -605,7 +598,7 @@ class Terminator: """ Maximize the Terminator window.""" self.window.maximize () - def toggle_fullscreen (self): + def fullscreen_toggle (self): """ Toggle the fullscreen state of the window. If it is in fullscreen state, it will be unfullscreened. If it is not, it will be set to fullscreen state. @@ -665,7 +658,7 @@ class Terminator: mask = gtk.gdk.CONTROL_MASK | gtk.gdk.SHIFT_MASK if (keyname == 'F11'): - self.toggle_fullscreen () + self.fullscreen_toggle () return (True) if (event.state & mask) == mask: @@ -678,67 +671,62 @@ class Terminator: def splitaxis (self, widget, vertical=True): """ Split the provided widget on the horizontal or vertical axis. """ - # create a new terminal and parent pane. terminal = TerminatorTerm (self, self.profile, None, widget.get_cwd()) pane = (vertical) and gtk.VPaned () or gtk.HPaned () - # get the parent of the provided terminal - parent = widget.get_box ().get_parent () + parent = widget.get_box ().get_parent () if isinstance (parent, gtk.Window): # We have just one term + # [Window, Terminal] widget.get_box ().reparent (pane) - pane.pack1 (widget.get_box (), True, True) pane.pack2 (terminal.get_box (), True, True) - parent.add (pane) - position = (vertical) and parent.allocation.height \ or parent.allocation.width - - # Code needed to store application widget structure. - # - # get widget index, add pane before her in widget_history - # and a terminal after her - - for n in range(len(self.widget_history)): - if self.widget_history[n] == widget: - self.widget_history.insert(n, pane) - self.widget_history.insert(n+2, terminal) - print self.widget_history + # After: + # [Window, Pane, OldTerminal, NewTerminal] + self.widgets.insert(0, pane) + self.widgets.append(terminal) if isinstance (parent, gtk.Paned): # We are inside a split term position = (vertical) and widget.get_box().allocation.height \ or widget.get_box().allocation.width - + ## ... Pane, ClickedTerminal, Terminal ... + ## becomes + ## ... Pane, Pane, ClickedTerminal, NewTerminal, Terminal] if (widget.get_box () == parent.get_child1 ()): widget.get_box ().reparent (pane) parent.pack1 (pane, True, True) + ## ... Pane, Terminal, ClickedTerminal ... + ## becomes + ## ... Pane, Terminal, Pane, ClickedTerminal, NewTerminal] else: widget.get_box ().reparent (pane) parent.pack2 (pane, True, True) - pane.pack1 (widget.get_box (), True, True) pane.pack2 (terminal.get_box (), True, True) + i = self.widgets.index(widget) + self.widgets.insert(i, pane) + self.widgets.insert(i+2, terminal) + # show all, set position of the divider pane.show () pane.set_position (position / 2) terminal.get_box ().show () - # insert the term reference into the list index = self.term_list.index (widget) self.term_list.insert (index + 1, terminal) - # make the new terminal grab the focus terminal._vte.grab_focus () - return (terminal) def closeterm (self, widget): + parent = widget.get_box ().get_parent () sibling = None @@ -748,6 +736,14 @@ class Terminator: self.on_destroy_event (parent, gtk.gdk.Event (gtk.gdk.DESTROY)) return + i = self.widgets.index(widget) + if isinstance(self.widgets[i-1], gtk.Paned): + del(self.widgets[i]) + del(self.widgets[i-1]) + else: + del(self.widgets[i]) + del(self.widgets[i-2]) + if isinstance (parent, gtk.Paned): index = self.term_list.index (widget) grandparent = parent.get_parent () @@ -806,7 +802,6 @@ class Terminator: self.term_list[previous]._vte.grab_focus () def resizeterm (self, widget, keyname): - vertical = False if keyname in ('Up', 'Down'): vertical = True @@ -816,7 +811,6 @@ class Terminator: return parent = self.get_first_parent_paned(widget.get_box (),vertical) - if parent == None: return @@ -833,58 +827,46 @@ class Terminator: if keyname in ('Up', 'Left'): move = -10 - - parent_position = parent.get_position() - move = max(2, parent_position + move) - move = min(maxi, move) parent.set_position(move) def hide_all_but_me (self, widget): """Proof of concept: Maximize an instance of TerminatorTerm - Only first split is kept in memory... """ - parent = widget.get_box ().get_parent () - ##TRY TO SHOW ONLY ONE AND KEEP PREVIOUS LAYOUT + parent = widget.get_box ().get_parent () if isinstance (parent, gtk.Window): # We have just one term return else: - me = None - for n in self.widget_history: - if n == widget: - me = n - else: - try: - self.window.remove(n) - except: - self.window.remove(n.get_box()) - if me: - me.get_box ().reparent(self.window) - - def show_back_others (self, widget): + self.window.remove(self.window.get_children()[0]) + widget.get_box().reparent(self.window) + + def show_back_others(self, widget): """Proof of concept: Go back to previous application widget structure. - Still positions are not stored in 'widget_history' list. - Maximizing first terminal in and restoring - previous layout works perfectly; maximizing second - terminal doesn't restore properly, yet! """ - ## HERE TERMINALS AND PANES SHOULD POP BACK! - number_of_widgets = len(self.widget_history) - if number_of_widgets == 2: # just a gtk.Window and a TerminatorTerm - return + for n in self.window.get_children(): + self.window.remove(n) + self.restore() + + def restore(self): + if isinstance(self.widgets[0], TerminatorTerm): + self.window.add (self.widgets[0].get_box ()) else: - # Clean Window - for n in self.window.get_children(): - self.window.remove(n) - self.widget_history[1].pack1(self.widget_history[2].get_box()) - self.widget_history[1].pack1(self.widget_history[3].get_box()) - self.window.add(self.widget_history[1]) - self.window.show_all() - return + self.window.add (self.restore_tree (self.widgets[0])) + self.window.show_all() + + def restore_tree(self, widget): + if isinstance(widget, TerminatorTerm): + return widget.get_box() + else: + i = self.widgets.index(widget) + widget.add1 (self.restore_tree (self.widgets[i+1])) + widget.add2 (self.restore_tree (self.widgets[i+2])) + widget.show() + return widget def get_first_parent_paned (self, widget, vertical = None): """This method returns the first parent pane of a widget. From b03616b766f7e3e4d2f1175c47fdcab931d44727 Mon Sep 17 00:00:00 2001 From: Edoardo Batini Date: Tue, 20 May 2008 16:11:40 +0200 Subject: [PATCH 05/19] Improvements to full-window. Should work for every terminal now. TODO: Killing full-window terminal --- terminator | 46 ++++++++++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/terminator b/terminator index 9fedd9af..617b1fa2 100755 --- a/terminator +++ b/terminator @@ -590,7 +590,7 @@ class Terminator: # FIXME: This should be really be decided from some kind of profile term = (TerminatorTerm (self, self.profile, self.command)) self.term_list = [term] - + self.widgets = [term] self.window.add (term.get_box ()) self.window.show () @@ -736,6 +736,7 @@ class Terminator: self.on_destroy_event (parent, gtk.gdk.Event (gtk.gdk.DESTROY)) return + ## Deletes terminal and pane from self.widgets list i = self.widgets.index(widget) if isinstance(self.widgets[i-1], gtk.Paned): del(self.widgets[i]) @@ -835,31 +836,44 @@ class Terminator: def hide_all_but_me (self, widget): """Proof of concept: Maximize an instance of TerminatorTerm """ - parent = widget.get_box ().get_parent () - if isinstance (parent, gtk.Window): - # We have just one term - return - else: - self.window.remove(self.window.get_children()[0]) - widget.get_box().reparent(self.window) - + self.window_child = self.window.get_children()[0] + self.old_parent = widget.get_box().get_parent() + self.foo = widget + self.bar = self.window_child + self.window.remove(self.window_child) + self.old_parent.remove(widget.get_box()) + self.window.add(widget.get_box()) + +# self.full_win.add(widget.get_box()) + self.window.show_all() + def show_back_others(self, widget): """Proof of concept: Go back to previous application widget structure. """ - for n in self.window.get_children(): - self.window.remove(n) - self.restore() + self.foo = widget + + self.window.remove(widget.get_box()) + self.window.add(self.window_child) + + self.old_parent.add(widget.get_box()) + self.window.show_all() def restore(self): - if isinstance(self.widgets[0], TerminatorTerm): - self.window.add (self.widgets[0].get_box ()) - else: - self.window.add (self.restore_tree (self.widgets[0])) + num_of_widgets = len(self.widgets) + if num_of_widgets % 2 == 0: + print "Error numer of widgets must be " + print + print "###################################################" + for element in self.widgets: + print element + print "###################################################" + self.window.add (self.restore_tree (self.widgets[0])) self.window.show_all() def restore_tree(self, widget): if isinstance(widget, TerminatorTerm): + print """RESTORING %s which is child of %s.""" % (widget, widget.get_box().get_parent()) return widget.get_box() else: i = self.widgets.index(widget) From e291f0a281acb37a798b0a9703588f3a2c54e6a2 Mon Sep 17 00:00:00 2001 From: Edoardo Batini Date: Tue, 20 May 2008 17:21:34 +0200 Subject: [PATCH 06/19] Resynced with 'trunk'. Removed self.widgets list --- terminator | 237 ++++++++++++++++++++++++++--------------------------- 1 file changed, 117 insertions(+), 120 deletions(-) diff --git a/terminator b/terminator index 617b1fa2..f2157f69 100755 --- a/terminator +++ b/terminator @@ -72,11 +72,12 @@ def openurl (url): except: pass -class TerminatorTerm: +class TerminatorTerm (gtk.VBox): matches = {} def __init__ (self, terminator, profile = None, command = None, cwd = None): + gtk.VBox.__init__ (self) self.terminator = terminator self.conf = terminator.conf self.command = command @@ -99,10 +100,9 @@ class TerminatorTerm: self._title.show() self._titlebox = gtk.EventBox() self._titlebox.add(self._title) - self._box = gtk.VBox () - self._box.show() - self._box.pack_start(self._titlebox, False) - self._box.pack_start(self._termbox) + self.show() + self.pack_start(self._titlebox, False) + self.pack_start(self._termbox) if len(self.terminator.term_list) > 0 and self.conf.titlebars: if len(self.terminator.term_list) == 1: self.terminator.term_list[0]._titlebox.show() @@ -145,10 +145,10 @@ class TerminatorTerm: self.add_matches() env_proxy = os.getenv ('http_proxy') - if not env_proxy: + if not env_proxy and self.conf.http_proxy: os.putenv ('http_proxy', self.conf.http_proxy) - self.spawn_child () + os.putenv ('COLORTERM', 'gnome-terminal') def add_matches (self, lboundry="[[:<:]]", rboundry="[[:>:]]"): userchars = "-A-Za-z0-9" @@ -173,6 +173,8 @@ class TerminatorTerm: def spawn_child (self, event=None): update_records = self.conf.update_records login = self.conf.login_shell + args = [] + shell = '' if self.command: args = self.command @@ -180,24 +182,53 @@ class TerminatorTerm: elif self.conf.use_custom_command: args = self.conf.custom_command.split () shell = args[0] - else: - shell = pwd.getpwuid (os.getuid ())[6] - args = [os.path.basename (shell)] + + if not os.path.exists (shell): + shell = os.getenv ('SHELL') or '' + if not os.path.exists (shell): + shell = pwd.getpwuid (os.getuid ())[6] or '' + if not os.path.exists (shell): + for i in ['bash','zsh','tcsh','ksh','csh','sh']: + shell = '/usr/bin/%s'%i + if not os.path.exists (shell): + shell = '/bin/%s'%i + if not os.path.exists (shell): + continue + else: + break + else: + break; + + if not os.path.exists (shell): + # Give up, we're completely stuck + print >> sys.stderr, _('Unable to find a shell') + gobject.timeout_add (100, self.terminator.closeterm, self) + return (-1) + + if not args: + args.append (shell) + + os.putenv ('WINDOWID', '%s'%self._vte.get_parent_window().xid) self._pid = self._vte.fork_command (command = shell, argv = args, envv = [], directory=self.cwd, loglastlog = login, logwtmp = update_records, logutmp = update_records) + if self._pid == -1: + print >>sys.stderr, _('Unable to start shell: ') + shell + return (-1) + def get_cwd (self): """ Return the current working directory of the subprocess. This function requires OS specific behaviours """ + cwd = None system = platform.system () if system == 'Linux': - cwd = os.path.realpath ('/proc/%s/cwd' % self._pid) - else: - # We don't have a child cwd getter for this platform, so let - # TerminatorTerm use its default - cwd = None + try: + cwd = os.path.realpath ('/proc/%s/cwd' % self._pid) + except: + pass + return (cwd) def reconfigure_vte (self): @@ -315,6 +346,19 @@ class TerminatorTerm: self.reconfigure_vte () def on_vte_button_press (self, term, event): + # Left mouse button + Ctrl while over a link should open it + mask = gtk.gdk.CONTROL_MASK + if (event.state & mask) == mask: + if event.button == 1: + url = self._vte.match_check (int (event.x / self._vte.get_char_width ()), int (event.y / self._vte.get_char_height ())) + if url: + if (url[0][0:7] != "mailto:") & (url[1] == self.matches['email']): + address = "mailto:" + url[0] + else: + address = url[0] + openurl ( address ) + return False + # Left mouse button should transfer focus to this vte widget if event.button == 1: self._vte.grab_focus () @@ -416,8 +460,8 @@ class TerminatorTerm: pangodesc.set_size (fontsize) self._vte.set_font (pangodesc) - def on_vte_popup_menu (self, term): - self.do_popup () + def on_vte_popup_menu (self, term, event): + self.do_popup (event) def do_popup (self, event = None): menu = self.create_popup_menu (event) @@ -530,12 +574,8 @@ class TerminatorTerm: if vte.get_window_title (): self.terminator.set_window_title("%s: %s" %(APP_NAME.capitalize(), vte.get_window_title ())) - def get_box (self): - return self._box - class Terminator: def __init__ (self, profile, command = None, fullscreen = False, maximise = False, borderless = False): - self.profile = profile self.command = command @@ -590,9 +630,10 @@ class Terminator: # FIXME: This should be really be decided from some kind of profile term = (TerminatorTerm (self, self.profile, self.command)) self.term_list = [term] - self.widgets = [term] - self.window.add (term.get_box ()) + + self.window.add (term) self.window.show () + term.spawn_child () def maximize (self): """ Maximize the Terminator window.""" @@ -671,63 +712,58 @@ class Terminator: def splitaxis (self, widget, vertical=True): """ Split the provided widget on the horizontal or vertical axis. """ + # create a new terminal and parent pane. terminal = TerminatorTerm (self, self.profile, None, widget.get_cwd()) pane = (vertical) and gtk.VPaned () or gtk.HPaned () + # get the parent of the provided terminal - parent = widget.get_box ().get_parent () + parent = widget.get_parent () if isinstance (parent, gtk.Window): # We have just one term - # [Window, Terminal] - widget.get_box ().reparent (pane) - pane.pack1 (widget.get_box (), True, True) - pane.pack2 (terminal.get_box (), True, True) + widget.reparent (pane) + + pane.pack1 (widget, True, True) + pane.pack2 (terminal, True, True) + parent.add (pane) + position = (vertical) and parent.allocation.height \ or parent.allocation.width - # After: - # [Window, Pane, OldTerminal, NewTerminal] - self.widgets.insert(0, pane) - self.widgets.append(terminal) if isinstance (parent, gtk.Paned): # We are inside a split term - position = (vertical) and widget.get_box().allocation.height \ - or widget.get_box().allocation.width - ## ... Pane, ClickedTerminal, Terminal ... - ## becomes - ## ... Pane, Pane, ClickedTerminal, NewTerminal, Terminal] - if (widget.get_box () == parent.get_child1 ()): - widget.get_box ().reparent (pane) - parent.pack1 (pane, True, True) - ## ... Pane, Terminal, ClickedTerminal ... - ## becomes - ## ... Pane, Terminal, Pane, ClickedTerminal, NewTerminal] - else: - widget.get_box ().reparent (pane) - parent.pack2 (pane, True, True) - pane.pack1 (widget.get_box (), True, True) - pane.pack2 (terminal.get_box (), True, True) + position = (vertical) and widget.allocation.height \ + or widget.allocation.width - i = self.widgets.index(widget) - self.widgets.insert(i, pane) - self.widgets.insert(i+2, terminal) + if (widget == parent.get_child1 ()): + widget.reparent (pane) + parent.pack1 (pane, True, True) + else: + widget.reparent (pane) + parent.pack2 (pane, True, True) + + pane.pack1 (widget, True, True) + pane.pack2 (terminal, True, True) # show all, set position of the divider pane.show () pane.set_position (position / 2) - terminal.get_box ().show () + terminal.show () + terminal.spawn_child () + # insert the term reference into the list index = self.term_list.index (widget) self.term_list.insert (index + 1, terminal) + # make the new terminal grab the focus terminal._vte.grab_focus () + return (terminal) def closeterm (self, widget): - - parent = widget.get_box ().get_parent () + parent = widget.get_parent () sibling = None if isinstance (parent, gtk.Window): @@ -736,23 +772,14 @@ class Terminator: self.on_destroy_event (parent, gtk.gdk.Event (gtk.gdk.DESTROY)) return - ## Deletes terminal and pane from self.widgets list - i = self.widgets.index(widget) - if isinstance(self.widgets[i-1], gtk.Paned): - del(self.widgets[i]) - del(self.widgets[i-1]) - else: - del(self.widgets[i]) - del(self.widgets[i-2]) - if isinstance (parent, gtk.Paned): index = self.term_list.index (widget) grandparent = parent.get_parent () # Discover sibling while all objects exist - if widget.get_box () == parent.get_child1 (): + if widget == parent.get_child1 (): sibling = parent.get_child2 () - if widget.get_box () == parent.get_child2 (): + if widget == parent.get_child2 (): sibling = parent.get_child1 () if not sibling: @@ -763,12 +790,12 @@ class Terminator: self.term_list.remove (widget) grandparent.remove (parent) sibling.reparent (grandparent) - widget.get_box ().destroy () + widget.destroy () parent.destroy () if not isinstance (sibling, gtk.Paned): for term in self.term_list: - if term.get_box () == sibling: + if term == sibling: term._vte.grab_focus () break else: @@ -810,8 +837,7 @@ class Terminator: vertical = False else: return - - parent = self.get_first_parent_paned(widget.get_box (),vertical) + parent = self.get_first_parent_paned(widget,vertical) if parent == None: return @@ -821,67 +847,18 @@ class Terminator: if keyname in ('Up', 'Down'): maxi = parent.get_child1().get_allocation().height + parent.get_child2().get_allocation().height - 1 + else: maxi = parent.get_child1().get_allocation().width + parent.get_child2().get_allocation().width - 1 - move = 10 if keyname in ('Up', 'Left'): move = -10 - move = max(2, parent_position + move) + move = max(2, parent.get_position() + move) move = min(maxi, move) parent.set_position(move) - def hide_all_but_me (self, widget): - """Proof of concept: Maximize an instance of TerminatorTerm - """ - self.window_child = self.window.get_children()[0] - self.old_parent = widget.get_box().get_parent() - self.foo = widget - self.bar = self.window_child - self.window.remove(self.window_child) - self.old_parent.remove(widget.get_box()) - self.window.add(widget.get_box()) - -# self.full_win.add(widget.get_box()) - self.window.show_all() - - def show_back_others(self, widget): - """Proof of concept: Go back to previous application - widget structure. - """ - self.foo = widget - - self.window.remove(widget.get_box()) - self.window.add(self.window_child) - - self.old_parent.add(widget.get_box()) - self.window.show_all() - - def restore(self): - num_of_widgets = len(self.widgets) - if num_of_widgets % 2 == 0: - print "Error numer of widgets must be " - print - print "###################################################" - for element in self.widgets: - print element - print "###################################################" - self.window.add (self.restore_tree (self.widgets[0])) - self.window.show_all() - - def restore_tree(self, widget): - if isinstance(widget, TerminatorTerm): - print """RESTORING %s which is child of %s.""" % (widget, widget.get_box().get_parent()) - return widget.get_box() - else: - i = self.widgets.index(widget) - widget.add1 (self.restore_tree (self.widgets[i+1])) - widget.add2 (self.restore_tree (self.widgets[i+2])) - widget.show() - return widget - def get_first_parent_paned (self, widget, vertical = None): """This method returns the first parent pane of a widget. if vertical is True returns the first VPaned @@ -902,6 +879,26 @@ class Terminator: for term in self.term_list: term.reconfigure_vte () + def hide_all_but_me (self, widget): + """Proof of concept: Maximize to full window + an instance of TerminatorTerm. + """ + self.window_child = self.window.get_children()[0] + self.old_parent = widget.get_parent() + self.window.remove(self.window_child) + self.old_parent.remove(widget) + self.window.add(widget) + self.window.show_all() + + def show_back_others(self, widget): + """Proof of concept: Go back to previous application + widget structure. + """ + self.window.remove(widget) + self.window.add(self.window_child) + self.old_parent.add(widget) + self.window.show_all() + if __name__ == '__main__': def execute_cb (option, opt, value, parser): From 21ab156941ee7e74111e4ea6e9b708a6bd640aa4 Mon Sep 17 00:00:00 2001 From: Edoardo Batini Date: Tue, 20 May 2008 19:25:54 +0200 Subject: [PATCH 07/19] Closing full window terminal allowed. --- terminator | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/terminator b/terminator index f2157f69..a5f5683b 100755 --- a/terminator +++ b/terminator @@ -576,9 +576,11 @@ class TerminatorTerm (gtk.VBox): class Terminator: def __init__ (self, profile, command = None, fullscreen = False, maximise = False, borderless = False): + self.profile = profile self.command = command - + + self._fullwindow = False self._fullscreen = False self.term_list = [] stores = [] @@ -763,6 +765,9 @@ class Terminator: return (terminal) def closeterm (self, widget): + if self._fullwindow: + self.show_back_others(widget) + parent = widget.get_parent () sibling = None @@ -889,6 +894,7 @@ class Terminator: self.old_parent.remove(widget) self.window.add(widget) self.window.show_all() + self._fullwindow = True def show_back_others(self, widget): """Proof of concept: Go back to previous application @@ -898,6 +904,7 @@ class Terminator: self.window.add(self.window_child) self.old_parent.add(widget) self.window.show_all() + self._fullwindow = False if __name__ == '__main__': From e3bc45303145c3078684d374ea084ad51ea00458 Mon Sep 17 00:00:00 2001 From: Edoardo Batini Date: Tue, 20 May 2008 22:28:48 +0200 Subject: [PATCH 08/19] I Always forget something! --- terminator | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/terminator b/terminator index a5f5683b..314de5f5 100755 --- a/terminator +++ b/terminator @@ -534,12 +534,8 @@ class TerminatorTerm (gtk.VBox): item = gtk.MenuItem () menu.append (item) - item = gtk.MenuItem (_("Maximize T_erminal")) - item.connect ("activate", lambda menu_item: self.terminator.hide_all_but_me (self)) - menu.append (item) - - item = gtk.MenuItem (_("Go B_ack")) - item.connect ("activate", lambda menu_item: self.terminator.show_back_others (self)) + item = gtk.MenuItem (_("M_aximize/Unmaximize")) + item.connect ("activate", lambda menu_item: self.terminator.fullwindow (self)) menu.append (item) item = gtk.MenuItem () @@ -884,12 +880,20 @@ class Terminator: for term in self.term_list: term.reconfigure_vte () + def fullwindow(self, widget): + if not self._fullwindow: + self.hide_all_but_me(widget) + else: + self.show_back_others(widget) + def hide_all_but_me (self, widget): """Proof of concept: Maximize to full window an instance of TerminatorTerm. """ - self.window_child = self.window.get_children()[0] self.old_parent = widget.get_parent() + if isinstance(self.old_parent, gtk.Window): + return + self.window_child = self.window.get_children()[0] self.window.remove(self.window_child) self.old_parent.remove(widget) self.window.add(widget) @@ -900,12 +904,15 @@ class Terminator: """Proof of concept: Go back to previous application widget structure. """ - self.window.remove(widget) - self.window.add(self.window_child) - self.old_parent.add(widget) - self.window.show_all() - self._fullwindow = False - + if self._fullwindow: + self.window.remove(widget) + self.window.add(self.window_child) + self.old_parent.add(widget) + self.window.show_all() + self._fullwindow = False + return + else: + return if __name__ == '__main__': def execute_cb (option, opt, value, parser): From 3086c7542916f86e59db33ce4de0737f81203914 Mon Sep 17 00:00:00 2001 From: Edoardo Batini Date: Thu, 22 May 2008 15:01:02 +0200 Subject: [PATCH 09/19] Splitaxis not allowed while in full-window mode --- terminator | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/terminator b/terminator index 314de5f5..3f54332b 100755 --- a/terminator +++ b/terminator @@ -710,7 +710,9 @@ class Terminator: def splitaxis (self, widget, vertical=True): """ Split the provided widget on the horizontal or vertical axis. """ - + #should disable splitaxis menu instead? + if self._fullwindow: + return # create a new terminal and parent pane. terminal = TerminatorTerm (self, self.profile, None, widget.get_cwd()) pane = (vertical) and gtk.VPaned () or gtk.HPaned () From 13b8778d0b745c86e3193d03303ac3c173d1d492 Mon Sep 17 00:00:00 2001 From: Edoardo Batini Date: Thu, 22 May 2008 16:37:59 +0200 Subject: [PATCH 10/19] Merged with main branch [with chantra's tab] --- ChangeLog | 15 +- TODO | 1 - debian/copyright | 6 +- doc/terminator.1 | 2 +- setup.py | 2 +- terminator | 540 ++++++++++++++++-- terminatorlib/__init__.py | 0 .../config.py | 8 +- terminatorlib/encoding.py | 108 ++++ terminatorlib/freebsd.py | 83 +++ 10 files changed, 718 insertions(+), 47 deletions(-) create mode 100644 terminatorlib/__init__.py rename terminatorconfig.py => terminatorlib/config.py (97%) create mode 100644 terminatorlib/encoding.py create mode 100644 terminatorlib/freebsd.py diff --git a/ChangeLog b/ChangeLog index 6ae60bf5..edc3e1f0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,8 +3,19 @@ terminator 0.9: * Added kwybindings for terms size and scrollbar manipulation. Thanks Emmanuel Bretelle. * Completely revamped config system which now transparently makes use - of gconf settings if they are available, falls back to sensible - defaults if not, and can be overridden entirely by ~/.terminatorrc + of gconf settings if they are available, falls back to sensible + defaults if not, and can be overridden entirely by ~/.terminatorrc + * New application icon from Cory Kontros + * FreeBSD support (thanks to Thomas Hurst) + * Watch the system monospace font setting. Closes LP #197960 + * Proxy support (via GNOME and $http_proxy) + * GConf backend now caches + * Fix redundant title when there is only one Term. Closes LP#215210 + * Try much harder to find a usable shell + * Support encodings a-la GNOME Terminal + * Move python support code to a terminatorlib module + * Tab support + * Drag & Drop support terminator 0.8.1: * Fixed ChangeLog diff --git a/TODO b/TODO index 3e66cca9..64a16735 100644 --- a/TODO +++ b/TODO @@ -1,2 +1 @@ * Edit doc/terminatorrc.5 manpage to contain the information about the options -* Write a Tab feature for terminator diff --git a/debian/copyright b/debian/copyright index 79527aef..70c0d016 100644 --- a/debian/copyright +++ b/debian/copyright @@ -9,9 +9,13 @@ Upstream Authors: Huang He Kees Cook Thomas Meire + Nicolas Valcarcel + Emmanuel Bretelle + Chris Oattes Artwork: - Cristian Grada - Drew our icon and licenced it to us under this licence + Cory Kontros - Produced our current icon under the CC-by-SA licence + Cristian Grada - Drew our original icon and licenced it to us under this licence Translations: Thomas Meire diff --git a/doc/terminator.1 b/doc/terminator.1 index 5a3d5366..9dd051d0 100644 --- a/doc/terminator.1 +++ b/doc/terminator.1 @@ -85,7 +85,7 @@ Toggle fullscreen .SH "SEE ALSO" .BR gnome\-terminal(1),terminatorrc(5) .SH "AUTHOR" -Terminator was written by Chris Jones +Terminator was written by Chris Jones and others. .PP This manual page was written by Chris Jones for the Ubuntu project (but may be used by others). diff --git a/setup.py b/setup.py index a611dd46..842107e5 100755 --- a/setup.py +++ b/setup.py @@ -84,7 +84,7 @@ setup(name='Terminator', ('share/icons/hicolor/24x24/apps', glob.glob('data/icons/24x24/apps/*.png')), ('share/icons/hicolor/48x48/apps', glob.glob('data/icons/48x48/apps/*.png')), ], - py_modules=['terminatorconfig'], + packages=['terminatorlib'], cmdclass={'build': BuildData, 'install_data': InstallData} ) diff --git a/terminator b/terminator index 3f54332b..645a9302 100755 --- a/terminator +++ b/terminator @@ -35,8 +35,25 @@ except: # import unix-lib import pwd +TARGET_TYPE_VTE = 8 + # import our configuration loader -import terminatorconfig +from terminatorlib import config +from terminatorlib.config import dbg + +#import encoding list +from terminatorlib.encoding import TerminatorEncoding + +# Sort out cwd detection code, if available +pid_get_cwd = lambda pid: None +if platform.system() == 'FreeBSD': + try: + from terminatorlib import freebsd + pid_get_cwd = lambda pid: freebsd.get_process_cwd(pid) + except: + pass +elif platform.system == 'Linux': + pid_get_cwd = lambda pid: os.path.realpath ('/proc/%s/cwd' % pid) # import gtk libs # check just in case anyone runs it on a non-gnome system. @@ -121,10 +138,26 @@ class TerminatorTerm (gtk.VBox): packfunc (self._vte) packfunc (self._scrollbar, False) - + self._vte.connect ("key-press-event", self.on_vte_key_press) self._vte.connect ("button-press-event", self.on_vte_button_press) self._vte.connect ("popup-menu", self.on_vte_popup_menu) + + """drag and drop""" + srcvtetargets = [ ( "vte", gtk.TARGET_SAME_APP, TARGET_TYPE_VTE ) ] + dsttargets = [ ( "vte", gtk.TARGET_SAME_APP, TARGET_TYPE_VTE ), ('text/plain', 0, 0) , ("STRING", 0, 0), ("COMPOUND_TEXT", 0, 0)] + self._vte.drag_source_set( gtk.gdk.CONTROL_MASK | gtk.gdk.BUTTON3_MASK, srcvtetargets, gtk.gdk.ACTION_MOVE) + self._titlebox.drag_source_set( gtk.gdk.BUTTON1_MASK, srcvtetargets, gtk.gdk.ACTION_MOVE) + #self._vte.drag_dest_set(gtk.DEST_DEFAULT_MOTION | gtk.DEST_DEFAULT_HIGHLIGHT |gtk.DEST_DEFAULT_DROP ,dsttargets, gtk.gdk.ACTION_MOVE) + self._vte.drag_dest_set(gtk.DEST_DEFAULT_MOTION | gtk.DEST_DEFAULT_HIGHLIGHT |gtk.DEST_DEFAULT_DROP ,dsttargets, gtk.gdk.ACTION_MOVE) + self._vte.connect("drag-begin", self.on_drag_begin, self) + self._titlebox.connect("drag-begin", self.on_drag_begin, self) + self._vte.connect("drag-data-get", self.on_drag_data_get, self) + self._titlebox.connect("drag-data-get", self.on_drag_data_get, self) + #for testing purpose: drag-motion + self._vte.connect("drag-motion", self.on_drag_motion, self) + self._vte.connect("drag-data-received", self.on_drag_data_received, self) + self._vte.connect ("composited-changed", self.on_composited_changed) self._vte.connect ("window-title-changed", self.on_vte_title_change) self._vte.connect ("grab-focus", self.on_vte_focus) @@ -150,6 +183,146 @@ class TerminatorTerm (gtk.VBox): os.putenv ('COLORTERM', 'gnome-terminal') + def on_drag_begin(self, widget, drag_context, data): + dbg ('Drag begins') + if os.path.exists("/usr/share/icons/hicolor/48x48/apps/terminator.png"): + widget.drag_source_set_icon_pixbuf( gtk.gdk.pixbuf_new_from_file("/usr/share/icons/hicolor/48x48/apps/terminator.png")) + + def on_drag_data_get(self,widget, drag_context, selection_data, info, time, data): + dbg ("Drag data get") + selection_data.set("vte",info, str(data.terminator.term_list.index (self))) + + + def on_drag_motion(self, widget, drag_context, x, y, time, data): + dbg ("Drag Motion on ") + """ +x-special/gnome-icon-list +text/uri-list +UTF8_STRING +COMPOUND_TEXT +TEXT +STRING +text/plain;charset=utf-8 +text/plain;charset=UTF-8 +text/plain + """ + + if 'text/plain' in drag_context.targets: + #copy text from another widget + return + srcwidget = drag_context.get_source_widget() + if (isinstance(srcwidget, gtk.EventBox) and srcwidget == self._titlebox) or widget == srcwidget: + #on self + return + + + alloc = widget.allocation + rect = gtk.gdk.Rectangle(0, 0, alloc.width, alloc.height) + widget.window.invalidate_rect(rect, True) + widget.window.process_updates(True) + + context = widget.window.cairo_create() + if self.conf.use_theme_colors: + color = self._vte.get_style ().text[gtk.STATE_NORMAL] + else: + color = gtk.gdk.color_parse (self.conf.foreground_color) + + + context.set_source_rgba(color.red, color.green, color.blue, 0.5) + + pos = self.get_location(widget, x, y) + topleft = (0,0) + topright = (alloc.width,0) + topmiddle = (alloc.width/2,0) + bottomleft = (0, alloc.height) + bottomright = (alloc.width,alloc.height) + bottommiddle = (alloc.width/2, alloc.height) + middle = (alloc.width/2, alloc.height/2) + middleleft = (0, alloc.height/2) + middleright = (alloc.width, alloc.height/2) + #print "%f %f %d %d" %(coef1, coef2, b1,b2) + coord = () + if pos == "right": + coord = (topright, topmiddle, bottommiddle, bottomright) + if pos == "top": + coord = (topleft, topright, middleright , middleleft) + if pos == "left": + coord = (topleft, topmiddle, bottommiddle, bottomleft) + if pos == "bottom": + coord = (bottomleft, bottomright, middleright , middleleft) + + if len(coord) > 0 : + context.move_to(coord[len(coord)-1][0],coord[len(coord)-1][1]) + for i in coord: + context.line_to(i[0],i[1]) + + context.fill() + + + def on_drag_drop(self, widget, drag_context, x, y, time): + parent = widget.get_parent() + dbg ('Drag drop on %s'%parent) + + def on_drag_data_received(self, widget, drag_context, x, y, selection_data, info, time, data): + dbg ("Drag Data Received") + if selection_data.type == 'text/plain': + #copy text to destination + #print "%s %s" % (selection_data.type, selection_data.target) + txt = selection_data.data.strip() + if txt[0:7] == "file://": + txt = "'%s'" % txt[7:] + self._vte.feed_child(txt) + return + + widgetsrc = data.terminator.term_list[int(selection_data.data)] + srcvte = drag_context.get_source_widget() + #check if computation requireds + if (isinstance(srcvte, gtk.EventBox) and srcvte == self._titlebox) or srcvte == widget: + dbg (" on itself") + return + + srchbox = widgetsrc + dsthbox = widget.get_parent().get_parent() + + dstpaned = dsthbox.get_parent() + srcpaned = srchbox.get_parent() + if isinstance(dstpaned, gtk.Window) and isinstance(srcpaned, gtk.Window): + dbg (" Only one terminal") + return + pos = self.get_location(widget, x, y) + + data.terminator.remove(widgetsrc) + data.terminator.add(self, widgetsrc,pos) + return + + def get_location(self, vte, x, y): + pos = "" + #get the diagonales function for the receiving widget + coef1 = float(vte.allocation.height)/float(vte.allocation.width) + coef2 = -float(vte.allocation.height)/float(vte.allocation.width) + b1 = 0 + b2 = vte.allocation.height + #determine position in rectangle + """ + -------- + |\ /| + | \ / | + | \/ | + | /\ | + | / \ | + |/ \| + -------- + """ + if (x*coef1 + b1 > y ) and (x*coef2 + b2 < y ): + pos = "right" + if (x*coef1 + b1 > y ) and (x*coef2 + b2 > y ): + pos = "top" + if (x*coef1 + b1 < y ) and (x*coef2 + b2 > y ): + pos = "left" + if (x*coef1 + b1 < y ) and (x*coef2 + b2 < y ): + pos = "bottom" + return pos + def add_matches (self, lboundry="[[:<:]]", rboundry="[[:>:]]"): userchars = "-A-Za-z0-9" passchars = "-A-Za-z0-9,?;.:/!%$^*&~\"#'" @@ -220,16 +393,8 @@ class TerminatorTerm (gtk.VBox): """ Return the current working directory of the subprocess. This function requires OS specific behaviours """ - cwd = None - system = platform.system () - if system == 'Linux': - try: - cwd = os.path.realpath ('/proc/%s/cwd' % self._pid) - except: - pass - - return (cwd) + return (pid_get_cwd(self._pid)) def reconfigure_vte (self): # Set our emulation @@ -364,8 +529,8 @@ class TerminatorTerm (gtk.VBox): self._vte.grab_focus () return False - # Right mouse button should display a context menu - if event.button == 3: + # Right mouse button should display a context menu if ctrl not pressed + if event.button == 3 and event.state & gtk.gdk.CONTROL_MASK == 0: self.do_popup (event) return True @@ -434,10 +599,22 @@ class TerminatorTerm (gtk.VBox): elif keyname == 'S': self.do_scrollbar_toggle () return (True) + elif keyname == 'T': + self.terminator.newtab(self) + return (True) elif keyname in ('Up', 'Down', 'Left', 'Right'): self.terminator.resizeterm (self, keyname) return (True) + mask = gtk.gdk.CONTROL_MASK + if (event.state & mask) == mask: + if keyname == 'Page_Down': + self.terminator.next_tab(self) + return (True) + elif keyname == 'Page_Up': + self.terminator.previous_tab(self) + return (True) + if keyname and (keyname == 'Tab' or keyname.endswith('_Tab')): if event.state == gtk.gdk.CONTROL_MASK: self.terminator.go_next (self) @@ -520,6 +697,8 @@ class TerminatorTerm (gtk.VBox): item.connect ("toggled", lambda menu_item: self.do_title_toggle ()) menu.append (item) + self._do_encoding_items (menu) + item = gtk.MenuItem () menu.append (item) @@ -530,6 +709,10 @@ class TerminatorTerm (gtk.VBox): item = gtk.MenuItem (_("Split V_ertically")) item.connect ("activate", lambda menu_item: self.terminator.splitaxis (self, True)) menu.append (item) + + item = gtk.MenuItem (_("Open _Tab")) + item.connect ("activate", lambda menu_item: self.terminator.newtab (self)) + menu.append (item) item = gtk.MenuItem () menu.append (item) @@ -548,6 +731,61 @@ class TerminatorTerm (gtk.VBox): menu.show_all () return menu + def on_encoding_change (self, widget, encoding): + current = self._vte.get_encoding () + if current != encoding: + dbg ('Setting Encoding to: %s'%encoding) + self._vte.set_encoding (encoding) + + def _do_encoding_items (self, menu): + active_encodings = self.conf.active_encodings + item = gtk.MenuItem (_("Encodings")) + menu.append (item) + submenu = gtk.Menu () + item.set_submenu (submenu) + + current_encoding = self._vte.get_encoding () + group = None + for encoding in active_encodings: + radioitem = gtk.RadioMenuItem (group, _(encoding)) + if group is None: + group = radioitem + + if encoding == current_encoding: + radioitem.set_active (True) + + radioitem.connect ('activate', self.on_encoding_change, encoding) + submenu.append (radioitem) + + item = gtk.MenuItem (_("Other Encodings")) + submenu.append (item) + #second level + + submenu = gtk.Menu () + item.set_submenu (submenu) + encodings = TerminatorEncoding ().get_list () + encodings.sort (lambda x, y: cmp (x[2].lower (), y[2].lower ())) + group = None + + for encoding in encodings: + if encoding[1] in active_encodings: + continue + + if encoding[1] is None: + label = "%s %s"%(encoding[2], self._vte.get_encoding ()) + else: + label = "%s %s"%(encoding[2], encoding[1]) + + radioitem = gtk.RadioMenuItem (group, label) + if group is None: + group = radioitem + + if encoding[1] == current_encoding: + radioitem.set_active (True) + + radioitem.connect ('activate', self.on_encoding_change, encoding[1]) + submenu.append (radioitem) + def on_vte_title_change(self, vte): if self.conf.titletips: vte.set_property ("has-tooltip", True) @@ -555,6 +793,10 @@ class TerminatorTerm (gtk.VBox): #set the title anyhow, titlebars setting only show/hide the label self._title.set_text(vte.get_window_title ()) self.terminator.set_window_title("%s: %s" %(APP_NAME.capitalize(), vte.get_window_title ())) + notebookpage = self.terminator.get_first_notebook_page(vte) + while notebookpage != None: + notebookpage[0].set_tab_label_text(notebookpage[1], vte.get_window_title ()) + notebookpage = self.terminator.get_first_notebook_page(notebookpage[0]) def on_vte_focus_in(self, vte, event): self._titlebox.modify_bg(gtk.STATE_NORMAL,self.terminator.window.get_style().bg[gtk.STATE_SELECTED]) @@ -569,7 +811,14 @@ class TerminatorTerm (gtk.VBox): def on_vte_focus(self, vte): if vte.get_window_title (): self.terminator.set_window_title("%s: %s" %(APP_NAME.capitalize(), vte.get_window_title ())) - + notebookpage = self.terminator.get_first_notebook_page(vte) + while notebookpage != None: + notebookpage[0].set_tab_label_text(notebookpage[1], vte.get_window_title ()) + notebookpage = self.terminator.get_first_notebook_page(notebookpage[0]) + + def destroy(self): + self._vte.destroy() + class Terminator: def __init__ (self, profile, command = None, fullscreen = False, maximise = False, borderless = False): @@ -580,17 +829,17 @@ class Terminator: self._fullscreen = False self.term_list = [] stores = [] - stores.append (terminatorconfig.TerminatorConfValuestoreRC ()) + stores.append (config.TerminatorConfValuestoreRC ()) try: import gconf - store = terminatorconfig.TerminatorConfValuestoreGConf () + store = config.TerminatorConfValuestoreGConf () store.set_reconfigure_callback (self.reconfigure_vtes) stores.append (store) except: pass - self.conf = terminatorconfig.TerminatorConfig (stores) + self.conf = config.TerminatorConfig (stores) self.window = gtk.Window () self.window.set_title (APP_NAME.capitalize()) @@ -704,17 +953,20 @@ class Terminator: if keyname == 'Q': if not self.on_delete_event (window, gtk.gdk.Event (gtk.gdk.DELETE)): self.on_destroy_event (window, gtk.gdk.Event (gtk.gdk.DESTROY)) - + def set_window_title(self, title): + """ + Modifies Terminator window title + """ self.window.set_title(title) - def splitaxis (self, widget, vertical=True): - """ Split the provided widget on the horizontal or vertical axis. """ - #should disable splitaxis menu instead? - if self._fullwindow: - return + def add(self, widget, terminal, pos = "bottom"): + """ + Add a term to another at position pos + """ + vertical = pos in ("top", "bottom") + # create a new terminal and parent pane. - terminal = TerminatorTerm (self, self.profile, None, widget.get_cwd()) pane = (vertical) and gtk.VPaned () or gtk.HPaned () # get the parent of the provided terminal @@ -723,15 +975,42 @@ class Terminator: if isinstance (parent, gtk.Window): # We have just one term widget.reparent (pane) - - pane.pack1 (widget, True, True) - pane.pack2 (terminal, True, True) - + if pos in ("top", "left"): + pane.remove(widget) + pane.pack1 (terminal, True, True) + pane.pack2 (widget, True, True) + else: + pane.pack1 (widget, True, True) + pane.pack2 (terminal, True, True) parent.add (pane) position = (vertical) and parent.allocation.height \ or parent.allocation.width + if isinstance (parent, gtk.Notebook): + page = -1 + for i in range(0, parent.get_n_pages()): + if parent.get_nth_page(i) == widget: + page = i + break + widget.reparent (pane) + if pos in ("top", "left"): + pane.remove(widget) + pane.pack1 (terminal, True, True) + pane.pack2 (widget, True, True) + else: + pane.pack1 (widget, True, True) + pane.pack2 (terminal, True, True) + #parent.remove_page(page) + pane.show() + parent.insert_page(pane, None, page) + parent.set_tab_label_text(pane, widget._vte.get_window_title()) + parent.set_tab_label_packing(pane, True, True, gtk.PACK_START) + parent.set_current_page(page) + + + position = (vertical) and parent.allocation.height \ + or parent.allocation.width if isinstance (parent, gtk.Paned): # We are inside a split term position = (vertical) and widget.allocation.height \ @@ -744,6 +1023,14 @@ class Terminator: widget.reparent (pane) parent.pack2 (pane, True, True) + if pos in ("top", "left"): + pane.remove(widget) + pane.pack1 (terminal, True, True) + pane.pack2 (widget, True, True) + else: + pane.pack1 (widget, True, True) + pane.pack2 (terminal, True, True) + pane.pack1 (widget, True, True) pane.pack2 (terminal, True, True) @@ -762,7 +1049,75 @@ class Terminator: return (terminal) - def closeterm (self, widget): + def on_page_reordered(self, notebook, child, page_num): + dbg ("Reordered: %d"%page_num) + + def newtab(self,widget): + terminal = TerminatorTerm (self, self.profile, None, widget.get_cwd()) + widgetbox = widget + parent = widgetbox.get_parent () + + if isinstance(parent, gtk.Paned) or isinstance(parent, gtk.Window): + #no notebook yet. + notebook = gtk.Notebook() + notebook.connect('page-reordered',self.on_page_reordered) + notebook.set_property('homogeneous', True) + notebook.set_tab_reorderable(widgetbox, True) + + if isinstance(parent, gtk.Paned): + if parent.get_child1() == widgetbox: + widgetbox.reparent(notebook) + parent.pack1(notebook) + else: + widgetbox.reparent(notebook) + parent.pack2(notebook) + elif isinstance(parent, gtk.Window): + widgetbox.reparent(notebook) + parent.add(notebook) + notebook.set_tab_reorderable(widgetbox,True) + notebooklabel = "" + if widget._vte.get_window_title() is not None: + notebooklabel = widget._vte.get_window_title() + notebook.set_tab_label_text(widgetbox, notebooklabel) + notebook. set_tab_label_packing(widgetbox, True, True, gtk.PACK_START) + notebook.show() + elif isinstance(parent, gtk.Notebook): + notebook = parent + else: + return (False) + + notebook.append_page(terminal,terminal._vte.get_window_title()) + notebook. set_tab_label_packing(terminal, True, True, gtk.PACK_START) + notebook.set_tab_reorderable(terminal,True) + notebook.set_current_page(-1) + index = self.term_list.index(widget) + self.term_list.insert (index + 1, terminal) + terminal.show () + terminal.spawn_child () + terminal._vte.grab_focus () + return (True) + + + return terminal + + def splitaxis (self, widget, vertical=True): + """ Split the provided widget on the horizontal or vertical axis. """ + + #should disable splitaxis menu instead? + if self._fullwindow: + return + + # create a new terminal and parent pane. + terminal = TerminatorTerm (self, self.profile, None, widget.get_cwd()) + pos = vertical and "bottom" or "right" + self.add(widget, terminal, pos) + terminal.show () + terminal.spawn_child () + return terminal + + def remove(self, widget): + """Remove a TerminatorTerm from the Terminator view and terms list + Returns True on success, False on failure""" if self._fullwindow: self.show_back_others(widget) @@ -788,14 +1143,27 @@ class Terminator: if not sibling: # something is wrong, give up print >> sys.stderr, "Error: %s is not a child of %s"%(widget, parent) - return + return False - self.term_list.remove (widget) - grandparent.remove (parent) - sibling.reparent (grandparent) - widget.destroy () + parent.remove(widget) + if isinstance(grandparent, gtk.Notebook): + page = -1 + for i in range(0, grandparent.get_n_pages()): + if grandparent.get_nth_page(i) == parent: + page = i + break + parent.remove(sibling) + grandparent.remove_page(page) + grandparent.insert_page(sibling, None,page) + grandparent.set_tab_label_packing(sibling, True, True, gtk.PACK_START) + + else: + grandparent.remove (parent) + sibling.reparent (grandparent) + grandparent.resize_children() parent.destroy () - + self.term_list.remove (widget) + if not isinstance (sibling, gtk.Paned): for term in self.term_list: if term == sibling: @@ -804,10 +1172,39 @@ class Terminator: else: if index == 0: index = 1 self.term_list[index - 1]._vte.grab_focus () - if len(self.term_list) == 1: - self.term_list[0]._titlebox.hide() + elif isinstance (parent, gtk.Notebook): + parent.remove(widget) + nbpages = parent.get_n_pages() + index = self.term_list.index (widget) + self.term_list.remove (widget) + if nbpages == 1: + sibling = parent.get_nth_page(0) + parent.remove(sibling) + gdparent = parent.get_parent() + if isinstance(gdparent, gtk.Window): + gdparent.remove(parent) + gdparent.add(sibling) + elif isinstance(gdparent, gtk.Paned): + if gdparent.get_child1() == parent: + gdparent.remove(parent) + gdparent.pack1(sibling) + else: + gdparent.remove(parent) + gdparent.pack2(sibling) + parent.destroy() + if index == 0: index = 1 + self.term_list[index - 1]._vte.grab_focus () + + if len(self.term_list) == 1: + self.term_list[0]._titlebox.hide() - return + return True + + def closeterm (self, widget): + if self.remove(widget): + widget.destroy () + return True + return False def go_next (self, term): current = self.term_list.index (term) @@ -818,7 +1215,24 @@ class Terminator: else: next += 1 - self.term_list[next]._vte.grab_focus () + + nextterm = self.term_list[next] + if isinstance(nextterm.get_parent(), gtk.Notebook): + box = nextterm + parent = box.get_parent() + for i in range(0, parent.get_n_pages()): + if box == parent.get_nth_page(i): + parent.set_current_page(i) + break + notebookpage = self.get_first_notebook_page(nextterm) + if notebookpage: + child = None + for i in range(0, notebookpage[0].get_n_pages()): + if notebookpage[0].get_nth_page(i) == notebookpage[1]: + notebookpage[0].set_current_page(i) + break + nextterm._vte.grab_focus () + def go_prev (self, term): current = self.term_list.index (term) @@ -830,7 +1244,23 @@ class Terminator: previous -= 1 #self.window.set_title(self.term_list[previous]._vte.get_window_title()) - self.term_list[previous]._vte.grab_focus () + previousterm = self.term_list[previous] + if isinstance(previousterm.get_parent(), gtk.Notebook): + box = previousterm + parent = box.get_parent() + for i in range(0, parent.get_n_pages()): + if box == parent.get_nth_page(i): + parent.set_current_page(i) + break + notebookpage = self.get_first_notebook_page(previousterm) + if notebookpage: + child = None + for i in range(0, notebookpage[0].get_n_pages()): + if notebookpage[0].get_nth_page(i) == notebookpage[1]: + notebookpage[0].set_current_page(i) + break + previousterm._vte.grab_focus () + def resizeterm (self, widget, keyname): vertical = False @@ -862,6 +1292,24 @@ class Terminator: parent.set_position(move) + def previous_tab(self, term): + notebook = self.get_first_parent_notebook(term) + notebook.prev_page() + return + + def next_tab(self, term): + notebook = self.get_first_parent_notebook(term) + notebook.next_page() + return + + def get_first_parent_notebook(self, widget): + if isinstance (widget, gtk.Window): + return None + parent = widget.get_parent() + if isinstance (parent, gtk.Notebook): + return parent + return self.get_first_parent_notebook(parent) + def get_first_parent_paned (self, widget, vertical = None): """This method returns the first parent pane of a widget. if vertical is True returns the first VPaned @@ -878,6 +1326,17 @@ class Terminator: return parent return self.get_first_parent_paned(parent, vertical) + def get_first_notebook_page(self, widget): + if isinstance (widget, gtk.Window): + return None + parent = widget.get_parent() + if isinstance (parent, gtk.Notebook): + page = -1 + for i in range(0, parent.get_n_pages()): + if parent.get_nth_page(i) == widget: + return (parent, widget) + return self.get_first_notebook_page(parent) + def reconfigure_vtes (self): for term in self.term_list: term.reconfigure_vte () @@ -915,6 +1374,7 @@ class Terminator: return else: return + if __name__ == '__main__': def execute_cb (option, opt, value, parser): diff --git a/terminatorlib/__init__.py b/terminatorlib/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/terminatorconfig.py b/terminatorlib/config.py similarity index 97% rename from terminatorconfig.py rename to terminatorlib/config.py index e056c952..8e945dc0 100755 --- a/terminatorconfig.py +++ b/terminatorlib/config.py @@ -110,6 +110,8 @@ class TerminatorConfValuestore: 'use_theme_colors' : True, 'http_proxy' : '', 'ignore_hosts' : ['localhost','127.0.0.0/8','*.local'], + 'encoding' : 'UTF-8', + 'active_encodings' : ['UTF-8', 'ISO-8859-1'], } def __getattr__ (self, keyname): @@ -169,6 +171,10 @@ class TerminatorConfValuestoreGConf (TerminatorConfValuestore): profile = self.client.get_string (self._gt_dir + '/global/default_profile') profiles = self.client.get_list (self._gt_dir + '/global/profile_list','string') + #set up the active encoding list + self.active_encodings = self.client.get_list (self._gt_dir + '/global/active_encodings', 'string') + + #need to handle the list of Gconf.value if profile in profiles: dbg (" VSGConf: Found profile '%s' in profile_list"%profile) self.profile = '%s/%s'%(self._profile_dir, profile) @@ -212,7 +218,7 @@ class TerminatorConfValuestoreGConf (TerminatorConfValuestore): value = None dbg (' VSGConf: preparing: %s/%s'%(self.profile, key)) - + # FIXME: Ugly special cases we should look to fix in some other way. if key == 'font' and self.use_system_font: value = self.client.get ('/desktop/gnome/interface/monospace_font_name') diff --git a/terminatorlib/encoding.py b/terminatorlib/encoding.py new file mode 100644 index 00000000..5851b6be --- /dev/null +++ b/terminatorlib/encoding.py @@ -0,0 +1,108 @@ +#!/usr/bin/python +# TerminatorEncoding - charset encoding classes +# Copyright (C) 2006-2008 chantra@debuntu.org +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 2 only. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +"""TerminatorEncoding by Emmanuel Bretelle + +TerminatorEncoding supplies a list of possible encoding + values. +This list is taken from gnome-terminal's src/encoding.h + and src/encoding.c +""" + +class TerminatorEncoding: + + encodings = [ + [True, None, _("Current Locale")], + [False, "ISO-8859-1", _("Western")], + [False, "ISO-8859-2", _("Central European")], + [False, "ISO-8859-3", _("South European") ], + [False, "ISO-8859-4", _("Baltic") ], + [False,"ISO-8859-5", _("Cyrillic") ], + [False, "ISO-8859-6", _("Arabic") ], + [False, "ISO-8859-7", _("Greek") ], + [False, "ISO-8859-8", _("Hebrew Visual") ], + [False, "ISO-8859-8-I", _("Hebrew") ], + [False, "ISO-8859-9", _("Turkish") ], + [False, "ISO-8859-10", _("Nordic") ], + [False, "ISO-8859-13", _("Baltic") ], + [False, "ISO-8859-14", _("Celtic") ], + [False, "ISO-8859-15", _("Western") ], + [False, "ISO-8859-16", _("Romanian") ], + [False, "UTF-7", _("Unicode") ], + [False, "UTF-8", _("Unicode") ], + [False, "UTF-16", _("Unicode") ], + [False, "UCS-2", _("Unicode") ], + [False, "UCS-4", _("Unicode") ], + [False, "ARMSCII-8", _("Armenian") ], + [False, "BIG5", _("Chinese Traditional") ], + [False, "BIG5-HKSCS", _("Chinese Traditional") ], + [False, "CP866", _("Cyrillic/Russian") ], + [False, "EUC-JP", _("Japanese") ], + [False, "EUC-KR", _("Korean") ], + [False, "EUC-TW", _("Chinese Traditional") ], + [False, "GB18030", _("Chinese Simplified") ], + [False, "GB2312", _("Chinese Simplified") ], + [False, "GBK", _("Chinese Simplified") ], + [False, "GEORGIAN-PS", _("Georgian") ], + [False, "HZ", _("Chinese Simplified") ], + [False, "IBM850", _("Western") ], + [False, "IBM852", _("Central European") ], + [False, "IBM855", _("Cyrillic") ], + [False, "IBM857", _("Turkish") ], + [False, "IBM862", _("Hebrew") ], + [False, "IBM864", _("Arabic") ], + [False, "ISO2022JP", _("Japanese") ], + [False, "ISO2022KR", _("Korean") ], + [False, "ISO-IR-111", _("Cyrillic") ], + [False, "JOHAB", _("Korean") ], + [False, "KOI8-R", _("Cyrillic") ], + [False, "KOI8-U", _("Cyrillic/Ukrainian") ], + [False, "MAC_ARABIC", _("Arabic") ], + [False, "MAC_CE", _("Central European") ], + [False, "MAC_CROATIAN", _("Croatian") ], + [False, "MAC-CYRILLIC", _("Cyrillic") ], + [False, "MAC_DEVANAGARI", _("Hindi") ], + [False, "MAC_FARSI", _("Persian") ], + [False, "MAC_GREEK", _("Greek") ], + [False, "MAC_GUJARATI", _("Gujarati") ], + [False, "MAC_GURMUKHI", _("Gurmukhi") ], + [False, "MAC_HEBREW", _("Hebrew") ], + [False, "MAC_ICELANDIC", _("Icelandic") ], + [False, "MAC_ROMAN", _("Western") ], + [False, "MAC_ROMANIAN", _("Romanian") ], + [False, "MAC_TURKISH", _("Turkish") ], + [False, "MAC_UKRAINIAN", _("Cyrillic/Ukrainian") ], + [False, "SHIFT-JIS", _("Japanese") ], + [False, "TCVN", _("Vietnamese") ], + [False, "TIS-620", _("Thai") ], + [False, "UHC", _("Korean") ], + [False, "VISCII", _("Vietnamese") ], + [False, "WINDOWS-1250", _("Central European") ], + [False, "WINDOWS-1251", _("Cyrillic") ], + [False, "WINDOWS-1252", _("Western") ], + [False, "WINDOWS-1253", _("Greek") ], + [False, "WINDOWS-1254", _("Turkish") ], + [False, "WINDOWS-1255", _("Hebrew") ], + [False, "WINDOWS-1256", _("Arabic") ], + [False, "WINDOWS-1257", _("Baltic") ], + [False, "WINDOWS-1258", _("Vietnamese") ] + ] + + def get_list(): + return TerminatorEncoding.encodings + get_list = staticmethod(get_list) + \ No newline at end of file diff --git a/terminatorlib/freebsd.py b/terminatorlib/freebsd.py new file mode 100644 index 00000000..221d5146 --- /dev/null +++ b/terminatorlib/freebsd.py @@ -0,0 +1,83 @@ +#!/usr/local/bin/python +# +# Use sysctl() to retrieve the cwd of an arbitrary process on FreeBSD. +# Tested on FreeBSD 7-STABLE/amd64 from April 11 2008. +# +# Be prepared for excitement if the structs are changed. +# +# Blame: Thomas Hurst +# + +from ctypes import * + +# This is padded awkwardly, see /usr/include/sys/socket.h +class sockaddr_storage(Structure): + _fields_ = [ + ('ss_len', c_char), + ('ss_family', c_char), # /usr/include/sys/_types.h; _uint8_t + ('__ss_pad1', c_char * 6), # (sizeof(int64) - sizeof(char) - sizeof(ss_family_t)) + ('__ss_align', c_longlong), + ('__ss_pad2', c_char * 112), # (128(maxsize) - sizeof(char) - sizeof(ss_family_t) - + # sizeof(ss_pad1) - sizeof(int64)) + ] + +# struct kinfo_file, defined in /usr/include/sys/user.h +class kinfo_file(Structure): + _fields_ = [ + ('kf_structsize', c_int), + ('kf_type', c_int), + ('kf_fd', c_int), + ('kf_ref_count', c_int), + ('kf_flags', c_int), + ('kf_offset', c_long), # this is a off_t, a pointer + ('kf_vnode_type', c_int), + ('kf_sock_domain', c_int), + ('kf_sock_type', c_int), + ('kf_sock_protocol', c_int), + ('kf_path', c_char * 1024), # PATH_MAX + ('kf_sa_local', sockaddr_storage), + ('kf_sa_peer', sockaddr_storage), + ] + + +def get_process_cwd(pid): + libc = CDLL('libc.so') + + len = c_uint(sizeof(c_uint)) + ver = c_uint(0) + + if (libc.sysctlbyname('kern.osreldate', byref(ver), byref(len), None, 0) < 0): + return None + + # kern.proc.filedesc added for procstat(1) after these __FreeBSD_versions + if ver.value < 700104 and ver.value < 800019: + return None + + # /usr/include/sys/sysctl.h + # CTL_KERN, KERN_PROC, KERN_PROC_FILEDESC + oid = (c_uint * 4)(1, 14, 14, pid) + + if libc.sysctl(oid, 4, None, byref(len), None, 0) < 0: + return None + + buf = c_char_p(" " * len.value) + if libc.sysctl(oid, 4, buf, byref(len), None, 0) < 0: + return None + + kifs = cast(buf, POINTER(kinfo_file)) + for i in range(0, len.value / sizeof(kinfo_file)): + kif = kifs[i] + if kif.kf_fd == -1: # KF_FD_TYPE_CWD + return kif.kf_path + +if __name__ == '__main__': + import os, sys + print " => %d cwd = %s" % (os.getpid(), get_process_cwd(os.getpid())) + for pid in sys.argv: + try: + pid = int(pid) + except: + pass + else: + print " => %d cwd = %s" % (pid, get_process_cwd(pid)) + From 2d65ae59664cc2ec4bf9c845e9f5b48bd6feeb53 Mon Sep 17 00:00:00 2001 From: Edoardo Batini Date: Thu, 22 May 2008 18:22:02 +0200 Subject: [PATCH 11/19] Zoom feature Fixes LP #229201 --- terminator | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/terminator b/terminator index 645a9302..651dd1b1 100755 --- a/terminator +++ b/terminator @@ -498,6 +498,9 @@ text/plain if self.scrollbar_position == 'hidden' or self.scrollbar_position == 'disabled': self._scrollbar.hide () else: + print + print self.scrollbar_position + print self._scrollbar.show () if self.scrollbar_position == 'right': self._termbox.reorder_child (self._vte, 0) @@ -1354,11 +1357,12 @@ class Terminator: self.old_parent = widget.get_parent() if isinstance(self.old_parent, gtk.Window): return + if isinstance(self.old_parent, gtk.Notebook): + self.old_page = self.old_parent.get_current_page() self.window_child = self.window.get_children()[0] self.window.remove(self.window_child) self.old_parent.remove(widget) self.window.add(widget) - self.window.show_all() self._fullwindow = True def show_back_others(self, widget): @@ -1369,7 +1373,9 @@ class Terminator: self.window.remove(widget) self.window.add(self.window_child) self.old_parent.add(widget) - self.window.show_all() + if isinstance(self.old_parent, gtk.Notebook): + self.old_parent.set_current_page(self.old_page) + print "\nPARENT IS A NOTEBOOK\n" self._fullwindow = False return else: From 39fff2287b378f47dee6f0b841d434c91959604d Mon Sep 17 00:00:00 2001 From: Edoardo Batini Date: Fri, 23 May 2008 23:30:53 +0200 Subject: [PATCH 12/19] Resync with trunk --- doc/terminatorrc.5 | 4 +- terminator | 219 +++++++++++++++++++++++++-------------- terminatorlib/config.py | 46 ++++++-- terminatorlib/freebsd.py | 23 ++-- 4 files changed, 187 insertions(+), 105 deletions(-) diff --git a/doc/terminatorrc.5 b/doc/terminatorrc.5 index b10407f7..d7d54410 100644 --- a/doc/terminatorrc.5 +++ b/doc/terminatorrc.5 @@ -19,7 +19,7 @@ If true, don't make a noise when applications send the escape sequence for the t Default value: \fBTrue\fR .TP .B background_color -Default colour of terminal background, as a colour specification (can be HTML-style hex digits, or a colour name such as "red"). +Default colour of terminal background, as a colour specification (can be HTML-style hex digits, or a colour name such as "red"). \fBNote:\fR You may need to set \fBuse_theme_colors=False\fR to force this setting to take effect. Default value: \fB#000000\fR .TP .B background_darkness @@ -51,7 +51,7 @@ An Pango font name. Examples are "Sans 12" or "Monospace Bold 14". Default value: \fBSerif 10\fR .TP .B foreground_color -Default colour of text in the terminal, as a colour specification (can be HTML-style hex digits, or a colour name such as "red"). +Default colour of text in the terminal, as a colour specification (can be HTML-style hex digits, or a colour name such as "red"). \fBNote:\fR You may need to set \fBuse_theme_colors=False\fR to force this setting to take effect. Default value: \fB#AAAAAA\fR .TP .B scrollbar_position diff --git a/terminator b/terminator index 651dd1b1..9cd4a9f7 100755 --- a/terminator +++ b/terminator @@ -50,10 +50,15 @@ if platform.system() == 'FreeBSD': try: from terminatorlib import freebsd pid_get_cwd = lambda pid: freebsd.get_process_cwd(pid) + dbg ('Using FreeBSD pid_get_cwd') except: + dbg ('FreeBSD version too old for pid_get_cwd') pass -elif platform.system == 'Linux': +elif platform.system() == 'Linux': + dbg ('Using Linux pid_get_cwd') pid_get_cwd = lambda pid: os.path.realpath ('/proc/%s/cwd' % pid) +else: + dbg ('Unable to set a pid_get_cwd, unknown system: %s'%platform.system) # import gtk libs # check just in case anyone runs it on a non-gnome system. @@ -323,6 +328,7 @@ text/plain pos = "bottom" return pos + def add_matches (self, lboundry="[[:<:]]", rboundry="[[:>:]]"): userchars = "-A-Za-z0-9" passchars = "-A-Za-z0-9,?;.:/!%$^*&~\"#'" @@ -393,8 +399,9 @@ text/plain """ Return the current working directory of the subprocess. This function requires OS specific behaviours """ - - return (pid_get_cwd(self._pid)) + cwd = pid_get_cwd (self._pid) + dbg ('get_cwd found: %s'%cwd) + return (cwd) def reconfigure_vte (self): # Set our emulation @@ -498,9 +505,6 @@ text/plain if self.scrollbar_position == 'hidden' or self.scrollbar_position == 'disabled': self._scrollbar.hide () else: - print - print self.scrollbar_position - print self._scrollbar.show () if self.scrollbar_position == 'right': self._termbox.reorder_child (self._vte, 0) @@ -608,7 +612,13 @@ text/plain elif keyname in ('Up', 'Down', 'Left', 'Right'): self.terminator.resizeterm (self, keyname) return (True) - + elif keyname == 'Page_Down': + self.terminator.move_tab(self, 'right') + return (True) + elif keyname == 'Page_Up': + self.terminator.move_tab(self, 'left') + return (True) + mask = gtk.gdk.CONTROL_MASK if (event.state & mask) == mask: if keyname == 'Page_Down': @@ -720,13 +730,6 @@ text/plain item = gtk.MenuItem () menu.append (item) - item = gtk.MenuItem (_("M_aximize/Unmaximize")) - item.connect ("activate", lambda menu_item: self.terminator.fullwindow (self)) - menu.append (item) - - item = gtk.MenuItem () - menu.append (item) - item = gtk.ImageMenuItem (gtk.STOCK_CLOSE) item.connect ("activate", lambda menu_item: self.terminator.closeterm (self)) menu.append (item) @@ -824,11 +827,9 @@ text/plain class Terminator: def __init__ (self, profile, command = None, fullscreen = False, maximise = False, borderless = False): - self.profile = profile self.command = command - - self._fullwindow = False + self._fullscreen = False self.term_list = [] stores = [] @@ -968,8 +969,6 @@ class Terminator: Add a term to another at position pos """ vertical = pos in ("top", "bottom") - - # create a new terminal and parent pane. pane = (vertical) and gtk.VPaned () or gtk.HPaned () # get the parent of the provided terminal @@ -1009,6 +1008,7 @@ class Terminator: parent.insert_page(pane, None, page) parent.set_tab_label_text(pane, widget._vte.get_window_title()) parent.set_tab_label_packing(pane, True, True, gtk.PACK_START) + parent.set_tab_reorderable(pane, True) parent.set_current_page(page) @@ -1053,51 +1053,131 @@ class Terminator: return (terminal) def on_page_reordered(self, notebook, child, page_num): + #page has been reordered, we need to get the + # first term and last term dbg ("Reordered: %d"%page_num) + nbpages = notebook.get_n_pages() + if nbpages == 1: + dbg("[ERROR] only one page in on_page_reordered") + first = self._notebook_first_term(notebook.get_nth_page(page_num)) + last = self._notebook_last_term(notebook.get_nth_page(page_num)) + firstidx = self.term_list.index(first) + lastidx = self.term_list.index(last) + termslice = self.term_list[firstidx:lastidx+1] + #remove them from the list + for term in termslice: + self.term_list.remove(term) + + if page_num == 0: + #first page, we insert before the first term of next page + nexttab = notebook.get_nth_page(1) + sibling = self._notebook_first_term(nexttab) + siblingindex = self.term_list.index(sibling) + for term in termslice: + self.term_list.insert(siblingindex, term) + siblingindex += 1 + else: + #other pages, we insert after the last term of previous page + previoustab = notebook.get_nth_page(page_num - 1) + sibling = self._notebook_last_term(previoustab) + print sibling + siblingindex = self.term_list.index(sibling) + for term in termslice: + siblingindex += 1 + self.term_list.insert(siblingindex, term) + + #for page reorder, we need to get the first term of a notebook + def notebook_first_term(self, notebook): + return self._notebook_first_term(notebook.get_nth_page(0)) + + def _notebook_first_term(self, child): + if isinstance(child, TerminatorTerm): + return child + elif isinstance(child, gtk.Paned): + return self._notebook_first_term(child.get_child1()) + elif isinstance(child, gtk.Notebook): + return self._notebook_first_term(child.get_nth_page(0)) + + dbg("[ERROR] unsupported class %s in _notebook_first_term" % child.__class__.__name__) + return None + + #for page reorder, we need to get the last term of a notebook + def notebook_last_term(self, notebook): + return self._notebook_last_term(notebook.get_nth_page(notebook.get_n_pages()-1)) + + def _notebook_last_term(self, child): + if isinstance(child, TerminatorTerm): + return child + elif isinstance(child, gtk.Paned): + return self._notebook_first_term(child.get_child2()) + elif isinstance(child, gtk.Notebook): + return self._notebook_first_term(child.get_nth_page(child.get_n_pages()-1)) + + dbg("[ERROR] unsupported class %s in _notebook_last_term" % child.__class__.__name__) + return None + def newtab(self,widget): terminal = TerminatorTerm (self, self.profile, None, widget.get_cwd()) - widgetbox = widget - parent = widgetbox.get_parent () + parent = widget.get_parent () if isinstance(parent, gtk.Paned) or isinstance(parent, gtk.Window): #no notebook yet. notebook = gtk.Notebook() + notebook.set_tab_pos(gtk.POS_TOP) notebook.connect('page-reordered',self.on_page_reordered) notebook.set_property('homogeneous', True) - notebook.set_tab_reorderable(widgetbox, True) + notebook.set_tab_reorderable(widget, True) if isinstance(parent, gtk.Paned): - if parent.get_child1() == widgetbox: - widgetbox.reparent(notebook) + if parent.get_child1() == widget: + widget.reparent(notebook) parent.pack1(notebook) else: - widgetbox.reparent(notebook) + widget.reparent(notebook) parent.pack2(notebook) elif isinstance(parent, gtk.Window): - widgetbox.reparent(notebook) + widget.reparent(notebook) parent.add(notebook) - notebook.set_tab_reorderable(widgetbox,True) + notebook.set_tab_reorderable(widget,True) notebooklabel = "" if widget._vte.get_window_title() is not None: notebooklabel = widget._vte.get_window_title() - notebook.set_tab_label_text(widgetbox, notebooklabel) - notebook. set_tab_label_packing(widgetbox, True, True, gtk.PACK_START) + notebook.set_tab_label_text(widget, notebooklabel) + notebook. set_tab_label_packing(widget, True, True, gtk.PACK_START) notebook.show() elif isinstance(parent, gtk.Notebook): notebook = parent else: return (False) - notebook.append_page(terminal,terminal._vte.get_window_title()) - notebook. set_tab_label_packing(terminal, True, True, gtk.PACK_START) - notebook.set_tab_reorderable(terminal,True) - notebook.set_current_page(-1) - index = self.term_list.index(widget) - self.term_list.insert (index + 1, terminal) + ## NOTE + ## Here we need to append to the notebook before we can + ## spawn the terminal (WINDOW_ID needs to be set) + + notebook.append_page(terminal,None) terminal.show () terminal.spawn_child () + ## Some gtk/vte weirdness + ## If we don't use this silly test, + ## terminal._vte.get_window_title() might return + ## bogus values + notebooklabel = "" + if terminal._vte.get_window_title() is not None: + notebooklabel = terminal._vte.get_window_title() + notebook.set_tab_label_text(terminal, notebooklabel) + notebook.set_tab_label_packing(terminal, True, True, gtk.PACK_START) + notebook.set_tab_reorderable(terminal,True) + ## Now, we set focus on the new term + notebook.set_current_page(-1) terminal._vte.grab_focus () + + #adding a new tab, thus we need to get the + # last term of the previous tab and add + # the new term just after + sibling = self._notebook_last_term(notebook.get_nth_page(notebook.page_num(terminal)-1)) + index = self.term_list.index(sibling) + self.term_list.insert (index + 1, terminal) return (True) @@ -1105,11 +1185,6 @@ class Terminator: def splitaxis (self, widget, vertical=True): """ Split the provided widget on the horizontal or vertical axis. """ - - #should disable splitaxis menu instead? - if self._fullwindow: - return - # create a new terminal and parent pane. terminal = TerminatorTerm (self, self.profile, None, widget.get_cwd()) pos = vertical and "bottom" or "right" @@ -1121,9 +1196,6 @@ class Terminator: def remove(self, widget): """Remove a TerminatorTerm from the Terminator view and terms list Returns True on success, False on failure""" - if self._fullwindow: - self.show_back_others(widget) - parent = widget.get_parent () sibling = None @@ -1159,6 +1231,8 @@ class Terminator: grandparent.remove_page(page) grandparent.insert_page(sibling, None,page) grandparent.set_tab_label_packing(sibling, True, True, gtk.PACK_START) + grandparent.set_tab_reorderable(sibling, True) + else: grandparent.remove (parent) @@ -1264,6 +1338,8 @@ class Terminator: break previousterm._vte.grab_focus () + + def resizeterm (self, widget, keyname): vertical = False @@ -1305,6 +1381,26 @@ class Terminator: notebook.next_page() return + def move_tab(self, term, direction): + dbg("moving to direction %s" % direction) + (notebook, page) = self.get_first_notebook_page(term) + page_num = notebook.page_num(page) + nbpages = notebook.get_n_pages() + #dbg ("%s %s %s %s" % (page_num, nbpages,notebook, page)) + if page_num == 0 and direction == 'left': + new_page_num = nbpages + elif page_num == nbpages - 1 and direction == 'right': + new_page_num = 0 + elif direction == 'left': + new_page_num = page_num - 1 + elif direction == 'right': + new_page_num = page_num + 1 + else: + dbg("[ERROR] unhandled combination in move_tab: direction = %s page_num = %d" % (direction, page_num)) + return False + notebook.reorder_child(page, new_page_num) + return True + def get_first_parent_notebook(self, widget): if isinstance (widget, gtk.Window): return None @@ -1344,43 +1440,6 @@ class Terminator: for term in self.term_list: term.reconfigure_vte () - def fullwindow(self, widget): - if not self._fullwindow: - self.hide_all_but_me(widget) - else: - self.show_back_others(widget) - - def hide_all_but_me (self, widget): - """Proof of concept: Maximize to full window - an instance of TerminatorTerm. - """ - self.old_parent = widget.get_parent() - if isinstance(self.old_parent, gtk.Window): - return - if isinstance(self.old_parent, gtk.Notebook): - self.old_page = self.old_parent.get_current_page() - self.window_child = self.window.get_children()[0] - self.window.remove(self.window_child) - self.old_parent.remove(widget) - self.window.add(widget) - self._fullwindow = True - - def show_back_others(self, widget): - """Proof of concept: Go back to previous application - widget structure. - """ - if self._fullwindow: - self.window.remove(widget) - self.window.add(self.window_child) - self.old_parent.add(widget) - if isinstance(self.old_parent, gtk.Notebook): - self.old_parent.set_current_page(self.old_page) - print "\nPARENT IS A NOTEBOOK\n" - self._fullwindow = False - return - else: - return - if __name__ == '__main__': def execute_cb (option, opt, value, parser): diff --git a/terminatorlib/config.py b/terminatorlib/config.py index 8e945dc0..751fef06 100755 --- a/terminatorlib/config.py +++ b/terminatorlib/config.py @@ -32,7 +32,7 @@ AttributeError. This is by design. If you want to look something up, set a default for it first.""" # import standard python libs -import os, sys +import os, sys, re # import unix-lib import pwd @@ -58,8 +58,8 @@ class TerminatorConfig: self.sources.append (source) def __getattr__ (self, keyname): - dbg ("TConfig: Looking for: '%s'"%keyname) for source in self.sources: + dbg ("TConfig: Looking for: '%s' in '%s'"%(keyname, source.type)) try: val = getattr (source, keyname) dbg (" TConfig: got: '%s' from a '%s'"%(val, source.type)) @@ -81,11 +81,12 @@ class TerminatorConfValuestore: 'profile_dir' : '/apps/gnome-terminal/profiles', 'titlebars' : True, 'titletips' : False, - 'allow_bold' : False, + 'allow_bold' : True, 'silent_bell' : True, 'background_color' : '#000000', 'background_darkness' : 0.5, 'background_type' : 'solid', + 'background_image' : '', 'backspace_binding' : 'ascii-del', 'delete_binding' : 'delete-sequence', 'cursor_blink' : False, @@ -112,12 +113,15 @@ class TerminatorConfValuestore: 'ignore_hosts' : ['localhost','127.0.0.0/8','*.local'], 'encoding' : 'UTF-8', 'active_encodings' : ['UTF-8', 'ISO-8859-1'], + 'background_image' : '', } def __getattr__ (self, keyname): if self.values.has_key (keyname): + dbg ("Returning '%s'"%keyname) return self.values[keyname] else: + dbg ("Failed to find '%s'"%keyname) raise (AttributeError) class TerminatorConfValuestoreDefault (TerminatorConfValuestore): @@ -127,6 +131,7 @@ class TerminatorConfValuestoreDefault (TerminatorConfValuestore): class TerminatorConfValuestoreRC (TerminatorConfValuestore): rcfilename = "" + splitter = re.compile("\s*=\s*") #FIXME: use inotify to watch the rc, split __init__ into a parsing function # that can be re-used when rc changes. def __init__ (self): @@ -141,14 +146,33 @@ class TerminatorConfValuestoreRC (TerminatorConfValuestore): try: item = item.strip () if item and item[0] != '#': - (key, value) = item.split ("=") - dbg (" VS_RCFile: Setting value %s to %s"%(key, value)) - if value == 'True': - self.values[key] = True - elif value == 'False': - self.values[key] = False - except: - dbg (" VS_RCFile: Exception handling: %s"%item) + (key, value) = self.splitter.split (item) + + # Check if this is actually a key we care about + if not self.defaults.has_key (key): + raise AttributeError; + + deftype = self.defaults[key].__class__.__name__ + if deftype == 'bool': + if value.lower () == 'true': + self.values[key] = True + elif value.lower () == 'false': + self.values[key] = False + else: + raise AttributeError + elif deftype == 'int': + self.values[key] = int (value) + elif deftype == 'float': + self.values[key] = float (value) + elif deftype == 'list': + print >> sys.stderr, _("Reading list values from .terminatorrc is not currently supported") + raise ValueError + else: + self.values[key] = value + + dbg (" VS_RCFile: Set value '%s' to '%s'"%(key, self.values[key])) + except Exception, e: + dbg (" VS_RCFile: %s Exception handling: %s" % (type(e), item)) pass class TerminatorConfValuestoreGConf (TerminatorConfValuestore): diff --git a/terminatorlib/freebsd.py b/terminatorlib/freebsd.py index 221d5146..8937dc4d 100644 --- a/terminatorlib/freebsd.py +++ b/terminatorlib/freebsd.py @@ -39,20 +39,19 @@ class kinfo_file(Structure): ('kf_sa_peer', sockaddr_storage), ] +libc = CDLL('libc.so') + +len = c_uint(sizeof(c_uint)) +ver = c_uint(0) + +if (libc.sysctlbyname('kern.osreldate', byref(ver), byref(len), None, 0) < 0): + raise OSError, "sysctlbyname returned < 0" + +# kern.proc.filedesc added for procstat(1) after these __FreeBSD_versions +if ver.value < 700104 and ver.value < 800019: + raise NotImplementedError, "cwd detection requires a recent 7.0-STABLE or 8-CURRENT" def get_process_cwd(pid): - libc = CDLL('libc.so') - - len = c_uint(sizeof(c_uint)) - ver = c_uint(0) - - if (libc.sysctlbyname('kern.osreldate', byref(ver), byref(len), None, 0) < 0): - return None - - # kern.proc.filedesc added for procstat(1) after these __FreeBSD_versions - if ver.value < 700104 and ver.value < 800019: - return None - # /usr/include/sys/sysctl.h # CTL_KERN, KERN_PROC, KERN_PROC_FILEDESC oid = (c_uint * 4)(1, 14, 14, pid) From 394e41a9ab5569986a566bdace15a274dbca9a3c Mon Sep 17 00:00:00 2001 From: Edoardo Batini Date: Fri, 23 May 2008 23:41:49 +0200 Subject: [PATCH 13/19] Full window feature --- terminator | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/terminator b/terminator index 9cd4a9f7..956665f4 100755 --- a/terminator +++ b/terminator @@ -730,6 +730,13 @@ text/plain item = gtk.MenuItem () menu.append (item) + item = gtk.MenuItem (_("M_aximize/Unmaximize")) + item.connect ("activate", lambda menu_item: self.terminator.fullwindow (self)) + menu.append (item) + + item = gtk.MenuItem () + menu.append (item) + item = gtk.ImageMenuItem (gtk.STOCK_CLOSE) item.connect ("activate", lambda menu_item: self.terminator.closeterm (self)) menu.append (item) @@ -830,6 +837,7 @@ class Terminator: self.profile = profile self.command = command + self._fullwindow = False self._fullscreen = False self.term_list = [] stores = [] @@ -1118,6 +1126,10 @@ class Terminator: return None def newtab(self,widget): + if self._fullwindow: + dbg ("newtab function called, but Terminator was in full-window mode.") + return + terminal = TerminatorTerm (self, self.profile, None, widget.get_cwd()) parent = widget.get_parent () @@ -1186,6 +1198,9 @@ class Terminator: def splitaxis (self, widget, vertical=True): """ Split the provided widget on the horizontal or vertical axis. """ # create a new terminal and parent pane. + if self._fullwindow: + dbg ("splitaxis function called, but Terminator was in full-window mode.") + return terminal = TerminatorTerm (self, self.profile, None, widget.get_cwd()) pos = vertical and "bottom" or "right" self.add(widget, terminal, pos) @@ -1278,6 +1293,10 @@ class Terminator: return True def closeterm (self, widget): + if self._fullwindow: + self.show_back_others(widget) + dbg ("closeterm function called while Terminator was in full-window mode.") + if self.remove(widget): widget.destroy () return True @@ -1440,6 +1459,44 @@ class Terminator: for term in self.term_list: term.reconfigure_vte () + def fullwindow(self, widget): + if not self._fullwindow: + self.hide_all_but_me(widget) + else: + self.show_back_others(widget) + + def hide_all_but_me (self, widget): + """Proof of concept: Maximize to full window + an instance of TerminatorTerm. + """ + self.old_parent = widget.get_parent() + if isinstance(self.old_parent, gtk.Window): + return + if isinstance(self.old_parent, gtk.Notebook): + self.old_page = self.old_parent.get_current_page() + self.window_child = self.window.get_children()[0] + self.window.remove(self.window_child) + self.old_parent.remove(widget) + self.window.add(widget) + self._fullwindow = True + + def show_back_others(self, widget): + """Proof of concept: Go back to previous application + widget structure. + """ + if self._fullwindow: + self.window.remove(widget) + self.window.add(self.window_child) + self.old_parent.add(widget) + if isinstance(self.old_parent, gtk.Notebook): + self.old_parent.set_current_page(self.old_page) + print "\nPARENT IS A NOTEBOOK\n" + self._fullwindow = False + return + else: + return + + if __name__ == '__main__': def execute_cb (option, opt, value, parser): From d78e314efa3f906f82c203cc88bc1f1b7000d9e0 Mon Sep 17 00:00:00 2001 From: Edoardo Batini Date: Sat, 24 May 2008 01:10:08 +0200 Subject: [PATCH 14/19] Repairs restoring from full window removing a grandparent.resize_children() from Terminator.remove function --- terminator | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/terminator b/terminator index 956665f4..13f49d26 100755 --- a/terminator +++ b/terminator @@ -868,7 +868,7 @@ class Terminator: self.window.connect ("destroy", self.on_destroy_event) self.window.set_property ('allow-shrink', True) - + if fullscreen: self.fullscreen_toggle () @@ -971,6 +971,11 @@ class Terminator: Modifies Terminator window title """ self.window.set_title(title) + + def handle_moved(self, *args): + print "Handle-Move called" + for arg in args: + print arg def add(self, widget, terminal, pos = "bottom"): """ @@ -979,6 +984,10 @@ class Terminator: vertical = pos in ("top", "bottom") pane = (vertical) and gtk.VPaned () or gtk.HPaned () + #Store pane's handle position in percentage in pane itself + setattr(pane, "ratio", 50) + pane.connect("accept-position", self.handle_moved) + # get the parent of the provided terminal parent = widget.get_parent () @@ -1047,7 +1056,7 @@ class Terminator: # show all, set position of the divider pane.show () - pane.set_position (position / 2) + pane.set_position (position * pane.ratio / 100) terminal.show () terminal.spawn_child () @@ -1201,6 +1210,7 @@ class Terminator: if self._fullwindow: dbg ("splitaxis function called, but Terminator was in full-window mode.") return + terminal = TerminatorTerm (self, self.profile, None, widget.get_cwd()) pos = vertical and "bottom" or "right" self.add(widget, terminal, pos) @@ -1252,7 +1262,7 @@ class Terminator: else: grandparent.remove (parent) sibling.reparent (grandparent) - grandparent.resize_children() +# grandparent.resize_children() parent.destroy () self.term_list.remove (widget) @@ -1294,8 +1304,8 @@ class Terminator: def closeterm (self, widget): if self._fullwindow: - self.show_back_others(widget) dbg ("closeterm function called while Terminator was in full-window mode.") + self.show_back_others(widget) if self.remove(widget): widget.destroy () @@ -1357,9 +1367,6 @@ class Terminator: break previousterm._vte.grab_focus () - - - def resizeterm (self, widget, keyname): vertical = False if keyname in ('Up', 'Down'): @@ -1378,9 +1385,9 @@ class Terminator: if keyname in ('Up', 'Down'): maxi = parent.get_child1().get_allocation().height + parent.get_child2().get_allocation().height - 1 - else: maxi = parent.get_child1().get_allocation().width + parent.get_child2().get_allocation().width - 1 + move = 10 if keyname in ('Up', 'Left'): move = -10 @@ -1389,6 +1396,13 @@ class Terminator: move = min(maxi, move) parent.set_position(move) + if keyname in ('Up', 'Down'): + ratio = 100 * parent.get_child1().get_allocation().height / maxi + else: + ratio = 100 * parent.get_child1().get_allocation().width / maxi + setattr(parent, "ratio", ratio) + print parent.get_position() + print ratio def previous_tab(self, term): notebook = self.get_first_parent_notebook(term) @@ -1490,13 +1504,11 @@ class Terminator: self.old_parent.add(widget) if isinstance(self.old_parent, gtk.Notebook): self.old_parent.set_current_page(self.old_page) - print "\nPARENT IS A NOTEBOOK\n" self._fullwindow = False return else: return - if __name__ == '__main__': def execute_cb (option, opt, value, parser): From 00a6dc3fa1aa6e3aeacc0f04665f31e7619bea1a Mon Sep 17 00:00:00 2001 From: Edoardo Batini Date: Thu, 29 May 2008 14:25:46 +0200 Subject: [PATCH 15/19] Nth resync with trunk --- doc/terminatorrc.5 | 18 ++- terminator | 267 ++++++++++++++++++---------------------- terminatorlib/config.py | 5 + 3 files changed, 143 insertions(+), 147 deletions(-) diff --git a/doc/terminatorrc.5 b/doc/terminatorrc.5 index d7d54410..104c16d9 100644 --- a/doc/terminatorrc.5 +++ b/doc/terminatorrc.5 @@ -5,7 +5,7 @@ This manual page documents briefly the .B termiatorrc config file. .PP -\fBterminatorrc\fP is an optional file for configure the terminator termial emulator. It is used if there is no gconf PROFILE on the system for configuring the options of the terminal(s). +\fBterminatorrc\fP is an optional file to configure the terminator terminal emulator. It is used if there is no gconf PROFILE on the system for configuring the options of the terminal(s). .SH "OPTIONS" The options are defined one per line as \fB'OPTION = VALUE'\fR. The options are described below: @@ -93,5 +93,21 @@ Default value: \fB\-A\-Za\-z0\-9,./?%&#:_\fR .B mouse_autohide \fR(boolean) Controls whether the mouse cursor should be hidden while typing. Default value: \fBTrue\fR +.TP +.B fullscreen \fR(boolean) +Controls whether the Terminator window will be started in fullscreen mode +Default value: \fBFalse\fR +.TP +.B maximise \fR(boolean) +Controls whether the Terminator window will be started maximised +Default value: \fBFalse\fR +.TP +.B borderless \fR(boolean) +Controls whether the Terminator window will be started without window borders +Default value: \fBFalse\fR +.TP +.B handle_size +Controls the width of the separator between terminals. Anything outside the range 0-5 (inclusive) will be ignored and use your default theme value. +Default value: \fB-1\fR .SH "SEE ALSO" .BR gnome\-terminal(1) diff --git a/terminator b/terminator index 13f49d26..c59859ed 100755 --- a/terminator +++ b/terminator @@ -125,9 +125,8 @@ class TerminatorTerm (gtk.VBox): self.show() self.pack_start(self._titlebox, False) self.pack_start(self._termbox) - if len(self.terminator.term_list) > 0 and self.conf.titlebars: - if len(self.terminator.term_list) == 1: - self.terminator.term_list[0]._titlebox.show() + + if self.conf.titlebars: self._titlebox.show() else: self._titlebox.hide() @@ -136,10 +135,10 @@ class TerminatorTerm (gtk.VBox): if self.scrollbar_position != "hidden" and self.scrollbar_position != "disabled": self._scrollbar.show () - if self.scrollbar_position == 'right': - packfunc = self._termbox.pack_start - else: + if self.scrollbar_position == 'left': packfunc = self._termbox.pack_end + else: + packfunc = self._termbox.pack_start packfunc (self._vte) packfunc (self._scrollbar, False) @@ -183,7 +182,7 @@ class TerminatorTerm (gtk.VBox): self.add_matches() env_proxy = os.getenv ('http_proxy') - if not env_proxy and self.conf.http_proxy: + if not env_proxy and self.conf.http_proxy and self.conf.http_proxy != '': os.putenv ('http_proxy', self.conf.http_proxy) os.putenv ('COLORTERM', 'gnome-terminal') @@ -491,8 +490,8 @@ text/plain # Set our audible belliness silent_bell = self.conf.silent_bell - self._vte.set_audible_bell = not silent_bell - self._vte.set_visible_bell = silent_bell + self._vte.set_audible_bell (not silent_bell) + self._vte.set_visible_bell (silent_bell) # Set our scrolliness self._vte.set_scrollback_lines (self.conf.scrollback_lines) @@ -575,6 +574,12 @@ text/plain self.zoom (False) return (True) + mask = gtk.gdk.CONTROL_MASK | gtk.gdk.SHIFT_MASK | gtk.gdk.MOD1_MASK + if (event.state & mask) == mask: + #Top level tab + if keyname == 'T': + self.terminator.newtab (self, True) + return (True) # bindings that should be moved to Terminator as they all just call # a function of Terminator. It would be cleaner is TerminatorTerm # has absolutely no reference to Terminator. @@ -629,13 +634,16 @@ text/plain return (True) if keyname and (keyname == 'Tab' or keyname.endswith('_Tab')): - if event.state == gtk.gdk.CONTROL_MASK: - self.terminator.go_next (self) - return (True) + mask = gtk.gdk.CONTROL_MASK | gtk.gdk.SHIFT_MASK if (event.state & mask) == mask: self.terminator.go_prev (self) return (True) - + mask = gtk.gdk.CONTROL_MASK + if (event.state & mask) == mask: + self.terminator.go_next (self) + return (True) + # Warning, mask value is either gtk.gdk.CONTROL_MASK or gtk.gdk.CONTROL_MASK | gtk.gdk.SHIFT_MASK + # if you intend to use it, reinit it return (False) def zoom (self, zoom_in): @@ -727,13 +735,11 @@ text/plain item.connect ("activate", lambda menu_item: self.terminator.newtab (self)) menu.append (item) - item = gtk.MenuItem () - menu.append (item) - - item = gtk.MenuItem (_("M_aximize/Unmaximize")) - item.connect ("activate", lambda menu_item: self.terminator.fullwindow (self)) - menu.append (item) - + if self.conf.extreme_tabs: + item = gtk.MenuItem (_("Open Top Level Tab")) + item.connect ("activate", lambda menu_item: self.terminator.newtab (self, True)) + menu.append (item) + item = gtk.MenuItem () menu.append (item) @@ -837,7 +843,6 @@ class Terminator: self.profile = profile self.command = command - self._fullwindow = False self._fullscreen = False self.term_list = [] stores = [] @@ -852,7 +857,17 @@ class Terminator: pass self.conf = config.TerminatorConfig (stores) - + #changes to the Paned's handle_size can only be done + # once we loaded the configuration + + if self.conf.handle_size in range (0,6): + gtk.rc_parse_string(""" + style "terminator-paned-style" { + GtkPaned::handle_size = %s + } + + class "GtkPaned" style "terminator-paned-style" + """ % self.conf.handle_size) self.window = gtk.Window () self.window.set_title (APP_NAME.capitalize()) @@ -866,16 +881,17 @@ class Terminator: self.window.connect ("key-press-event", self.on_key_press) self.window.connect ("delete_event", self.on_delete_event) self.window.connect ("destroy", self.on_destroy_event) + self.window.connect ("window-state-event", self.on_window_state_changed) self.window.set_property ('allow-shrink', True) - - if fullscreen: + + if fullscreen or self.conf.fullscreen: self.fullscreen_toggle () - if maximise: + if maximise or self.conf.maximise: self.maximize () - if borderless: + if borderless or self.conf.borderless: self.window.set_decorated (False) # Set RGBA colormap if possible so VTE can use real alpha @@ -891,6 +907,7 @@ class Terminator: self.term_list = [term] self.window.add (term) + term._titlebox.hide() self.window.show () term.spawn_child () @@ -907,7 +924,12 @@ class Terminator: self.window.unfullscreen () else: self.window.fullscreen () - self._fullscreen = not self._fullscreen + + def on_window_state_changed (self, window, event): + state = event.new_window_state & gtk.gdk.WINDOW_STATE_FULLSCREEN + self._fullscreen = bool (state) + + return (False) def on_delete_event (self, window, event, data=None): if len (self.term_list) == 1: @@ -971,11 +993,6 @@ class Terminator: Modifies Terminator window title """ self.window.set_title(title) - - def handle_moved(self, *args): - print "Handle-Move called" - for arg in args: - print arg def add(self, widget, terminal, pos = "bottom"): """ @@ -983,14 +1000,10 @@ class Terminator: """ vertical = pos in ("top", "bottom") pane = (vertical) and gtk.VPaned () or gtk.HPaned () - - #Store pane's handle position in percentage in pane itself - setattr(pane, "ratio", 50) - pane.connect("accept-position", self.handle_moved) - + pane.handle_size = 1 + # get the parent of the provided terminal parent = widget.get_parent () - if isinstance (parent, gtk.Window): # We have just one term widget.reparent (pane) @@ -1006,8 +1019,15 @@ class Terminator: position = (vertical) and parent.allocation.height \ or parent.allocation.width + if (isinstance (parent, gtk.Notebook) or isinstance (parent, gtk.Window)) \ + and \ + widget.conf.titlebars: + #not the only term in the notebook/window anymore, need to reshow the title + widget._titlebox.show() + if isinstance (parent, gtk.Notebook): page = -1 + for i in range(0, parent.get_n_pages()): if parent.get_nth_page(i) == widget: page = i @@ -1056,14 +1076,15 @@ class Terminator: # show all, set position of the divider pane.show () - pane.set_position (position * pane.ratio / 100) + pane.set_position (position / 2) terminal.show () - terminal.spawn_child () + # insert the term reference into the list index = self.term_list.index (widget) - self.term_list.insert (index + 1, terminal) - + if pos in ('bottom', 'right'): + index = index + 1 + self.term_list.insert (index, terminal) # make the new terminal grab the focus terminal._vte.grab_focus () @@ -1098,7 +1119,6 @@ class Terminator: #other pages, we insert after the last term of previous page previoustab = notebook.get_nth_page(page_num - 1) sibling = self._notebook_last_term(previoustab) - print sibling siblingindex = self.term_list.index(sibling) for term in termslice: siblingindex += 1 @@ -1127,22 +1147,27 @@ class Terminator: if isinstance(child, TerminatorTerm): return child elif isinstance(child, gtk.Paned): - return self._notebook_first_term(child.get_child2()) + return self._notebook_last_term(child.get_child2()) elif isinstance(child, gtk.Notebook): - return self._notebook_first_term(child.get_nth_page(child.get_n_pages()-1)) + return self._notebook_last_term(child.get_nth_page(child.get_n_pages()-1)) dbg("[ERROR] unsupported class %s in _notebook_last_term" % child.__class__.__name__) return None - def newtab(self,widget): - if self._fullwindow: - dbg ("newtab function called, but Terminator was in full-window mode.") - return - + def newtab(self,widget, toplevel = False): terminal = TerminatorTerm (self, self.profile, None, widget.get_cwd()) - parent = widget.get_parent () - - if isinstance(parent, gtk.Paned) or isinstance(parent, gtk.Window): + #only one term, we don't show the title + terminal._titlebox.hide() + if self.conf.extreme_tabs and not toplevel: + parent = widget.get_parent () + child = widget + else: + child = self.window.get_children()[0] + parent = child.get_parent() + + if isinstance(parent, gtk.Paned) or (isinstance(parent, gtk.Window) + and + ((self.conf.extreme_tabs and not toplevel) or not isinstance(child, gtk.Notebook))): #no notebook yet. notebook = gtk.Notebook() notebook.set_tab_pos(gtk.POS_TOP) @@ -1151,24 +1176,28 @@ class Terminator: notebook.set_tab_reorderable(widget, True) if isinstance(parent, gtk.Paned): - if parent.get_child1() == widget: - widget.reparent(notebook) + if parent.get_child1() == child: + child.reparent(notebook) parent.pack1(notebook) else: - widget.reparent(notebook) + child.reparent(notebook) parent.pack2(notebook) elif isinstance(parent, gtk.Window): - widget.reparent(notebook) + child.reparent(notebook) parent.add(notebook) - notebook.set_tab_reorderable(widget,True) + notebook.set_tab_reorderable(child,True) notebooklabel = "" + if isinstance(child, TerminatorTerm): + child._titlebox.hide() if widget._vte.get_window_title() is not None: notebooklabel = widget._vte.get_window_title() - notebook.set_tab_label_text(widget, notebooklabel) - notebook. set_tab_label_packing(widget, True, True, gtk.PACK_START) + notebook.set_tab_label_text(child, notebooklabel) + notebook. set_tab_label_packing(child, True, True, gtk.PACK_START) notebook.show() elif isinstance(parent, gtk.Notebook): notebook = parent + elif isinstance(parent, gtk.Window) and isinstance(child, gtk.Notebook): + notebook = child else: return (False) @@ -1207,10 +1236,6 @@ class Terminator: def splitaxis (self, widget, vertical=True): """ Split the provided widget on the horizontal or vertical axis. """ # create a new terminal and parent pane. - if self._fullwindow: - dbg ("splitaxis function called, but Terminator was in full-window mode.") - return - terminal = TerminatorTerm (self, self.profile, None, widget.get_cwd()) pos = vertical and "bottom" or "right" self.add(widget, terminal, pos) @@ -1257,13 +1282,17 @@ class Terminator: grandparent.insert_page(sibling, None,page) grandparent.set_tab_label_packing(sibling, True, True, gtk.PACK_START) grandparent.set_tab_reorderable(sibling, True) + grandparent.set_current_page(page) else: grandparent.remove (parent) sibling.reparent (grandparent) -# grandparent.resize_children() + grandparent.resize_children() parent.destroy () + if isinstance(sibling, TerminatorTerm) and isinstance(sibling.get_parent(), gtk.Notebook): + sibling._titlebox.hide() + self.term_list.remove (widget) if not isinstance (sibling, gtk.Paned): @@ -1293,20 +1322,18 @@ class Terminator: else: gdparent.remove(parent) gdparent.pack2(sibling) + if isinstance(sibling, TerminatorTerm) and sibling.conf.titlebars and sibling.conf.extreme_tabs: + sibling._titlebox.show() parent.destroy() - if index == 0: index = 1 - self.term_list[index - 1]._vte.grab_focus () - + if index == 0: index = 1 + self.term_list[index - 1]._vte.grab_focus () + self._set_current_notebook_page_recursive(self.term_list[index - 1]) if len(self.term_list) == 1: self.term_list[0]._titlebox.hide() return True def closeterm (self, widget): - if self._fullwindow: - dbg ("closeterm function called while Terminator was in full-window mode.") - self.show_back_others(widget) - if self.remove(widget): widget.destroy () return True @@ -1323,20 +1350,9 @@ class Terminator: nextterm = self.term_list[next] - if isinstance(nextterm.get_parent(), gtk.Notebook): - box = nextterm - parent = box.get_parent() - for i in range(0, parent.get_n_pages()): - if box == parent.get_nth_page(i): - parent.set_current_page(i) - break - notebookpage = self.get_first_notebook_page(nextterm) - if notebookpage: - child = None - for i in range(0, notebookpage[0].get_n_pages()): - if notebookpage[0].get_nth_page(i) == notebookpage[1]: - notebookpage[0].set_current_page(i) - break + ##we need to set the current page of each notebook + self._set_current_notebook_page_recursive(nextterm) + nextterm._vte.grab_focus () @@ -1351,22 +1367,20 @@ class Terminator: #self.window.set_title(self.term_list[previous]._vte.get_window_title()) previousterm = self.term_list[previous] - if isinstance(previousterm.get_parent(), gtk.Notebook): - box = previousterm - parent = box.get_parent() - for i in range(0, parent.get_n_pages()): - if box == parent.get_nth_page(i): - parent.set_current_page(i) - break - notebookpage = self.get_first_notebook_page(previousterm) - if notebookpage: - child = None - for i in range(0, notebookpage[0].get_n_pages()): - if notebookpage[0].get_nth_page(i) == notebookpage[1]: - notebookpage[0].set_current_page(i) - break + ##we need to set the current page of each notebook + self._set_current_notebook_page_recursive(previousterm) previousterm._vte.grab_focus () + + def _set_current_notebook_page_recursive(self, widget): + page = self.get_first_notebook_page(widget) + while page: + child = None + page_num = page[0].page_num(page[1]) + page[0].set_current_page(page_num) + page = self.get_first_notebook_page(page[0]) + + def resizeterm (self, widget, keyname): vertical = False if keyname in ('Up', 'Down'): @@ -1385,9 +1399,9 @@ class Terminator: if keyname in ('Up', 'Down'): maxi = parent.get_child1().get_allocation().height + parent.get_child2().get_allocation().height - 1 + else: maxi = parent.get_child1().get_allocation().width + parent.get_child2().get_allocation().width - 1 - move = 10 if keyname in ('Up', 'Left'): move = -10 @@ -1396,13 +1410,6 @@ class Terminator: move = min(maxi, move) parent.set_position(move) - if keyname in ('Up', 'Down'): - ratio = 100 * parent.get_child1().get_allocation().height / maxi - else: - ratio = 100 * parent.get_child1().get_allocation().width / maxi - setattr(parent, "ratio", ratio) - print parent.get_position() - print ratio def previous_tab(self, term): notebook = self.get_first_parent_notebook(term) @@ -1473,44 +1480,7 @@ class Terminator: for term in self.term_list: term.reconfigure_vte () - def fullwindow(self, widget): - if not self._fullwindow: - self.hide_all_but_me(widget) - else: - self.show_back_others(widget) - - def hide_all_but_me (self, widget): - """Proof of concept: Maximize to full window - an instance of TerminatorTerm. - """ - self.old_parent = widget.get_parent() - if isinstance(self.old_parent, gtk.Window): - return - if isinstance(self.old_parent, gtk.Notebook): - self.old_page = self.old_parent.get_current_page() - self.window_child = self.window.get_children()[0] - self.window.remove(self.window_child) - self.old_parent.remove(widget) - self.window.add(widget) - self._fullwindow = True - - def show_back_others(self, widget): - """Proof of concept: Go back to previous application - widget structure. - """ - if self._fullwindow: - self.window.remove(widget) - self.window.add(self.window_child) - self.old_parent.add(widget) - if isinstance(self.old_parent, gtk.Notebook): - self.old_parent.set_current_page(self.old_page) - self._fullwindow = False - return - else: - return - if __name__ == '__main__': - def execute_cb (option, opt, value, parser): assert value is None value = [] @@ -1544,7 +1514,12 @@ if __name__ == '__main__': command.append (options.command) if (options.execute): command = options.execute - + + if gtk.gdk.display_get_default() == None: + print >> sys.stderr, _("You need to run terminator in an X environment. " \ + "Make sure DISPLAY is properly set") + sys.exit(1) + term = Terminator (options.profile, command, options.fullscreen, options.maximise, options.borderless) gtk.main () diff --git a/terminatorlib/config.py b/terminatorlib/config.py index 751fef06..3bc5fe64 100755 --- a/terminatorlib/config.py +++ b/terminatorlib/config.py @@ -114,6 +114,11 @@ class TerminatorConfValuestore: 'encoding' : 'UTF-8', 'active_encodings' : ['UTF-8', 'ISO-8859-1'], 'background_image' : '', + 'extreme_tabs' : False, + 'fullscreen' : False, + 'borderless' : False, + 'maximise' : False, + 'handle_size' : -1, } def __getattr__ (self, keyname): From 9729af5118b6db8453e42dbf7c005233b6dd38e6 Mon Sep 17 00:00:00 2001 From: Edoardo Batini Date: Thu, 29 May 2008 14:40:58 +0200 Subject: [PATCH 16/19] Full window mode re-enabled --- terminator | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) diff --git a/terminator b/terminator index c59859ed..64ad5667 100755 --- a/terminator +++ b/terminator @@ -743,6 +743,13 @@ text/plain item = gtk.MenuItem () menu.append (item) + item = gtk.MenuItem (_("M_aximize/Unmaximize")) + item.connect ("activate", lambda menu_item: self.terminator.fullwindow (self)) + menu.append (item) + + item = gtk.MenuItem () + menu.append (item) + item = gtk.ImageMenuItem (gtk.STOCK_CLOSE) item.connect ("activate", lambda menu_item: self.terminator.closeterm (self)) menu.append (item) @@ -843,6 +850,7 @@ class Terminator: self.profile = profile self.command = command + self._fullwindow = False self._fullscreen = False self.term_list = [] stores = [] @@ -1155,6 +1163,13 @@ class Terminator: return None def newtab(self,widget, toplevel = False): + ## Lines added for fullwidow (not fullscreen) support. + ## Disables adding new tab when a terminal is + ## maximized + if self._fullwindow: + dbg ("newtab function called, but Terminator was in full-window mode.") + return + terminal = TerminatorTerm (self, self.profile, None, widget.get_cwd()) #only one term, we don't show the title terminal._titlebox.hide() @@ -1235,6 +1250,12 @@ class Terminator: def splitaxis (self, widget, vertical=True): """ Split the provided widget on the horizontal or vertical axis. """ + ## Lines added for fullwidow (not fullscreen) support. + ## Disables splitaxis when a terminal is maximized + if self._fullwindow: + dbg ("splitaxis function called, but Terminator was in full-window mode.") + return + # create a new terminal and parent pane. terminal = TerminatorTerm (self, self.profile, None, widget.get_cwd()) pos = vertical and "bottom" or "right" @@ -1288,7 +1309,8 @@ class Terminator: else: grandparent.remove (parent) sibling.reparent (grandparent) - grandparent.resize_children() + if not self._fullwindow: + grandparent.resize_children() parent.destroy () if isinstance(sibling, TerminatorTerm) and isinstance(sibling.get_parent(), gtk.Notebook): sibling._titlebox.hide() @@ -1334,6 +1356,13 @@ class Terminator: return True def closeterm (self, widget): + ## Lines added for fullwidow (not fullscreen) support. + ## Disables adding new tab when a terminal is + ## maximized + if self._fullwindow: + dbg ("closeterm function called while in full-window mode. Restoring previous layout before closing.") + self.show_back_others(widget) + if self.remove(widget): widget.destroy () return True @@ -1480,6 +1509,46 @@ class Terminator: for term in self.term_list: term.reconfigure_vte () + ## Full window mode functions + + def fullwindow(self, widget): + if not self._fullwindow: + self.hide_all_but_me(widget) + else: + self.show_back_others(widget) + + def hide_all_but_me (self, widget): + """Proof of concept: Maximize to full window + an instance of TerminatorTerm. + """ + self.old_parent = widget.get_parent() + if isinstance(self.old_parent, gtk.Window): + return + if isinstance(self.old_parent, gtk.Notebook): + self.old_page = self.old_parent.get_current_page() + self.window_child = self.window.get_children()[0] + self.window.remove(self.window_child) + self.old_parent.remove(widget) + self.window.add(widget) + self._fullwindow = True + + def show_back_others(self, widget): + """Proof of concept: Go back to previous application + widget structure. + """ + if self._fullwindow: + self.window.remove(widget) + self.window.add(self.window_child) + self.old_parent.add(widget) + if isinstance(self.old_parent, gtk.Notebook): + self.old_parent.set_current_page(self.old_page) + print "\nPARENT IS A NOTEBOOK\n" + self._fullwindow = False + return + else: + return + + if __name__ == '__main__': def execute_cb (option, opt, value, parser): assert value is None From bcad01126a4ff3b2e6c05152f4ce4925e04d8c20 Mon Sep 17 00:00:00 2001 From: Chris Jones Date: Fri, 30 May 2008 13:09:24 +0100 Subject: [PATCH 17/19] rework full-window-term branch to be called terminal zooming, and make the menu entries make a little more sense --- ChangeLog | 2 ++ terminator | 99 +++++++++++++++++++++++++++--------------------------- 2 files changed, 51 insertions(+), 50 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7c263d18..7394ac0b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -18,6 +18,8 @@ terminator 0.9: * Drag & Drop support * Many bug fixes and wider compatibility with GNOME Terminal * Alpha transparency support when running in a composited window manager + * Support terminal zooming - now you can quickly hide all terminals apart + from one terminator 0.8.1: * Fixed ChangeLog diff --git a/terminator b/terminator index 64ad5667..3d760dda 100755 --- a/terminator +++ b/terminator @@ -723,32 +723,38 @@ text/plain item = gtk.MenuItem () menu.append (item) - item = gtk.MenuItem (_("Split H_orizontally")) - item.connect ("activate", lambda menu_item: self.terminator.splitaxis (self, False)) - menu.append (item) - - item = gtk.MenuItem (_("Split V_ertically")) - item.connect ("activate", lambda menu_item: self.terminator.splitaxis (self, True)) - menu.append (item) - - item = gtk.MenuItem (_("Open _Tab")) - item.connect ("activate", lambda menu_item: self.terminator.newtab (self)) - menu.append (item) - - if self.conf.extreme_tabs: - item = gtk.MenuItem (_("Open Top Level Tab")) - item.connect ("activate", lambda menu_item: self.terminator.newtab (self, True)) + if not self.terminator._zoomed: + item = gtk.MenuItem (_("Split H_orizontally")) + item.connect ("activate", lambda menu_item: self.terminator.splitaxis (self, False)) menu.append (item) + + item = gtk.MenuItem (_("Split V_ertically")) + item.connect ("activate", lambda menu_item: self.terminator.splitaxis (self, True)) + menu.append (item) + + item = gtk.MenuItem (_("Open _Tab")) + item.connect ("activate", lambda menu_item: self.terminator.newtab (self)) + menu.append (item) + + if self.conf.extreme_tabs: + item = gtk.MenuItem (_("Open Top Level Tab")) + item.connect ("activate", lambda menu_item: self.terminator.newtab (self, True)) + menu.append (item) - item = gtk.MenuItem () - menu.append (item) + item = gtk.MenuItem () + menu.append (item) - item = gtk.MenuItem (_("M_aximize/Unmaximize")) - item.connect ("activate", lambda menu_item: self.terminator.fullwindow (self)) - menu.append (item) + if len (self.terminator.term_list) > 1: + if not self.terminator._zoomed: + item = gtk.MenuItem (_("_Zoom terminal")) + item.connect ("activate", lambda menu_item: self.terminator.toggle_zoom (self)) + else: + item = gtk.MenuItem (_("_Unzoom terminal")) + item.connect ("activate", lambda menu_item: self.terminator.toggle_zoom (self)) + menu.append (item) - item = gtk.MenuItem () - menu.append (item) + item = gtk.MenuItem () + menu.append (item) item = gtk.ImageMenuItem (gtk.STOCK_CLOSE) item.connect ("activate", lambda menu_item: self.terminator.closeterm (self)) @@ -850,7 +856,7 @@ class Terminator: self.profile = profile self.command = command - self._fullwindow = False + self._zoomed = False self._fullscreen = False self.term_list = [] stores = [] @@ -1163,11 +1169,9 @@ class Terminator: return None def newtab(self,widget, toplevel = False): - ## Lines added for fullwidow (not fullscreen) support. - ## Disables adding new tab when a terminal is - ## maximized - if self._fullwindow: - dbg ("newtab function called, but Terminator was in full-window mode.") + if self._zoomed: + # We don't want to add a new tab while we are zoomed in on a terminal + dbg ("newtab function called, but Terminator was in zoomed terminal mode.") return terminal = TerminatorTerm (self, self.profile, None, widget.get_cwd()) @@ -1250,10 +1254,9 @@ class Terminator: def splitaxis (self, widget, vertical=True): """ Split the provided widget on the horizontal or vertical axis. """ - ## Lines added for fullwidow (not fullscreen) support. - ## Disables splitaxis when a terminal is maximized - if self._fullwindow: - dbg ("splitaxis function called, but Terminator was in full-window mode.") + if self._zoomed: + # We don't want to split the terminal while we are in zoomed mode + dbg ("splitaxis function called, but Terminator was in zoomed mode.") return # create a new terminal and parent pane. @@ -1309,7 +1312,7 @@ class Terminator: else: grandparent.remove (parent) sibling.reparent (grandparent) - if not self._fullwindow: + if not self._zoomed: grandparent.resize_children() parent.destroy () if isinstance(sibling, TerminatorTerm) and isinstance(sibling.get_parent(), gtk.Notebook): @@ -1356,12 +1359,10 @@ class Terminator: return True def closeterm (self, widget): - ## Lines added for fullwidow (not fullscreen) support. - ## Disables adding new tab when a terminal is - ## maximized - if self._fullwindow: - dbg ("closeterm function called while in full-window mode. Restoring previous layout before closing.") - self.show_back_others(widget) + if self._zoomed: + # We are zoomed, pop back out to normal layout before closing + dbg ("closeterm function called while in zoomed mode. Restoring previous layout before closing.") + self.unzoom_term (widget) if self.remove(widget): widget.destroy () @@ -1509,15 +1510,13 @@ class Terminator: for term in self.term_list: term.reconfigure_vte () - ## Full window mode functions - - def fullwindow(self, widget): - if not self._fullwindow: - self.hide_all_but_me(widget) + def toggle_zoom(self, widget): + if not self._zoomed: + self.zoom_term (widget) else: - self.show_back_others(widget) + self.unzoom_term (widget) - def hide_all_but_me (self, widget): + def zoom_term (self, widget): """Proof of concept: Maximize to full window an instance of TerminatorTerm. """ @@ -1530,20 +1529,20 @@ class Terminator: self.window.remove(self.window_child) self.old_parent.remove(widget) self.window.add(widget) - self._fullwindow = True + self._zoomed = True - def show_back_others(self, widget): + def unzoom_term (self, widget): """Proof of concept: Go back to previous application widget structure. """ - if self._fullwindow: + if self._zoomed: self.window.remove(widget) self.window.add(self.window_child) self.old_parent.add(widget) if isinstance(self.old_parent, gtk.Notebook): self.old_parent.set_current_page(self.old_page) print "\nPARENT IS A NOTEBOOK\n" - self._fullwindow = False + self._zoomed = False return else: return From af6c18a7690c4b01c21e5e4b8b0854c1f65d8f6e Mon Sep 17 00:00:00 2001 From: Chris Jones Date: Fri, 30 May 2008 13:19:35 +0100 Subject: [PATCH 18/19] rework the full-window-term code a little so that it is referred to as terminal zooming (perhaps an unfortunate name wrt zooming fonts), make the context menu items behave a little better and add a keyboard shortcut --- terminator | 3 +++ 1 file changed, 3 insertions(+) diff --git a/terminator b/terminator index 3d760dda..7698ba15 100755 --- a/terminator +++ b/terminator @@ -623,6 +623,9 @@ text/plain elif keyname == 'Page_Up': self.terminator.move_tab(self, 'left') return (True) + elif keyname == 'Z': + self.terminator.toggle_zoom (self) + return (True) mask = gtk.gdk.CONTROL_MASK if (event.state & mask) == mask: From a416f092cecd7c69ad76179924530a1ac2a623ea Mon Sep 17 00:00:00 2001 From: Chris Jones Date: Fri, 30 May 2008 13:20:49 +0100 Subject: [PATCH 19/19] document ctrl-shift-z --- doc/terminator.1 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/terminator.1 b/doc/terminator.1 index 9dd051d0..7bd4392d 100644 --- a/doc/terminator.1 +++ b/doc/terminator.1 @@ -77,6 +77,9 @@ Move to \fBp\fRrevious terminal. .B Ctrl+Shift+W Close the current terminal. .TP +.B Ctrl+Shift+Z +Toggle between showing all terminals and only showing the current one. +.TP .B Ctrl+Shift+Q Close the current window. .TP