diff options
author | Dieter Plaetinck <dieter@plaetinck.be> | 2010-03-23 10:34:24 +0100 |
---|---|---|
committer | Dieter Plaetinck <dieter@plaetinck.be> | 2010-03-23 10:34:24 +0100 |
commit | bfec366b7d36e195ef5c422c55ecbc4093deb201 (patch) | |
tree | a78f53361f2f12575647cbfb017d755650a142cc /examples/data/scripts/uzbl-tabbed | |
parent | 72ac64e75fc3346187b80c61341c20f5d1ae06b8 (diff) | |
parent | 9b2c83f47d064b7651864f15da6a5e3528a37433 (diff) |
Merge remote branch 'origin/master'
Diffstat (limited to 'examples/data/scripts/uzbl-tabbed')
-rwxr-xr-x | examples/data/scripts/uzbl-tabbed | 154 |
1 files changed, 55 insertions, 99 deletions
diff --git a/examples/data/scripts/uzbl-tabbed b/examples/data/scripts/uzbl-tabbed index f07bae4..1597dd3 100755 --- a/examples/data/scripts/uzbl-tabbed +++ b/examples/data/scripts/uzbl-tabbed @@ -54,9 +54,6 @@ # pango - python bindings needed for text rendering & layout in gtk widgets. # pygobject - GLib's GObject bindings for python. # -# Optional dependencies: -# simplejson - save uzbl_tabbed.py sessions & presets in json. -# # Note: I haven't included version numbers with this dependency list because # I've only ever tested uzbl_tabbed.py on the latest stable versions of these # packages in Gentoo's portage. Package names may vary on different systems. @@ -161,8 +158,9 @@ import atexit import types from gobject import io_add_watch, source_remove, timeout_add, IO_IN, IO_HUP -from signal import signal, SIGTERM, SIGINT +from signal import signal, SIGTERM, SIGINT, SIGCHLD from optparse import OptionParser, OptionGroup +from traceback import print_exc pygtk.require('2.0') @@ -213,7 +211,6 @@ config = { # Session options 'save_session': True, # Save session in file when quit - 'json_session': False, # Use json to save session. 'saved_sessions_dir': os.path.join(DATA_DIR, 'sessions/'), 'session_file': os.path.join(DATA_DIR, 'session'), @@ -371,9 +368,8 @@ class SocketClient: class UzblInstance: '''Uzbl instance meta-data/meta-action object.''' - def __init__(self, parent, tab, name, uri, title, switch, process): + def __init__(self, parent, tab, name, uri, title, switch): - self.process = process self.parent = parent self.tab = tab self.name = name @@ -455,10 +451,11 @@ class UzblInstance: if type == "EVENT": type, args = args.split(" ", 1) if type == "TITLE_CHANGED": - self.title = args + self.title = args.strip() self.title_changed() elif type == "VARIABLE_SET": var, _, val = args.split(" ", 2) + try: val = int(val) except: @@ -485,7 +482,7 @@ class UzblInstance: config[var] = val if var == "uri": - self.uri = var + self.uri = val.strip() self.parent.update_tablist() elif type == "NEW_TAB": self.parent.new_tab(args) @@ -529,18 +526,6 @@ class UzblInstance: self._client.close() self._client = None - pid = self.process.pid - timeout = time.time() + 5 - - while self.process.poll() is None and time.time() < timeout: - # Sleep between polls. - time.sleep(0.1) - - if self.process.poll() is None: - # uzbl instance didn't exit in time. - error("quit timeout expired, sending SIGTERM to uzbl instance") - self.process.terminate() - class UzblTabbed: '''A tabbed version of uzbl using gtk.Notebook''' @@ -551,6 +536,7 @@ class UzblTabbed: self._timers = {} self._buffer = "" self._killed = False + self._processes = [] # A list of the recently closed tabs self._closed = [] @@ -571,6 +557,7 @@ class UzblTabbed: self.window.set_default_size(*window_size) except: + print_exc() error("Invalid value for default_size in config file.") self.window.set_title("Uzbl Browser") @@ -668,10 +655,14 @@ class UzblTabbed: # Catch keyboard interrupts signal(SIGINT, lambda signum, stack_frame: self.terminate(SIGINT)) + # Catch SIGCHLD + signal(SIGCHLD, lambda signum, stack_frame: self.join_children()) + try: gtk.main() except: + print_exc() error("encounted error %r" % sys.exc_info()[1]) # Unlink fifo socket @@ -687,6 +678,14 @@ class UzblTabbed: raise + def join_children(self): + '''Find and remove zombie children processes.''' + + for p in self._processes: + if p.poll() is not None: + self._processes.remove(p) + + def terminate(self, termsig=None): '''Handle termination signals and exit safely and cleanly.''' @@ -834,6 +833,7 @@ class UzblTabbed: self.parse_command(cmd) except: + print_exc() error("parse_command: invalid command %s" % ' '.join(cmd)) raise @@ -1007,9 +1007,9 @@ class UzblTabbed: cmd = ['uzbl-browser', '-n', name, '-s', str(sid), '--connect-socket', self.socket_path, '--uri', uri] - process = subprocess.Popen(cmd) # TODO: do i need close_fds=True ? + self._processes += [subprocess.Popen(cmd)] # TODO: do i need close_fds=True ? - uzbl = UzblInstance(self, tab, name, uri, title, switch, process) + uzbl = UzblInstance(self, tab, name, uri, title, switch) SocketClient.instances_queue[name] = uzbl self.tabs[tab] = uzbl @@ -1237,48 +1237,35 @@ class UzblTabbed: def save_session(self, session_file=None): '''Save the current session to file for restoration on next load.''' - strip = str.strip - if session_file is None: session_file = config['session_file'] tabs = self.tabs.keys() - state = [] + lines = "curtab = %d\n" % self.notebook.get_current_page() for tab in list(self.notebook): - if tab not in tabs: continue - uzbl = self.tabs[tab] - if not uzbl.uri: continue - state += [(uzbl.uri, uzbl.title),] - - session = {'curtab': self.notebook.get_current_page(), - 'tabs': state} - - if config['json_session']: - raw = json.dumps(session) + if tab not in tabs: + continue - else: - lines = ["curtab = %d" % session['curtab'],] - for (uri, title) in session['tabs']: - lines += ["%s\t%s" % (strip(uri), strip(title)),] + uzbl = self.tabs[tab] + if not uzbl.uri: + continue - raw = "\n".join(lines) + lines += "%s %s\n" % (uzbl.uri, uzbl.title) if not os.path.isfile(session_file): dirname = os.path.dirname(session_file) if not os.path.isdir(dirname): os.makedirs(dirname) - h = open(session_file, 'w') - h.write(raw) - h.close() + fh = open(session_file, 'w') + fh.write(lines) + fh.close() def load_session(self, session_file=None): '''Load a saved session from file.''' default_path = False - strip = str.strip - json_session = config['json_session'] delete_loaded = False if session_file is None: @@ -1289,50 +1276,34 @@ class UzblTabbed: if not os.path.isfile(session_file): return False - h = open(session_file, 'r') - raw = h.read() - h.close() - if json_session: - if sum([1 for s in raw.split("\n") if strip(s)]) != 1: - error("Warning: The session file %r does not look json. "\ - "Trying to load it as a non-json session file."\ - % session_file) - json_session = False - - if json_session: - try: - session = json.loads(raw) - curtab, tabs = session['curtab'], session['tabs'] + fh = open(session_file, 'r') + raw = fh.read() + fh.close() - except: - error("Failed to load jsonifed session from %r"\ - % session_file) - return None + tabs = [] + curtab = 0 - else: - tabs = [] - strip = str.strip - curtab, tabs = 0, [] - lines = [s for s in raw.split("\n") if strip(s)] - if len(lines) < 2: - error("Warning: The non-json session file %r looks invalid."\ - % session_file) - return None + lines = filter(None, map(str.strip, raw.split('\n'))) + if len(lines) < 2: + error("Error: The session file %r looks invalid." % session_file) + if delete_loaded and os.path.exists(session_file): + os.remove(session_file) - try: - for line in lines: - if line.startswith("curtab"): - curtab = int(line.split()[-1]) + return None - else: - uri, title = line.split("\t",1) - tabs += [(strip(uri), strip(title)),] + try: + for line in lines: + if line.startswith("curtab"): + curtab = int(line.split()[-1]) - except: - error("Warning: failed to load session file %r" % session_file) - return None + else: + uri, title = map(str.strip, line.split(" ", 1)) + tabs += [(uri, title),] - session = {'curtab': curtab, 'tabs': tabs} + except: + print_exc() + error("Warning: failed to load session file %r" % session_file) + return None # Now populate notebook with the loaded session. for (index, (uri, title)) in enumerate(tabs): @@ -1342,11 +1313,6 @@ class UzblTabbed: if delete_loaded and os.path.exists(session_file): os.remove(session_file) - # There may be other state information in the session dict of use to - # other functions. Of course however the non-json session object is - # just a dummy object of no use to no one. - return session - def quitrequest(self, *args): '''Attempt to close all uzbl instances nicely and exit.''' @@ -1412,16 +1378,6 @@ if __name__ == "__main__": if options.verbose: config['verbose'] = True - if config['json_session']: - try: - import simplejson as json - - except: - error("Warning: json_session set but cannot import the python "\ - "module simplejson. Fix: \"set json_session = 0\" or "\ - "install the simplejson python module to remove this warning.") - config['json_session'] = False - if config['verbose']: import pprint sys.stderr.write("%s\n" % pprint.pformat(config)) |