Optimise various low level parts (Stephen Boddy)
This commit is contained in:
commit
32b8d04695
|
@ -3,6 +3,8 @@ terminator 0.96:
|
||||||
* Fix searching with infinite scrollback (Julien Thewys #755077)
|
* Fix searching with infinite scrollback (Julien Thewys #755077)
|
||||||
* Fix searching on Ubuntu 10.10 and 11.04, and implement searching
|
* Fix searching on Ubuntu 10.10 and 11.04, and implement searching
|
||||||
by regular expression (Roberto Aguilar #709018)
|
by regular expression (Roberto Aguilar #709018)
|
||||||
|
* Optimise various low level components so they are dramatically
|
||||||
|
faster (Stephen Boddy)
|
||||||
|
|
||||||
terminator 0.95:
|
terminator 0.95:
|
||||||
* Add a configuration option to enable a DBus server
|
* Add a configuration option to enable a DBus server
|
||||||
|
|
|
@ -195,7 +195,9 @@ the %s will also close all terminals within it.') % (reqtype, reqtype))
|
||||||
def get_visible_terminals(self):
|
def get_visible_terminals(self):
|
||||||
"""Walk the widget tree to find all of the visible terminals. That is,
|
"""Walk the widget tree to find all of the visible terminals. That is,
|
||||||
any terminals which are not hidden in another Notebook pane"""
|
any terminals which are not hidden in another Notebook pane"""
|
||||||
maker = Factory()
|
if not hasattr(self, 'cached_maker'):
|
||||||
|
self.cached_maker = Factory()
|
||||||
|
maker = self.cached_maker
|
||||||
terminals = {}
|
terminals = {}
|
||||||
|
|
||||||
for child in self.get_offspring():
|
for child in self.get_offspring():
|
||||||
|
|
|
@ -33,6 +33,9 @@ class Factory(Borg):
|
||||||
'Notebook': 'notebook',
|
'Notebook': 'notebook',
|
||||||
'Container': 'container',
|
'Container': 'container',
|
||||||
'Window': 'window'}
|
'Window': 'window'}
|
||||||
|
types_keys = types.keys()
|
||||||
|
instance_types = {}
|
||||||
|
instance_types_keys = []
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
"""Class initialiser"""
|
"""Class initialiser"""
|
||||||
|
@ -45,16 +48,25 @@ class Factory(Borg):
|
||||||
|
|
||||||
def isinstance(self, product, classtype):
|
def isinstance(self, product, classtype):
|
||||||
"""Check if a given product is a particular type of object"""
|
"""Check if a given product is a particular type of object"""
|
||||||
if classtype in self.types.keys():
|
if classtype in self.types_keys:
|
||||||
# This is quite ugly, but we're importing from the current
|
# This is now very ugly, but now it's fast :-)
|
||||||
# directory if that makes sense, otherwise falling back to
|
# Someone with real Python skills should fix this to be less insane.
|
||||||
# terminatorlib. Someone with real Python skills should fix
|
# Optimisations:
|
||||||
# this to be less insane.
|
# - swap order of imports, otherwise we throw ImportError
|
||||||
|
# almost every time
|
||||||
|
# - cache everything we can
|
||||||
try:
|
try:
|
||||||
module = __import__(self.types[classtype], None, None, [''])
|
type_key = 'terminatorlib.%s' % self.types[classtype]
|
||||||
|
if type_key not in self.instance_types_keys:
|
||||||
|
self.instance_types[type_key] = __import__(type_key, None, None, [''])
|
||||||
|
self.instance_types_keys.append(type_key)
|
||||||
|
module = self.instance_types[type_key]
|
||||||
except ImportError:
|
except ImportError:
|
||||||
module = __import__('terminatorlib.%s' % self.types[classtype],
|
type_key = self.types[classtype]
|
||||||
None, None, [''])
|
if type_key not in self.instance_types_keys:
|
||||||
|
self.instance_types[type_key] = __import__(type_key, None, None, [''])
|
||||||
|
self.instance_types_keys.append(type_key)
|
||||||
|
module = self.instance_types[type_key]
|
||||||
return(isinstance(product, getattr(module, classtype)))
|
return(isinstance(product, getattr(module, classtype)))
|
||||||
else:
|
else:
|
||||||
err('Factory::isinstance: unknown class type: %s' % classtype)
|
err('Factory::isinstance: unknown class type: %s' % classtype)
|
||||||
|
|
|
@ -12,7 +12,7 @@ from factory import Factory
|
||||||
from container import Container
|
from container import Container
|
||||||
from editablelabel import EditableLabel
|
from editablelabel import EditableLabel
|
||||||
from translation import _
|
from translation import _
|
||||||
from util import err, dbg, get_top_window, enumerate_descendants
|
from util import err, dbg, enumerate_descendants
|
||||||
|
|
||||||
class Notebook(Container, gtk.Notebook):
|
class Notebook(Container, gtk.Notebook):
|
||||||
"""Class implementing a gtk.Notebook container"""
|
"""Class implementing a gtk.Notebook container"""
|
||||||
|
@ -173,7 +173,7 @@ class Notebook(Container, gtk.Notebook):
|
||||||
def newtab(self, debugtab=False, widget=None, cwd=None):
|
def newtab(self, debugtab=False, widget=None, cwd=None):
|
||||||
"""Add a new tab, optionally supplying a child widget"""
|
"""Add a new tab, optionally supplying a child widget"""
|
||||||
maker = Factory()
|
maker = Factory()
|
||||||
top_window = get_top_window(self)
|
top_window = self.get_toplevel()
|
||||||
|
|
||||||
if not widget:
|
if not widget:
|
||||||
widget = maker.make('Terminal')
|
widget = maker.make('Terminal')
|
||||||
|
|
|
@ -7,7 +7,7 @@ variants"""
|
||||||
import gobject
|
import gobject
|
||||||
import gtk
|
import gtk
|
||||||
|
|
||||||
from util import dbg, err, get_top_window
|
from util import dbg, err
|
||||||
from terminator import Terminator
|
from terminator import Terminator
|
||||||
from factory import Factory
|
from factory import Factory
|
||||||
from container import Container
|
from container import Container
|
||||||
|
@ -86,7 +86,7 @@ class Paned(Container):
|
||||||
raise ValueError('Paned widgets can only have two children')
|
raise ValueError('Paned widgets can only have two children')
|
||||||
|
|
||||||
if maker.isinstance(widget, 'Terminal'):
|
if maker.isinstance(widget, 'Terminal'):
|
||||||
top_window = get_top_window(self)
|
top_window = self.get_toplevel()
|
||||||
signals = {'close-term': self.wrapcloseterm,
|
signals = {'close-term': self.wrapcloseterm,
|
||||||
'split-horiz': self.split_horiz,
|
'split-horiz': self.split_horiz,
|
||||||
'split-vert': self.split_vert,
|
'split-vert': self.split_vert,
|
||||||
|
|
|
@ -15,7 +15,7 @@ import pango
|
||||||
import subprocess
|
import subprocess
|
||||||
import urllib
|
import urllib
|
||||||
|
|
||||||
from util import dbg, err, gerr, get_top_window
|
from util import dbg, err, gerr
|
||||||
import util
|
import util
|
||||||
from config import Config
|
from config import Config
|
||||||
from cwd import get_default_cwd
|
from cwd import get_default_cwd
|
||||||
|
@ -118,6 +118,8 @@ class Terminal(gtk.VBox):
|
||||||
self.origcwd = self.terminator.origcwd
|
self.origcwd = self.terminator.origcwd
|
||||||
self.clipboard = gtk.clipboard_get(gtk.gdk.SELECTION_CLIPBOARD)
|
self.clipboard = gtk.clipboard_get(gtk.gdk.SELECTION_CLIPBOARD)
|
||||||
|
|
||||||
|
self.pending_on_vte_size_allocate = False
|
||||||
|
|
||||||
self.vte = vte.Terminal()
|
self.vte = vte.Terminal()
|
||||||
self.vte.set_size(80, 24)
|
self.vte.set_size(80, 24)
|
||||||
self.vte._expose_data = None
|
self.vte._expose_data = None
|
||||||
|
@ -335,7 +337,7 @@ for %s (%s)' % (name, urlplugin.__class__.__name__))
|
||||||
self.emit('title-change', self.get_window_title()))
|
self.emit('title-change', self.get_window_title()))
|
||||||
self.vte.connect('grab-focus', self.on_vte_focus)
|
self.vte.connect('grab-focus', self.on_vte_focus)
|
||||||
self.vte.connect('focus-in-event', self.on_vte_focus_in)
|
self.vte.connect('focus-in-event', self.on_vte_focus_in)
|
||||||
self.vte.connect('size-allocate', self.on_vte_size_allocate)
|
self.vte.connect('size-allocate', self.deferred_on_vte_size_allocate)
|
||||||
|
|
||||||
self.vte.add_events(gtk.gdk.ENTER_NOTIFY_MASK)
|
self.vte.add_events(gtk.gdk.ENTER_NOTIFY_MASK)
|
||||||
self.vte.connect('enter_notify_event',
|
self.vte.connect('enter_notify_event',
|
||||||
|
@ -747,7 +749,7 @@ for %s (%s)' % (name, urlplugin.__class__.__name__))
|
||||||
# maybe we can emit the key event and let Terminator() care?
|
# maybe we can emit the key event and let Terminator() care?
|
||||||
groupsend = self.terminator.groupsend
|
groupsend = self.terminator.groupsend
|
||||||
groupsend_type = self.terminator.groupsend_type
|
groupsend_type = self.terminator.groupsend_type
|
||||||
window_focussed = get_top_window(self.vte).get_property('has-toplevel-focus')
|
window_focussed = self.vte.get_toplevel().get_property('has-toplevel-focus')
|
||||||
if groupsend != groupsend_type['off'] and window_focussed and self.vte.is_focus():
|
if groupsend != groupsend_type['off'] and window_focussed and self.vte.is_focus():
|
||||||
if self.group and groupsend == groupsend_type['group']:
|
if self.group and groupsend == groupsend_type['group']:
|
||||||
self.terminator.group_emit(self, self.group, 'key-press-event',
|
self.terminator.group_emit(self, self.group, 'key-press-event',
|
||||||
|
@ -961,7 +963,7 @@ for %s (%s)' % (name, urlplugin.__class__.__name__))
|
||||||
|
|
||||||
def ensure_visible_and_focussed(self):
|
def ensure_visible_and_focussed(self):
|
||||||
"""Make sure that we're visible and focussed"""
|
"""Make sure that we're visible and focussed"""
|
||||||
window = util.get_top_window(self)
|
window = self.get_toplevel()
|
||||||
topchild = window.get_child()
|
topchild = window.get_child()
|
||||||
maker = Factory()
|
maker = Factory()
|
||||||
|
|
||||||
|
@ -1002,12 +1004,24 @@ for %s (%s)' % (name, urlplugin.__class__.__name__))
|
||||||
"""A child widget is done editing a label, return focus to VTE"""
|
"""A child widget is done editing a label, return focus to VTE"""
|
||||||
self.vte.grab_focus()
|
self.vte.grab_focus()
|
||||||
|
|
||||||
|
def deferred_on_vte_size_allocate(self, widget, allocation):
|
||||||
|
# widget & allocation are not used in on_vte_size_allocate, so we
|
||||||
|
# can use the on_vte_size_allocate instead of duplicating the code
|
||||||
|
if self.pending_on_vte_size_allocate == True:
|
||||||
|
return
|
||||||
|
self.pending_on_vte_size_allocate = True
|
||||||
|
gobject.idle_add(self.do_deferred_on_vte_size_allocate, widget, allocation)
|
||||||
|
|
||||||
|
def do_deferred_on_vte_size_allocate(self, widget, allocation):
|
||||||
|
self.pending_on_vte_size_allocate = False
|
||||||
|
self.on_vte_size_allocate(widget, allocation)
|
||||||
|
|
||||||
def on_vte_size_allocate(self, widget, allocation):
|
def on_vte_size_allocate(self, widget, allocation):
|
||||||
self.titlebar.update_terminal_size(self.vte.get_column_count(),
|
self.titlebar.update_terminal_size(self.vte.get_column_count(),
|
||||||
self.vte.get_row_count())
|
self.vte.get_row_count())
|
||||||
if self.vte.window and self.config['geometry_hinting']:
|
if self.vte.window and self.config['geometry_hinting']:
|
||||||
window = util.get_top_window(self)
|
window = self.get_toplevel()
|
||||||
window.set_rough_geometry_hints()
|
window.deferred_set_rough_geometry_hints()
|
||||||
|
|
||||||
def on_vte_notify_enter(self, term, event):
|
def on_vte_notify_enter(self, term, event):
|
||||||
"""Handle the mouse entering this terminal"""
|
"""Handle the mouse entering this terminal"""
|
||||||
|
@ -1079,7 +1093,7 @@ for %s (%s)' % (name, urlplugin.__class__.__name__))
|
||||||
"""Determine if we are a zoomed terminal"""
|
"""Determine if we are a zoomed terminal"""
|
||||||
prop = None
|
prop = None
|
||||||
parent = self.get_parent()
|
parent = self.get_parent()
|
||||||
window = get_top_window(self)
|
window = self.get_toplevel()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
prop = window.get_property('term-zoomed')
|
prop = window.get_property('term-zoomed')
|
||||||
|
@ -1313,7 +1327,7 @@ for %s (%s)' % (name, urlplugin.__class__.__name__))
|
||||||
def on_beep(self, widget):
|
def on_beep(self, widget):
|
||||||
"""Set the urgency hint for our window"""
|
"""Set the urgency hint for our window"""
|
||||||
if self.config['urgent_bell'] == True:
|
if self.config['urgent_bell'] == True:
|
||||||
window = util.get_top_window(self)
|
window = self.get_toplevel()
|
||||||
window.set_urgency_hint(True)
|
window.set_urgency_hint(True)
|
||||||
if self.config['icon_bell'] == True:
|
if self.config['icon_bell'] == True:
|
||||||
self.titlebar.icon_bell()
|
self.titlebar.icon_bell()
|
||||||
|
|
|
@ -89,14 +89,6 @@ def has_ancestor(widget, wtype):
|
||||||
return(True)
|
return(True)
|
||||||
return(False)
|
return(False)
|
||||||
|
|
||||||
def get_top_window(widget):
|
|
||||||
"""Return the Window instance a widget belongs to"""
|
|
||||||
parent = widget.get_parent()
|
|
||||||
while parent:
|
|
||||||
widget = parent
|
|
||||||
parent = widget.get_parent()
|
|
||||||
return(widget)
|
|
||||||
|
|
||||||
def path_lookup(command):
|
def path_lookup(command):
|
||||||
'''Find a command in our path'''
|
'''Find a command in our path'''
|
||||||
if os.path.isabs(command):
|
if os.path.isabs(command):
|
||||||
|
|
|
@ -81,6 +81,8 @@ class Window(Container, gtk.Window):
|
||||||
err('Window::__init__: Unable to parse geometry: %s' %
|
err('Window::__init__: Unable to parse geometry: %s' %
|
||||||
options.geometry)
|
options.geometry)
|
||||||
|
|
||||||
|
self.pending_set_rough_geometry_hint = False
|
||||||
|
|
||||||
def do_get_property(self, prop):
|
def do_get_property(self, prop):
|
||||||
"""Handle gobject getting a property"""
|
"""Handle gobject getting a property"""
|
||||||
if prop.name in ['term_zoomed', 'term-zoomed']:
|
if prop.name in ['term_zoomed', 'term-zoomed']:
|
||||||
|
@ -480,7 +482,9 @@ class Window(Container, gtk.Window):
|
||||||
"""Walk down the widget tree to find all of the visible terminals.
|
"""Walk down the widget tree to find all of the visible terminals.
|
||||||
Mostly using Container::get_visible_terminals()"""
|
Mostly using Container::get_visible_terminals()"""
|
||||||
terminals = {}
|
terminals = {}
|
||||||
maker = Factory()
|
if not hasattr(self, 'cached_maker'):
|
||||||
|
self.cached_maker = Factory()
|
||||||
|
maker = self.cached_maker
|
||||||
child = self.get_child()
|
child = self.get_child()
|
||||||
|
|
||||||
if not child:
|
if not child:
|
||||||
|
@ -508,10 +512,24 @@ class Window(Container, gtk.Window):
|
||||||
return(terminal)
|
return(terminal)
|
||||||
return(None)
|
return(None)
|
||||||
|
|
||||||
|
def deferred_set_rough_geometry_hints(self):
|
||||||
|
# no parameters are used in set_rough_geometry_hints, so we can
|
||||||
|
# use the set_rough_geometry_hints
|
||||||
|
if self.pending_set_rough_geometry_hint == True:
|
||||||
|
return
|
||||||
|
self.pending_set_rough_geometry_hint = True
|
||||||
|
gobject.idle_add(self.do_deferred_set_rough_geometry_hints)
|
||||||
|
|
||||||
|
def do_deferred_set_rough_geometry_hints(self):
|
||||||
|
self.pending_set_rough_geometry_hint = False
|
||||||
|
self.set_rough_geometry_hints()
|
||||||
|
|
||||||
def set_rough_geometry_hints(self):
|
def set_rough_geometry_hints(self):
|
||||||
"""Walk all the terminals along the top and left edges to fake up how
|
"""Walk all the terminals along the top and left edges to fake up how
|
||||||
many columns/rows we sort of have"""
|
many columns/rows we sort of have"""
|
||||||
maker = Factory()
|
if not hasattr(self, 'cached_maker'):
|
||||||
|
self.cached_maker = Factory()
|
||||||
|
maker = self.cached_maker
|
||||||
if maker.isinstance(self.get_child(), 'Notebook'):
|
if maker.isinstance(self.get_child(), 'Notebook'):
|
||||||
dbg("We don't currently support geometry hinting with tabs")
|
dbg("We don't currently support geometry hinting with tabs")
|
||||||
return
|
return
|
||||||
|
|
Loading…
Reference in New Issue