From 5c3d3c5c2e8ba3309630e416d3602da537f73f5b Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Thu, 18 Dec 2008 23:41:55 -0800 Subject: [PATCH 1/2] first pass at direction terminal control --- terminatorlib/config.py | 4 + terminatorlib/terminator.py | 158 +++++++++++++++++++++++++++++--- terminatorlib/terminatorterm.py | 22 +++++ 3 files changed, 169 insertions(+), 15 deletions(-) diff --git a/terminatorlib/config.py b/terminatorlib/config.py index 7d369819..5ecb2bf7 100755 --- a/terminatorlib/config.py +++ b/terminatorlib/config.py @@ -114,6 +114,10 @@ Defaults = { 'new_tab' : 'T', 'go_next' : ('N','Tab'), 'go_prev' : ('P','Tab'), + 'go_up' : 'Up', + 'go_down' : 'Down', + 'go_left' : 'Left', + 'go_right' : 'Right', 'split_horiz' : 'O', 'split_vert' : 'E', 'close_term' : 'W', diff --git a/terminatorlib/terminator.py b/terminatorlib/terminator.py index 7b88b770..74b370b6 100755 --- a/terminatorlib/terminator.py +++ b/terminatorlib/terminator.py @@ -823,7 +823,146 @@ class Terminator: return True return False + def go_to (self, term, selector): + current = self.term_list.index (term) + target = selector (term) + if not target is None: + term = self.term_list[target] + ##we need to set the current page of each notebook + self._set_current_notebook_page_recursive(term) + term._vte.grab_focus () + + def _select_direction (self, term, matcher): + current = self.term_list.index (term) + current_x, current_y = term.get_cursor_xy () + best_index = None + best_x = None + best_y = None + + for i in range(0,len(self.term_list)): + if i == current: + continue + possible = self.term_list[i] + possible_x, possible_y = possible.get_cursor_xy() + print "I am %d %d:%d, saw %d %d:%d" % (current, current_x, current_y, i, possible_x, possible_y) + if matcher (current_x, current_y, possible_x, possible_y, \ + best_x, best_y): + best_index = i + best_x = possible_x + best_y = possible_y + if best_index is None: + print "nothing best" + else: + print "sending %d" % (best_index) + return best_index + + def _match_up (self, current_x, current_y, possible_x, possible_y, \ + best_x, best_y): + print "matching up..." + if possible_y < current_y: + print "possible_y < current_y" + if best_x is None or best_y is None: + print "first thing up" + return True + if possible_y < best_y: + print "closer y" + return True + if possible_y == best_y: + print "same y" + if abs(possible_x) < abs(best_x - current_x): + print "closer x" + return True + print "fail" + return False + + def _match_down (self, current_x, current_y, possible_x, possible_y, \ + best_x, best_y): + print "matching down..." + if possible_y > current_y: + print "possible_y > current_y" + if best_x is None or best_y is None: + print "first thing down" + return True + if possible_y > best_y: + print "closer y" + return True + if possible_y == best_y: + print "same y" + if abs(possible_x) < abs(best_x - current_x): + print "closer x" + return True + print "fail" + return False + + def _match_left (self, current_x, current_y, possible_x, possible_y, \ + best_x, best_y): + print "matching left..." + if possible_x < current_x: + print "possible_x < current_x" + if best_x is None or best_y is None: + print "first thing left" + return True + if possible_x > best_x: + print "closer x" + return True + if possible_x == best_x: + print "same x" + if abs(possible_y) < abs(best_y - current_y): + print "closer y" + return True + print "fail" + return False + + def _match_right (self, current_x, current_y, possible_x, possible_y, \ + best_x, best_y): + print "matching right..." + if possible_x > current_x: + print "possible_x > current_x" + if best_x is None or best_y is None: + print "first thing right" + return True + if possible_x < best_x: + print "closer x" + return True + if possible_x == best_x: + print "same x" + if abs(possible_y) < abs(best_y - current_y): + print "closer y" + return True + print "fail" + return False + + def _select_up (self, term): + return self._select_direction (term, self._match_up) + + def _select_down (self, term): + return self._select_direction (term, self._match_down) + + def _select_left (self, term): + return self._select_direction (term, self._match_left) + + def _select_right (self, term): + return self._select_direction (term, self._match_right) + def go_next (self, term): + self.go_to (term, self._select_next) + + def go_prev (self, term): + self.go_to (term, self._select_prev) + + def go_up (self, term): + self.go_to (term, self._select_up) + + def go_down (self, term): + self.go_to (term, self._select_down) + + def go_left (self, term): + self.go_to (term, self._select_left) + + def go_right (self, term): + self.go_to (term, self._select_right) + + def _select_next (self, term): current = self.term_list.index (term) next = None if self.conf.cycle_term_tab: @@ -833,23 +972,17 @@ class Terminator: first = self._notebook_first_term(notebookpage[1]) if term == last: next = self.term_list.index(first) - + if next is None: if current == len (self.term_list) - 1: next = 0 else: next = current + 1 + return next - nextterm = self.term_list[next] - ##we need to set the current page of each notebook - self._set_current_notebook_page_recursive(nextterm) - - nextterm._vte.grab_focus () - - def go_prev (self, term): + def _select_prev (self, term): current = self.term_list.index (term) previous = None - if self.conf.cycle_term_tab: notebookpage = self.get_first_notebook_page(term) if notebookpage: @@ -863,12 +996,7 @@ class Terminator: previous = len (self.term_list) - 1 else: previous = current - 1 - - #self.window.set_title(self.term_list[previous]._vte.get_window_title()) - previousterm = self.term_list[previous] - ##we need to set the current page of each notebook - self._set_current_notebook_page_recursive(previousterm) - previousterm._vte.grab_focus () + return previous def _set_current_notebook_page_recursive(self, widget): page = self.get_first_notebook_page(widget) diff --git a/terminatorlib/terminatorterm.py b/terminatorlib/terminatorterm.py index 5b652bac..93c210cf 100755 --- a/terminatorlib/terminatorterm.py +++ b/terminatorlib/terminatorterm.py @@ -747,6 +747,18 @@ text/plain def key_go_prev(self): self.terminator.go_prev (self) + def key_go_up(self): + self.terminator.go_up (self) + + def key_go_down(self): + self.terminator.go_down (self) + + def key_go_left(self): + self.terminator.go_left (self) + + def key_go_right(self): + self.terminator.go_right (self) + def key_split_horiz(self): self.terminator.splitaxis (self, False) @@ -872,6 +884,16 @@ text/plain startrow = max(0, endrow - self.conf.scrollback_lines) return(startrow, endrow) + def get_cursor_xy (self): + column, row = self._vte.get_cursor_position () + cursor_x = column * self._vte.get_char_width () + cursor_y = row * self._vte.get_char_height () + x, y = self._vte.window.get_position () + #dbg("origin at %d:%d, cursor at %d:%d (%d:%d)" % (x, y, column, row, cursor_x, cursor_y)) + x = x + cursor_x + y = y + cursor_y + return (x, y) + def create_popup_menu (self, widget, event = None): menu = gtk.Menu () url = None From 04cecacdbb6fb01a716c09225d20f18b6c8ccb2b Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Fri, 19 Dec 2008 15:17:43 -0800 Subject: [PATCH 2/2] take full geometry of the terminals into account --- terminatorlib/terminator.py | 193 ++++++++++++++++++++------------ terminatorlib/terminatorterm.py | 27 +++-- 2 files changed, 144 insertions(+), 76 deletions(-) diff --git a/terminatorlib/terminator.py b/terminatorlib/terminator.py index 74b370b6..1a675361 100755 --- a/terminatorlib/terminator.py +++ b/terminatorlib/terminator.py @@ -834,102 +834,157 @@ class Terminator: def _select_direction (self, term, matcher): current = self.term_list.index (term) - current_x, current_y = term.get_cursor_xy () + current_geo = term.get_geometry () best_index = None - best_x = None - best_y = None + best_geo = None for i in range(0,len(self.term_list)): if i == current: continue possible = self.term_list[i] - possible_x, possible_y = possible.get_cursor_xy() - print "I am %d %d:%d, saw %d %d:%d" % (current, current_x, current_y, i, possible_x, possible_y) - if matcher (current_x, current_y, possible_x, possible_y, \ - best_x, best_y): + possible_geo = possible.get_geometry () + + #import pprint + #print "I am %d" % (current) + #pprint.pprint(current_geo) + #print "I saw %d" % (i) + #pprint.pprint(possible_geo) + + if matcher (current_geo, possible_geo, best_geo): best_index = i - best_x = possible_x - best_y = possible_y - if best_index is None: - print "nothing best" - else: - print "sending %d" % (best_index) + best_geo = possible_geo + #if best_index is None: + # print "nothing best" + #else: + # print "sending %d" % (best_index) return best_index - def _match_up (self, current_x, current_y, possible_x, possible_y, \ - best_x, best_y): - print "matching up..." - if possible_y < current_y: - print "possible_y < current_y" - if best_x is None or best_y is None: - print "first thing up" + def _match_up (self, current_geo, possible_geo, best_geo): + '''We want to find terminals that are fully above the top + border, but closest in the y direction, breaking ties via + the closest cursor x position.''' + #print "matching up..." + # top edge of the current terminal + edge = current_geo['origin_y'] + # botoom edge of the possible target + new_edge = possible_geo['origin_y']+possible_geo['span_y'] + if new_edge < edge: + #print "new_edge < edge" + if best_geo is None: + #print "first thing left" return True - if possible_y < best_y: - print "closer y" + best_edge = best_geo['origin_y']+best_geo['span_y'] + if new_edge > best_edge: + #print "closer y" return True - if possible_y == best_y: - print "same y" - if abs(possible_x) < abs(best_x - current_x): - print "closer x" + if new_edge == best_edge: + #print "same y" + + cursor = current_geo['origin_x'] + current_geo['cursor_x'] + new_cursor = possible_geo['origin_x'] + possible_geo['cursor_x'] + best_cursor = best_geo['origin_x'] + best_geo['cursor_x'] + + if abs(new_cursor - cursor) < abs(best_cursor - cursor): + #print "closer x" return True - print "fail" + #print "fail" return False - def _match_down (self, current_x, current_y, possible_x, possible_y, \ - best_x, best_y): - print "matching down..." - if possible_y > current_y: - print "possible_y > current_y" - if best_x is None or best_y is None: - print "first thing down" + def _match_down (self, current_geo, possible_geo, best_geo): + '''We want to find terminals that are fully below the bottom + border, but closest in the y direction, breaking ties via + the closest cursor x position.''' + #print "matching down..." + # bottom edge of the current terminal + edge = current_geo['origin_y']+current_geo['span_y'] + # top edge of the possible target + new_edge = possible_geo['origin_y'] + #print "edge: %d new_edge: %d" % (edge, new_edge) + if new_edge > edge: + #print "new_edge > edge" + if best_geo is None: + #print "first thing right" return True - if possible_y > best_y: - print "closer y" + best_edge = best_geo['origin_y'] + #print "best_edge: %d" % (best_edge) + if new_edge < best_edge: + #print "closer y" return True - if possible_y == best_y: - print "same y" - if abs(possible_x) < abs(best_x - current_x): - print "closer x" + if new_edge == best_edge: + #print "same y" + + cursor = current_geo['origin_x'] + current_geo['cursor_x'] + new_cursor = possible_geo['origin_x'] + possible_geo['cursor_x'] + best_cursor = best_geo['origin_x'] + best_geo['cursor_x'] + + if abs(new_cursor - cursor) < abs(best_cursor - cursor): + #print "closer x" return True - print "fail" + #print "fail" return False - def _match_left (self, current_x, current_y, possible_x, possible_y, \ - best_x, best_y): - print "matching left..." - if possible_x < current_x: - print "possible_x < current_x" - if best_x is None or best_y is None: - print "first thing left" + def _match_left (self, current_geo, possible_geo, best_geo): + '''We want to find terminals that are fully to the left of + the left-side border, but closest in the x direction, breaking + ties via the closest cursor y position.''' + #print "matching left..." + # left-side edge of the current terminal + edge = current_geo['origin_x'] + # right-side edge of the possible target + new_edge = possible_geo['origin_x']+possible_geo['span_x'] + if new_edge < edge: + #print "new_edge(%d) < edge(%d)" % (new_edge, edge) + if best_geo is None: + #print "first thing left" return True - if possible_x > best_x: - print "closer x" + best_edge = best_geo['origin_x']+best_geo['span_x'] + if new_edge > best_edge: + #print "closer x (new_edge(%d) > best_edge(%d))" % (new_edge, best_edge) return True - if possible_x == best_x: - print "same x" - if abs(possible_y) < abs(best_y - current_y): - print "closer y" + if new_edge == best_edge: + #print "same x" + + cursor = current_geo['origin_y'] + current_geo['cursor_y'] + new_cursor = possible_geo['origin_y'] + possible_geo['cursor_y'] + best_cursor = best_geo['origin_y'] + best_geo['cursor_y'] + + if abs(new_cursor - cursor) < abs(best_cursor - cursor): + #print "closer y" return True - print "fail" + #print "fail" return False - def _match_right (self, current_x, current_y, possible_x, possible_y, \ - best_x, best_y): - print "matching right..." - if possible_x > current_x: - print "possible_x > current_x" - if best_x is None or best_y is None: - print "first thing right" + def _match_right (self, current_geo, possible_geo, best_geo): + '''We want to find terminals that are fully to the right of + the right-side border, but closest in the x direction, breaking + ties via the closest cursor y position.''' + #print "matching right..." + # right-side edge of the current terminal + edge = current_geo['origin_x']+current_geo['span_x'] + # left-side edge of the possible target + new_edge = possible_geo['origin_x'] + #print "edge: %d new_edge: %d" % (edge, new_edge) + if new_edge > edge: + #print "new_edge > edge" + if best_geo is None: + #print "first thing right" return True - if possible_x < best_x: - print "closer x" + best_edge = best_geo['origin_x'] + #print "best_edge: %d" % (best_edge) + if new_edge < best_edge: + #print "closer x" return True - if possible_x == best_x: - print "same x" - if abs(possible_y) < abs(best_y - current_y): - print "closer y" + if new_edge == best_edge: + #print "same x" + + cursor = current_geo['origin_y'] + current_geo['cursor_y'] + new_cursor = possible_geo['origin_y'] + possible_geo['cursor_y'] + best_cursor = best_geo['origin_y'] + best_geo['cursor_y'] + + if abs(new_cursor - cursor) < abs(best_cursor - cursor): + #print "closer y" return True - print "fail" + #print "fail" return False def _select_up (self, term): diff --git a/terminatorlib/terminatorterm.py b/terminatorlib/terminatorterm.py index 93c210cf..b27b74be 100755 --- a/terminatorlib/terminatorterm.py +++ b/terminatorlib/terminatorterm.py @@ -884,15 +884,28 @@ text/plain startrow = max(0, endrow - self.conf.scrollback_lines) return(startrow, endrow) - def get_cursor_xy (self): + def get_geometry (self): + '''Returns Gdk.Window.get_position(), pixel-based cursor position, + and Gdk.Window.get_geometry()''' + reply = dict() + x, y = self._vte.window.get_origin () + reply.setdefault('origin_x',x) + reply.setdefault('origin_y',y) + column, row = self._vte.get_cursor_position () cursor_x = column * self._vte.get_char_width () - cursor_y = row * self._vte.get_char_height () - x, y = self._vte.window.get_position () - #dbg("origin at %d:%d, cursor at %d:%d (%d:%d)" % (x, y, column, row, cursor_x, cursor_y)) - x = x + cursor_x - y = y + cursor_y - return (x, y) + cursor_y = row * self._vte.get_char_height () + reply.setdefault('cursor_x', cursor_x) + reply.setdefault('cursor_y', cursor_y) + + geometry = self._vte.window.get_geometry() + reply.setdefault('offset_x', geometry[0]) + reply.setdefault('offset_y', geometry[1]) + reply.setdefault('span_x', geometry[2]) + reply.setdefault('span_y', geometry[3]) + reply.setdefault('depth', geometry[4]) + + return reply def create_popup_menu (self, widget, event = None): menu = gtk.Menu ()