aboutsummaryrefslogtreecommitdiffhomepage
path: root/examples/data/scripts/uzbl-tabbed
diff options
context:
space:
mode:
authorGravatar Dieter Plaetinck <dieter@plaetinck.be>2010-03-23 10:34:24 +0100
committerGravatar Dieter Plaetinck <dieter@plaetinck.be>2010-03-23 10:34:24 +0100
commitbfec366b7d36e195ef5c422c55ecbc4093deb201 (patch)
treea78f53361f2f12575647cbfb017d755650a142cc /examples/data/scripts/uzbl-tabbed
parent72ac64e75fc3346187b80c61341c20f5d1ae06b8 (diff)
parent9b2c83f47d064b7651864f15da6a5e3528a37433 (diff)
Merge remote branch 'origin/master'
Diffstat (limited to 'examples/data/scripts/uzbl-tabbed')
-rwxr-xr-xexamples/data/scripts/uzbl-tabbed154
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))