aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Brendan Taylor <whateley@gmail.com>2011-04-30 08:17:40 -0600
committerGravatar Brendan Taylor <whateley@gmail.com>2011-04-30 08:17:40 -0600
commitceeba25242492db44091a4c87b046a25527d2f59 (patch)
tree5687dda2e9847b28ba48974d5246654eca281311
parentb0d2559157d0b060e2a2c2c33f08bed5f9cfaf51 (diff)
parentcd7ff839afd2af2ec78868d91eca7fd4a2d4f117 (diff)
Merge branch 'experimental' into scrollbars
-rw-r--r--.gitignore4
-rw-r--r--AUTHORS5
-rw-r--r--Makefile23
-rw-r--r--README39
-rwxr-xr-xbin/uzbl-browser (renamed from src/uzbl-browser)2
-rwxr-xr-xbin/uzbl-event-manager (renamed from examples/data/scripts/uzbl-event-manager)0
-rwxr-xr-xbin/uzbl-tabbed (renamed from examples/data/scripts/uzbl-tabbed)618
-rw-r--r--docs/README.uzbl-event-manager27
-rw-r--r--examples/config/config47
-rw-r--r--examples/config/style.css (renamed from examples/data/style.css)15
-rw-r--r--examples/data/plugins/bind.py8
-rw-r--r--examples/data/plugins/history.py2
-rw-r--r--examples/data/plugins/keycmd.py218
-rwxr-xr-xexamples/data/scripts/auth.py2
-rwxr-xr-xexamples/data/scripts/download.sh60
-rw-r--r--examples/data/scripts/follow.js15
-rwxr-xr-xexamples/data/scripts/follow.sh14
-rwxr-xr-xexamples/data/scripts/formfiller.sh12
-rwxr-xr-xexamples/data/scripts/go_input.sh6
-rwxr-xr-xexamples/data/scripts/history.sh6
-rwxr-xr-xexamples/data/scripts/insert_bookmark.sh11
-rwxr-xr-xexamples/data/scripts/insert_temp.sh7
-rwxr-xr-xexamples/data/scripts/instance-select-wmii.sh25
-rwxr-xr-xexamples/data/scripts/load_cookies.sh17
-rwxr-xr-xexamples/data/scripts/load_url_from_bookmarks.sh10
-rwxr-xr-xexamples/data/scripts/load_url_from_history.sh13
-rwxr-xr-xexamples/data/scripts/load_url_from_temps.sh22
-rwxr-xr-xexamples/data/scripts/session.sh28
-rw-r--r--examples/data/scripts/util/dmenu.sh9
-rw-r--r--examples/data/scripts/util/uzbl-dir.sh19
-rw-r--r--examples/data/scripts/util/uzbl-window.sh16
-rwxr-xr-xmisc/cleanprocs-files.sh10
-rwxr-xr-xmisc/env.sh17
-rwxr-xr-xmisc/fifotest.sh20
-rw-r--r--src/callbacks.c19
-rw-r--r--src/events.c91
-rw-r--r--src/events.h8
-rw-r--r--src/uzbl-core.c58
-rw-r--r--src/uzbl-core.h6
39 files changed, 788 insertions, 741 deletions
diff --git a/.gitignore b/.gitignore
index 2ddbb60..8c08dc0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,8 @@
uzbl-core
*.o
+*.lo
*.pyc
+*.sw[a-z]
*~
tags
-uzbl-cookie-manager
+sandbox
diff --git a/AUTHORS b/AUTHORS
index ff31818..b3ce2e2 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -31,6 +31,7 @@ In alphabetical order:
Cedric Staub - Javascript cookies
Chris Mason - code snippets such as basic cookie handler
Chris van Dijk (quigybo) - work on uzbl-tabbed
+ Christer Sjöholm - uzbl-tabbed bugfixes
Ciprian Dorin, Craciun - patches
Daiki Ueno (ueno) - fix for crash when opening image in new window
Damien Leon - misc
@@ -53,6 +54,7 @@ In alphabetical order:
Jason Woofenden (JasonWoof) - geometry=maximized, link following
Jochen Sprickerhof - session.sh enhancements
k0ral - split status bar, cleanup and bugfix patches
+ Klaus T. Aehlig - various patches
Lars-Dominik Braun (PromyLOPh) - added ability to enable/disable the webkit page cache
Laurence Withers (lwithers) - talk_to_socket
Luca Bruno <lucab@debian.org> - bashims fixes
@@ -66,6 +68,7 @@ In alphabetical order:
Moritz Lenz - small doc fix
Nicolas Pouillard - refactored scroll command
Olivier Schwander - auto file:// prepend
+ Olof-Joachim Frahm - bugfixes
Paul Tomak - formfiller.sh script, uzbl vim syntax
Paweł Zuzelski (pawelz) <pawelz@pld-linux.org> - http auth handler, misc patches
Peter Suschlik - backwards searching
@@ -84,7 +87,7 @@ In alphabetical order:
Also, thanks to all people who've posted useful things to the mailing list and/or wiki.
-Originaly based on http://trac.webkit.org/browser/trunk/WebKitTools/GtkLauncher/main.c
+Originally based on http://trac.webkit.org/browser/trunk/WebKitTools/GtkLauncher/main.c
Which is copyrighted:
2006, 2007 Apple Inc
2007 Alp Toker <alp@atoker.com>
diff --git a/Makefile b/Makefile
index 62bc9b5..dad7e61 100644
--- a/Makefile
+++ b/Makefile
@@ -68,13 +68,13 @@ test-uzbl-core: uzbl-core
./uzbl-core --uri http://www.uzbl.org --verbose
test-uzbl-browser: uzbl-browser
- ./src/uzbl-browser --uri http://www.uzbl.org --verbose
+ ./bin/uzbl-browser --uri http://www.uzbl.org --verbose
test-uzbl-core-sandbox: uzbl-core
make DESTDIR=./sandbox RUN_PREFIX=`pwd`/sandbox/usr/local install-uzbl-core
make DESTDIR=./sandbox RUN_PREFIX=`pwd`/sandbox/usr/local install-example-data
cp -np ./misc/env.sh ./sandbox/env.sh
- source ./sandbox/env.sh && uzbl-core --uri http://www.uzbl.org --verbose
+ . ./sandbox/env.sh && uzbl-core --uri http://www.uzbl.org --verbose
make DESTDIR=./sandbox uninstall
rm -rf ./sandbox/usr
@@ -83,20 +83,21 @@ test-uzbl-browser-sandbox: uzbl-browser
make DESTDIR=./sandbox RUN_PREFIX=`pwd`/sandbox/usr/local install-uzbl-browser
make DESTDIR=./sandbox RUN_PREFIX=`pwd`/sandbox/usr/local install-example-data
cp -np ./misc/env.sh ./sandbox/env.sh
- -source ./sandbox/env.sh && uzbl-event-manager restart -avv
- source ./sandbox/env.sh && uzbl-browser --uri http://www.uzbl.org --verbose
- source ./sandbox/env.sh && uzbl-event-manager stop -ivv
+ -. ./sandbox/env.sh && uzbl-event-manager restart -avv
+ . ./sandbox/env.sh && uzbl-browser --uri http://www.uzbl.org --verbose
+ . ./sandbox/env.sh && uzbl-event-manager stop -ivv
make DESTDIR=./sandbox uninstall
rm -rf ./sandbox/usr
test-uzbl-tabbed-sandbox: uzbl-browser
make DESTDIR=./sandbox RUN_PREFIX=`pwd`/sandbox/usr/local install-uzbl-core
make DESTDIR=./sandbox RUN_PREFIX=`pwd`/sandbox/usr/local install-uzbl-browser
+ make DESTDIR=./sandbox RUN_PREFIX=`pwd`/sandbox/usr/local install-uzbl-tabbed
make DESTDIR=./sandbox RUN_PREFIX=`pwd`/sandbox/usr/local install-example-data
cp -np ./misc/env.sh ./sandbox/env.sh
- -source ./sandbox/env.sh && uzbl-event-manager restart -avv
- source ./sandbox/env.sh && ./sandbox/home/.local/share/uzbl/scripts/uzbl-tabbed
- source ./sandbox/env.sh && uzbl-event-manager stop -ivv
+ -. ./sandbox/env.sh && uzbl-event-manager restart -avv
+ . ./sandbox/env.sh && uzbl-tabbed
+ . ./sandbox/env.sh && uzbl-event-manager stop -ivv
make DESTDIR=./sandbox uninstall
rm -rf ./sandbox/usr
@@ -134,8 +135,8 @@ install-uzbl-core: all install-dirs
install -m755 uzbl-core $(INSTALLDIR)/bin/uzbl-core
install-uzbl-browser: install-dirs
- install -m755 src/uzbl-browser $(INSTALLDIR)/bin/uzbl-browser
- install -m755 examples/data/scripts/uzbl-event-manager $(INSTALLDIR)/bin/uzbl-event-manager
+ install -m755 bin/uzbl-browser $(INSTALLDIR)/bin/uzbl-browser
+ install -m755 bin/uzbl-event-manager $(INSTALLDIR)/bin/uzbl-event-manager
mv $(INSTALLDIR)/bin/uzbl-browser $(INSTALLDIR)/bin/uzbl-browser.bak
sed 's#^PREFIX=.*#PREFIX=$(RUN_PREFIX)#' < $(INSTALLDIR)/bin/uzbl-browser.bak > $(INSTALLDIR)/bin/uzbl-browser
chmod 755 $(INSTALLDIR)/bin/uzbl-browser
@@ -146,7 +147,7 @@ install-uzbl-browser: install-dirs
rm $(INSTALLDIR)/bin/uzbl-event-manager.bak
install-uzbl-tabbed: install-dirs
- install -m755 examples/data/scripts/uzbl-tabbed $(INSTALLDIR)/bin/uzbl-tabbed
+ install -m755 bin/uzbl-tabbed $(INSTALLDIR)/bin/uzbl-tabbed
# you probably only want to do this manually when testing and/or to the sandbox. not meant for distributors
install-example-data:
diff --git a/README b/README
index 3ac9a28..08c6356 100644
--- a/README
+++ b/README
@@ -104,7 +104,7 @@ There are several interfaces to interact with Uzbl:
When `uzbl` forks a new instance (eg "open in new window") it will use the same
command line arguments (eg the same `--config <file>`), except `--uri` and
-`--name`. If you made changes to the configuration at runtime, these are not
+`--named`. If you made changes to the configuration at runtime, these are not
passed on to the child.
#### Uzbl-browser
@@ -257,9 +257,14 @@ The following commands are recognized:
- Show the WebInspector
* `add_cookie <domain> <path> <name> <value> <scheme> <expires>`
- Adds a new cookie to the cookie jar
-* 'delete_cookie <domain> <path> <name> <value> [<scheme> <expires>]`
- - Deletes a matching cookie from the cookie jar. scheme and expire time
- is currently not considered when matching.
+* `delete_cookie <domain> <path> <name> <value> [<scheme> <expires>]`
+ - Deletes a matching cookie from the cookie jar. scheme and expire time
+ is currently not considered when matching.
+* `clear_cookies`
+ - Clears all cookies from the cookie jar
+* `download <uri> [<destination path>]`
+ - Starts a download using the given uri. A destination file path can be given
+ to specify where the download should be written to.
### VARIABLES AND CONSTANTS
@@ -504,9 +509,15 @@ Handler scripts (`download_handler`, `cookie_handler`, `scheme_handler` and
* download handler
- `$1 url`: The URL of the item to be downloaded.
- - `$2 suggested_filename`: A filename suggested by the server or based on the URL.
+ - `$2 suggested_filename`: A filename suggested by the server or based on the
+ URL.
- `$3 content_type`: The mimetype of the file to be downloaded.
- - `$4 total_size`: The size of the file to be downloaded in bytes. This may be inaccurate.
+ - `$4 total_size`: The size of the file to be downloaded in bytes. This may be
+ inaccurate.
+ - `$5 destination_path`: This is only present if the download was started
+ explicitly using the `download` command. If it is present, this is the path
+ that the file should be saved to. A download handler using WebKit's internal
+ downloader can just echo this path and exit when this argument is present.
* cookie handler
@@ -666,10 +677,14 @@ Events have this format:
`uri`.
* `EVENT [uzbl_instance_name] LINK_UNHOVER uri`: The mouse leaves the link
`uri`.
-* `EVENT [uzbl_instance_name] KEY_PRESS key_name`: The key (or mouse button)
+* `EVENT [uzbl_instance_name] KEY_PRESS 'mod_state' key_name`: The key (or mouse button)
`key_name` is pressed.
-* `EVENT [uzbl_instance_name] KEY_RELEASE key_name`: The key (or mouse button)
+* `EVENT [uzbl_instance_name] KEY_RELEASE 'mod_state' key_name`: The key (or mouse button)
`key_name` is released.
+* `EVENT [uzbl_instance_name] MOD_PRESS 'mod_state' mod_name`: A key mapped to
+ `mod_name` is pressed.
+* `EVENT [uzbl_instance_name] MOD_RELEASE 'mod_state' mod_name`: A key mapped to
+ `mod_name` is released.
* `EVENT [uzbl_instance_name] SELECTION_CHANGED selected_text`: When text is
selected in the `uzbl` window.
* `EVENT [uzbl_instance_name] NEW_WINDOW uri`: Request to creation of new `uzbl` window,
@@ -747,10 +762,6 @@ Events/requests which the EM and its plugins listens for
when the `<from>` key or button is pressed.
* `IGNORE_KEY`: Ignore a key pattern, specified by `<glob>`.
- `request IGNORE_KEY <glob>`
-* `MODKEY_ADDITION`: Create a compound modkey from multiple individual keys.
- - `request MODKEY_ADDITION <key1> <key2> <keyn> <result>`: The modkey
- `<result>` is considered pressed when all of `<key1>`, `<key2>`, and
- `<keyn>` are pressed.
* `TOGGLE_MODES`
- `request TOGGLE_MODES <mode1> <mode2> ... <moden>`
* `APPEND_KEYCMD`: Append a string to the current keycmd.
@@ -762,6 +773,8 @@ Events/requests which the EM and its plugins listens for
keycmd.
* `KEYCMD_STRIP_WORD`: Removes the last word from the keycmd, similar to
readline `^W`.
+ - `request KEYCMD_STRIP_WORD <seps>`: The `<seps>` argument is a list of
+ characters that are considered to separate words.
* `KEYCMD_EXEC_CURRENT`: (tries to) execute whatever is in the keycmd.
* `SET_KEYCMD`: Allow setting of the keycmd externally.
- `request SET_KEYCMD <string>`: Set the keycmd to `<string>`.
@@ -791,7 +804,7 @@ where `arguments` and `uri` are both optional. `arguments` can be:
* `-u`, `--uri=URI`: URI to load at startup. Equivalent to `uzbl <uri>` or `set
uri = URI` after `uzbl` has launched.
* `-v`, `--verbose`: Whether to print all messages or just errors.
-* `-n`, `--name=NAME`: Name of the current instance (defaults to Xorg window
+* `-n`, `--named=NAME`: Name of the current instance (defaults to Xorg window
id or random for GtkSocket mode).
* `-c`, `--config=FILE`: Path to config file or `-` for stdin.
* `-s`, `--socket=SOCKET`: Xembed socket ID.
diff --git a/src/uzbl-browser b/bin/uzbl-browser
index 81645ca..fb9a368 100755
--- a/src/uzbl-browser
+++ b/bin/uzbl-browser
@@ -42,7 +42,7 @@ then
echo "Error: Global config not found; please check if your distribution ships them separately"
exit 3
fi
- if ! cp "$EXAMPLES"/config/config "$XDG_CONFIG_HOME"/uzbl/config
+ if ! cp "$EXAMPLES"/config/* "$XDG_CONFIG_HOME"/uzbl/
then
echo "Could not copy default config to $XDG_CONFIG_HOME/uzbl/config" >&2
# Run with the global config as a last resort
diff --git a/examples/data/scripts/uzbl-event-manager b/bin/uzbl-event-manager
index cb462c7..cb462c7 100755
--- a/examples/data/scripts/uzbl-event-manager
+++ b/bin/uzbl-event-manager
diff --git a/examples/data/scripts/uzbl-tabbed b/bin/uzbl-tabbed
index de71c2c..1a65788 100755
--- a/examples/data/scripts/uzbl-tabbed
+++ b/bin/uzbl-tabbed
@@ -72,7 +72,6 @@
# gtk_tab_pos = (top|left|bottom|right)
# gtk_refresh = 1000
# switch_to_new_tabs = 1
-# capture_new_windows = 1
# multiline_tabs = 1
#
# Tab title options:
@@ -88,8 +87,6 @@
# session_file = $HOME/.local/share/uzbl/session
#
# Inherited uzbl options:
-# fifo_dir = /tmp
-# socket_dir = /tmp
# icon_path = $HOME/.local/share/uzbl/uzbl.png
# status_background = #303030
#
@@ -199,7 +196,6 @@ config = {
'gtk_tab_pos': 'top', # Gtk tab position (top|left|bottom|right)
'gtk_refresh': 1000, # Tablist refresh millisecond interval
'switch_to_new_tabs': True, # Upon opening a new tab switch to it
- 'capture_new_windows': True, # Use uzbl_tabbed to catch new windows
'multiline_tabs': True, # Tabs overflow onto new tablist lines.
# Tab title options
@@ -215,8 +211,6 @@ config = {
'session_file': os.path.join(DATA_DIR, 'session'),
# Inherited uzbl options
- 'fifo_dir': '/tmp', # Path to look for uzbl fifo.
- 'socket_dir': '/tmp', # Path to look for uzbl socket.
'icon_path': os.path.join(DATA_DIR, 'uzbl.png'),
'status_background': "#303030", # Default background for all panels.
@@ -297,19 +291,21 @@ def escape(s):
s = s.replace(split, glue)
return s
-
class SocketClient:
- '''Represents a Uzbl instance, which is not necessarly linked with a UzblInstance'''
+ '''Represents a connection to the uzbl-tabbed socket.'''
# List of UzblInstance objects not already linked with a SocketClient
instances_queue = {}
- def __init__(self, socket):
+ def __init__(self, socket, uzbl_tabbed):
self._buffer = ""
self._socket = socket
self._watchers = [io_add_watch(socket, IO_IN, self._socket_recv),\
io_add_watch(socket, IO_HUP, self._socket_closed)]
+
self.uzbl = None
+ self.uzbl_tabbed = uzbl_tabbed
+ self.dispatcher = GlobalEventDispatcher(uzbl_tabbed)
def _socket_recv(self, fd, condition):
@@ -329,26 +325,44 @@ class SocketClient:
'''An Uzbl instance sent some data, parse it'''
self._buffer += data
- if self.uzbl:
- if "\n" in self._buffer:
- cmds = self._buffer.split("\n")
- if cmds[-1]: # Last command has been received incomplete, don't process it
- self._buffer, cmds = cmds[-1], cmds[:-1]
- else:
- self._buffer = ""
+ if "\n" in self._buffer:
+ cmds = self._buffer.split("\n")
- for cmd in cmds:
- if cmd:
- self.uzbl.parse_command(cmd)
- else:
- name = re.findall('^EVENT \[(\d+-\d+)\] INSTANCE_START \d+$', self._buffer, re.M)
- uzbl = self.instances_queue.get(name[0])
+ if cmds[-1]: # Last command has been received incomplete, don't process it
+ self._buffer, cmds = cmds[-1], cmds[:-1]
+ else:
+ self._buffer = ""
+
+ for cmd in cmds:
+ if cmd:
+ self.handle_event(cmd)
+
+ def handle_event(self, cmd):
+ cmd = parse_event(cmd)
+ message, instance_name, message_type = cmd[0:3]
+ args = cmd[3:]
+
+ if not message == "EVENT":
+ return
+
+ # strip the surrounding []
+ instance_name = instance_name[1:-1]
+
+ if self.uzbl:
+ if not self.dispatcher.dispatch(message_type, args):
+ self.uzbl.dispatcher.dispatch(message_type, args)
+ elif message_type == 'INSTANCE_START':
+ uzbl = self.instances_queue.get(instance_name)
if uzbl:
- del self.instances_queue[name[0]]
- self.uzbl = uzbl
- self.uzbl.got_socket(self)
- self._feed("")
+ # we've found the uzbl we were waiting for
+ del self.instances_queue[instance_name]
+ else:
+ # an unsolicited uzbl has connected, how exciting!
+ uzbl = UzblInstance(self.uzbl_tabbed, None, '', '', False)
+ self.uzbl = uzbl
+ self.uzbl.got_socket(self)
+ self._feed("")
def send(self, data):
'''Child socket send function.'''
@@ -365,21 +379,146 @@ class SocketClient:
self._watchers = []
+def unquote(s):
+ '''Removes quotation marks around strings if any and interprets
+ \\-escape sequences using `string_escape`'''
+ if s and s[0] == s[-1] and s[0] in ['"', "'"]:
+ s = s[1:-1]
+ return s.encode('utf-8').decode('string_escape').decode('utf-8')
+
+_splitquoted = re.compile("( |\"(?:\\\\.|[^\"])*?\"|'(?:\\\\.|[^'])*?')")
+def parse_event(text):
+ '''Splits string on whitespace while respecting quotations'''
+ return [unquote(p) for p in _splitquoted.split(text) if p.strip()]
+
+class EventDispatcher:
+ def dispatch(self, message_type, args):
+ '''Returns True if the message was handled, False otherwise.'''
+
+ method = getattr(self, message_type.lower(), None)
+
+ if method is None:
+ return False
+
+ method(*args)
+ return True
+
+class GlobalEventDispatcher(EventDispatcher):
+ def __init__(self, uzbl_tabbed):
+ self.uzbl_tabbed = uzbl_tabbed
+
+ def new_tab(self, uri = ''):
+ self.uzbl_tabbed.new_tab(uri)
+
+ def new_tab_bg(self, uri = ''):
+ self.uzbl_tabbed.new_tab(uri, switch = False)
+
+ def new_tab_next(self, uri = ''):
+ self.uzbl_tabbed.new_tab(uri, next=True)
+
+ def new_bg_tab_next(self, uri = ''):
+ self.uzbl_tabbed.new_tab(uri, switch = False, next = True)
+
+ def next_tab(self, step = 1):
+ self.uzbl_tabbed.next_tab(int(step))
+
+ def prev_tab(self, step = 1):
+ self.uzbl_tabbed.prev_tab(int(step))
+
+ def goto_tab(self, index):
+ self.uzbl_tabbed.goto_tab(int(index))
+
+ def first_tab(self):
+ self.uzbl_tabbed.goto_tab(0)
+
+ def last_tab(self):
+ self.uzbl_tabbed.goto_tab(-1)
+
+ def preset_tabs(self, *args):
+ self.uzbl_tabbed.run_preset_command(*args)
+
+ def bring_to_front(self):
+ self.uzbl_tabbed.window.present()
+
+ def clean_tabs(self):
+ self.uzbl_tabbed.clean_slate()
+
+ def exit_all_tabs(self):
+ self.uzbl_tabbed.quitrequest()
+
+class InstanceEventDispatcher(EventDispatcher):
+ def __init__(self, uzbl):
+ self.uzbl = uzbl
+ self.parent = self.uzbl.parent
+
+ def plug_created(self, plug_id):
+ if not self.uzbl.tab:
+ tab = self.parent.create_tab()
+ tab.add_id(int(plug_id))
+ self.uzbl.set_tab(tab)
+
+ def title_changed(self, title):
+ self.uzbl.title = title.strip()
+ self.uzbl.title_changed(False)
+
+ def variable_set(self, var, _type, val):
+ try:
+ val = int(val)
+ except:
+ pass
+
+ if var in UZBL_TABBED_VARS:
+ if config[var] != val:
+ config[var] = val
+ if var == "show_gtk_tabs":
+ self.parent.notebook.set_show_tabs(bool(val))
+ elif var == "show_tablist" or var == "tablist_top":
+ self.parent.update_tablist_display()
+ elif var == "gtk_tab_pos":
+ self.parent.update_gtk_tab_pos()
+ elif var == "status_background":
+ if config['status_background'].strip():
+ try:
+ col = gtk.gdk.color_parse(config['status_background'])
+ self.parent.ebox.modify_bg(gtk.STATE_NORMAL, col)
+ except ValueError:
+ pass # got an invalid colour, just ignore it
+ elif var == "tab_titles" or var == "tab_indexes":
+ for tab in self.parent.notebook:
+ self.parent.tabs[tab].title_changed(True)
+
+ self.parent.update_tablist()
+ else:
+ config[var] = val
+
+ if var == "uri":
+ self.uzbl.uri = val.strip()
+ self.parent.update_tablist()
+
+ def load_commit(self, uri):
+ self.uzbl.uri = uri
+
class UzblInstance:
'''Uzbl instance meta-data/meta-action object.'''
- def __init__(self, parent, tab, name, uri, title, switch):
+ def __init__(self, parent, name, uri, title, switch):
self.parent = parent
- self.tab = tab
+ self.tab = None
+ self.dispatcher = InstanceEventDispatcher(self)
+
self.name = name
self.title = title
self.tabtitle = ""
self.uri = uri
+
self._client = None
self._switch = switch # Switch to tab after loading ?
- self.title_changed()
+ def set_tab(self, tab):
+ self.tab = tab
+ self.title_changed()
+ self.parent.tabs[self.tab] = self
def got_socket(self, client):
'''Uzbl instance is now connected'''
@@ -394,6 +533,9 @@ class UzblInstance:
def title_changed(self, gtk_only = True): # GTK-only is for indexes
'''self.title has changed, update the tabs list'''
+ if not self.tab:
+ return
+
tab_titles = config['tab_titles']
tab_indexes = config['tab_indexes']
show_ellipsis = config['show_ellipsis']
@@ -434,7 +576,8 @@ class UzblInstance:
''' Send the SET command to Uzbl '''
if self._client:
- self._client.send('set %s = %s') #TODO: escape chars ?
+ line = 'set %s = %s' % (key, val) #TODO: escape chars ?
+ self._client.send(line)
def exit(self):
@@ -443,88 +586,6 @@ class UzblInstance:
if self._client:
self._client.send('exit')
-
- def parse_command(self, cmd):
- ''' Parse event givent by the Uzbl instance '''
-
- type, _, args = cmd.split(" ", 2)
- if type == "EVENT":
- type, args = args.split(" ", 1)
- if type == "TITLE_CHANGED":
- self.title = args.strip()
- self.title_changed(False)
- elif type == "VARIABLE_SET":
- var, _, val = args.split(" ", 2)
-
- try:
- val = int(val)
- except:
- pass
-
- if var in UZBL_TABBED_VARS:
- if config[var] != val:
- config[var] = val
- if var == "show_gtk_tabs":
- self.parent.notebook.set_show_tabs(bool(val))
- elif var == "show_tablist" or var == "tablist_top":
- self.parent.update_tablist_display()
- elif var == "gtk_tab_pos":
- self.parent.update_gtk_tab_pos()
- elif var == "status_background":
- if config['status_background'].strip():
- try:
- col = gtk.gdk.color_parse(config['status_background'])
- self.parent.ebox.modify_bg(gtk.STATE_NORMAL, col)
- except ValueError:
- pass # got an invalid colour, just ignore it
- elif var == "tab_titles" or var == "tab_indexes":
- for tab in self.parent.notebook:
- self.parent.tabs[tab].title_changed(True)
-
- self.parent.update_tablist()
- else:
- config[var] = val
-
- if var == "uri":
- self.uri = val.strip()
- self.parent.update_tablist()
- elif type == "LOAD_COMMIT":
- self.uri = args
- elif type == "NEW_TAB":
- self.parent.new_tab(args)
- elif type == "NEW_BG_TAB":
- self.parent.new_tab(args, '', 0)
- elif type == "NEW_TAB_NEXT":
- self.parent.new_tab(args, next=True)
- elif type == "NEW_BG_TAB_NEXT":
- self.parent.new_tab(args, '', 0, next=True)
-
- elif type == "NEXT_TAB":
- if args:
- self.parent.next_tab(int(args))
- else:
- self.parent.next_tab()
- elif type == "PREV_TAB":
- if args:
- self.parent.prev_tab(int(args))
- else:
- self.parent.prev_tab()
- elif type == "GOTO_TAB":
- self.parent.goto_tab(int(args))
- elif type == "FIRST_TAB":
- self.parent.goto_tab(0)
- elif type == "LAST_TAB":
- self.parent.goto_tab(-1)
- elif type == "PRESET_TABS":
- self.parent.parse_command(["preset"] + args.split())
- elif type == "BRING_TO_FRONT":
- self.parent.window.present()
- elif type == "CLEAN_TABS":
- self.parent.clean_slate()
- elif type == "EXIT_ALL_TABS":
- self.parent.quitrequest()
-
-
def close(self):
'''The remote instance exited'''
@@ -555,6 +616,13 @@ class UzblTabbed:
# Generates a unique id for uzbl socket filenames.
self.next_pid = counter().next
+ # Whether to reconfigure new uzbl instances
+ self.force_socket_dir = False
+ self.force_fifo_dir = False
+
+ self.fifo_dir = '/tmp' # Path to look for uzbl fifo.
+ self.socket_dir = '/tmp' # Path to look for uzbl socket.
+
# Create main window
self.window = gtk.Window()
try:
@@ -568,6 +636,11 @@ class UzblTabbed:
self.window.set_title("Uzbl Browser")
self.window.set_border_width(0)
+ # this prevents the window from expanding if the contents of the
+ # statusbar are wider than the window.
+ # i suspect this is not the right way to do this.
+ self.window.set_geometry_hints(min_width=1)
+
# Set main window icon
icon_path = config['icon_path']
if os.path.exists(icon_path):
@@ -628,16 +701,12 @@ class UzblTabbed:
self.window.show()
self.wid = self.notebook.window.xid
- # Store information about the applications fifo and socket.
- fifo_filename = 'uzbltabbed_%d.fifo' % os.getpid()
+ # Store information about the application's socket.
socket_filename = 'uzbltabbed_%d.socket' % os.getpid()
- self._fifo = None
self._socket = None
- self.fifo_path = os.path.join(config['fifo_dir'], fifo_filename)
- self.socket_path = os.path.join(config['socket_dir'], socket_filename)
+ self.socket_path = os.path.join(self.socket_dir, socket_filename)
- # Now initialise the fifo and the socket
- self.init_fifo()
+ # Now initialise the the socket
self.init_socket()
# If we are using sessions then load the last one if it exists.
@@ -668,8 +737,7 @@ class UzblTabbed:
print_exc()
error("encounted error %r" % sys.exc_info()[1])
- # Unlink fifo socket
- self.unlink_fifo()
+ # Unlink socket
self.close_socket()
# Attempt to close all uzbl instances nicely.
@@ -707,7 +775,7 @@ class UzblTabbed:
'''A new uzbl instance was created'''
client, _ = sock.accept()
- self.clients[client] = SocketClient(client)
+ self.clients[client] = SocketClient(client, self)
return True
@@ -735,247 +803,45 @@ class UzblTabbed:
self._socket = None
- def init_fifo(self):
- '''Create interprocess communication fifo.'''
-
- if os.path.exists(self.fifo_path):
- if not os.access(self.fifo_path, os.F_OK | os.R_OK | os.W_OK):
- os.mkfifo(self.fifo_path)
-
- else:
- basedir = os.path.dirname(self.fifo_path)
- if not os.path.exists(basedir):
- os.makedirs(basedir)
-
- os.mkfifo(self.fifo_path)
-
- # Add event handlers for IO_IN & IO_HUP events.
- self.setup_fifo_watchers()
-
- echo("[fifo] listening at %r" % self.fifo_path)
-
- # Add atexit register to destroy the fifo on program termination.
- atexit.register(self.unlink_fifo)
-
+ def run_preset_command(self, cmd, *args):
+ if len(args) < 1:
+ error("parse_command: invalid preset command")
- def unlink_fifo(self):
- '''Unlink the fifo socket. Note: This function is called automatically
- on exit by an atexit register.'''
+ elif cmd == "save":
+ path = os.path.join(config['saved_sessions_dir'], args[0])
+ self.save_session(path)
- # Make sure the fifo fd is closed.
- self.close_fifo()
-
- # And unlink if the real fifo exists.
- if os.path.exists(self.fifo_path):
- os.unlink(self.fifo_path)
- echo("unlinked %r" % self.fifo_path)
-
-
- def close_fifo(self):
- '''Remove all event handlers watching the fifo and close the fd.'''
-
- # Already closed
- if self._fifo is None: return
-
- (fd, watchers) = self._fifo
- os.close(fd)
-
- # Stop all gobject io watchers watching the fifo.
- for gid in watchers:
- source_remove(gid)
-
- self._fifo = None
-
-
- def setup_fifo_watchers(self):
- '''Open fifo socket fd and setup gobject IO_IN & IO_HUP event
- handlers.'''
-
- # Close currently open fifo fd and kill all watchers
- self.close_fifo()
-
- fd = os.open(self.fifo_path, os.O_RDONLY | os.O_NONBLOCK)
-
- # Add gobject io event handlers to the fifo socket.
- watchers = [io_add_watch(fd, IO_IN, self.main_fifo_read),\
- io_add_watch(fd, IO_HUP, self.main_fifo_hangup)]
-
- self._fifo = (fd, watchers)
-
-
- def main_fifo_hangup(self, fd, cb_condition):
- '''Handle main fifo socket hangups.'''
-
- # Close old fd, open new fifo socket and add io event handlers.
- self.setup_fifo_watchers()
-
- # Kill the gobject event handler calling this handler function.
- return False
-
-
- def main_fifo_read(self, fd, cb_condition):
- '''Read from main fifo socket.'''
-
- self._buffer = os.read(fd, 1024)
- temp = self._buffer.split("\n")
- self._buffer = temp.pop()
- cmds = [s.strip().split() for s in temp if len(s.strip())]
-
- for cmd in cmds:
- try:
- #print cmd
- self.parse_command(cmd)
-
- except:
- print_exc()
- error("parse_command: invalid command %s" % ' '.join(cmd))
- raise
-
- return True
-
-
- def parse_command(self, cmd):
- '''Parse instructions from uzbl child processes.'''
-
- # Commands ( [] = optional, {} = required )
- # new [uri]
- # open new tab and head to optional uri.
- # newbg [uri]
- # open a new tab in the background
- # close [tab-num]
- # close current tab or close via tab id.
- # next [n-tabs]
- # open next tab or n tabs down. Supports negative indexing.
- # prev [n-tabs]
- # open prev tab or n tabs down. Supports negative indexing.
- # goto {tab-n}
- # goto tab n.
- # first
- # goto first tab.
- # last
- # goto last tab.
- # title {pid} {document-title}
- # updates tablist title.
- # uri {pid} {document-location}
- # updates tablist uri
- # bring_to_front
- # brings the gtk window to focus.
- # exit
- # exits uzbl_tabbed.py
-
- if cmd[0] == "new":
- if len(cmd) == 2:
- self.new_tab(cmd[1])
-
- else:
- self.new_tab()
-
- elif cmd[0] == "newbg":
- if len(cmd) == 2:
- self.new_tab(cmd[1], switch=False)
- else:
- self.new_tab(switch=False)
-
- elif cmd[0] == "newfromclip":
- uri = subprocess.Popen(['xclip','-selection','clipboard','-o'],\
- stdout=subprocess.PIPE).communicate()[0]
- if uri:
- self.new_tab(uri)
-
- elif cmd[0] == "close":
- if len(cmd) == 2:
- self.close_tab(int(cmd[1]))
-
- else:
- self.close_tab()
-
- elif cmd[0] == "next":
- if len(cmd) == 2:
- self.next_tab(int(cmd[1]))
-
- else:
- self.next_tab()
-
- elif cmd[0] == "prev":
- if len(cmd) == 2:
- self.prev_tab(int(cmd[1]))
+ elif cmd == "load":
+ path = os.path.join(config['saved_sessions_dir'], args[0])
+ self.load_session(path)
+ elif cmd == "del":
+ path = os.path.join(config['saved_sessions_dir'], args[0])
+ if os.path.isfile(path):
+ os.remove(path)
else:
- self.prev_tab()
-
- elif cmd[0] == "goto":
- self.goto_tab(int(cmd[1]))
-
- elif cmd[0] == "first":
- self.goto_tab(0)
-
- elif cmd[0] == "last":
- self.goto_tab(-1)
-
- elif cmd[0] in ["title", "uri"]:
- if len(cmd) > 2:
- uzbl = self.get_tab_by_name(int(cmd[1]))
- if uzbl:
- old = getattr(uzbl, cmd[0])
- new = ' '.join(cmd[2:])
- setattr(uzbl, cmd[0], new)
- if old != new:
- self.update_tablist()
-
- else:
- error("parse_command: no uzbl with name %r" % int(cmd[1]))
-
- elif cmd[0] == "preset":
- if len(cmd) < 3:
- error("parse_command: invalid preset command")
-
- elif cmd[1] == "save":
- path = os.path.join(config['saved_sessions_dir'], cmd[2])
- self.save_session(path)
-
- elif cmd[1] == "load":
- path = os.path.join(config['saved_sessions_dir'], cmd[2])
- self.load_session(path)
-
- elif cmd[1] == "del":
- path = os.path.join(config['saved_sessions_dir'], cmd[2])
- if os.path.isfile(path):
- os.remove(path)
-
- else:
- error("parse_command: preset %r does not exist." % path)
-
- elif cmd[1] == "list":
- uzbl = self.get_tab_by_name(int(cmd[2]))
- if uzbl:
- if not os.path.isdir(config['saved_sessions_dir']):
- js = "js alert('No saved presets.');"
- uzbl._client.send(js)
+ error("parse_command: preset %r does not exist." % path)
- else:
- listdir = os.listdir(config['saved_sessions_dir'])
- listdir = "\\n".join(listdir)
- js = "js alert('Session presets:\\n\\n%s');" % listdir
- uzbl._client.send(js)
+ elif cmd == "list":
+ # FIXME: what argument is this supposed to be passed,
+ # and why?
+ uzbl = self.get_tab_by_name(int(args[0]))
+ if uzbl:
+ if not os.path.isdir(config['saved_sessions_dir']):
+ js = "js alert('No saved presets.');"
+ uzbl._client.send(js)
else:
- error("parse_command: unknown tab name.")
+ listdir = os.listdir(config['saved_sessions_dir'])
+ listdir = "\\n".join(listdir)
+ js = "js alert('Session presets:\\n\\n%s');" % listdir
+ uzbl._client.send(js)
else:
- error("parse_command: unknown parse command %r"\
- % ' '.join(cmd))
-
- elif cmd[0] == "bring_to_front":
- self.window.present()
-
- elif cmd[0] == "clean":
- self.clean_slate()
-
- elif cmd[0] == "exit":
- self.quitrequest()
+ error("parse_command: unknown tab name.")
else:
- error("parse_command: unknown command %r" % ' '.join(cmd))
+ error("parse_command: unknown parse command %r" % cmd)
def get_tab_by_name(self, name):
@@ -987,6 +853,18 @@ class UzblTabbed:
return False
+ def create_tab(self, beside = False):
+ tab = gtk.Socket()
+ tab.show()
+
+ if beside:
+ pos = self.notebook.get_current_page() + 1
+ self.notebook.insert_page(tab, position=pos)
+ else:
+ self.notebook.append_page(tab)
+
+ self.notebook.set_tab_reorderable(tab, True)
+ return tab
def new_tab(self, uri='', title='', switch=None, next=False):
'''Add a new tab to the notebook and start a new instance of uzbl.
@@ -994,10 +872,7 @@ class UzblTabbed:
when you need to load multiple tabs at a time (I.e. like when
restoring a session from a file).'''
- tab = gtk.Socket()
- tab.show()
- self.notebook.insert_page(tab, position=next and self.notebook.get_current_page() + 1 or -1)
- self.notebook.set_tab_reorderable(tab, True)
+ tab = self.create_tab(next)
sid = tab.get_id()
uri = uri.strip()
name = "%d-%d" % (os.getpid(), self.next_pid())
@@ -1009,12 +884,13 @@ class UzblTabbed:
title = config['new_tab_title']
cmd = ['uzbl-browser', '-n', name, '-s', str(sid),
- '--connect-socket', self.socket_path, '--uri', uri]
+ '--connect-socket', self.socket_path, '--uri', str(uri)]
gobject.spawn_async(cmd, flags=gobject.SPAWN_SEARCH_PATH)
- uzbl = UzblInstance(self, tab, name, uri, title, switch)
+ uzbl = UzblInstance(self, name, uri, title, switch)
+ uzbl.set_tab(tab)
+
SocketClient.instances_queue[name] = uzbl
- self.tabs[tab] = uzbl
def clean_slate(self):
@@ -1027,16 +903,15 @@ class UzblTabbed:
uzbl = self.tabs[tab]
uzbl.exit()
-
def config_uzbl(self, uzbl):
'''Send bind commands for tab new/close/next/prev to a uzbl
instance.'''
- # Set definitions here
- # set(key, command back to fifo)
- if config['capture_new_windows']:
- uzbl.set("new_window", r'new $8')
+ if self.force_socket_dir:
+ uzbl.set("socket_dir", self.socket_dir)
+ if self.force_fifo_dir:
+ uzbl.set("fifo_dir", self.fifo_dir)
def goto_tab(self, index):
'''Goto tab n (supports negative indexing).'''
@@ -1353,9 +1228,8 @@ class UzblTabbed:
def quit(self, *args):
'''Cleanup and quit. Called by delete-event signal.'''
- # Close the fifo socket, remove any gobject io event handlers and
+ # Close the socket, remove any gobject io event handlers and
# delete socket.
- self.unlink_fifo()
self.close_socket()
# Remove all gobject timers that are still ticking.
@@ -1379,6 +1253,10 @@ if __name__ == "__main__":
action='store_true', help="ignore session saving a loading.")
parser.add_option('-v', '--verbose', dest='verbose',
action='store_true', help='print verbose output.')
+ parser.add_option('-s', '--socketdir', dest='socketdir',
+ help="directory to create socket")
+ parser.add_option('-f', '--fifodir', dest='fifodir',
+ help="directory to create fifo")
# Parse command line options
(options, uris) = parser.parse_args()
@@ -1395,6 +1273,14 @@ if __name__ == "__main__":
uzbl = UzblTabbed()
+ if options.socketdir:
+ uzbl.socket_dir = options.socketdir
+ uzbl.force_socket_dir = True
+
+ if options.fifodir:
+ uzbl.fifo_dir = options.fifodir
+ uzbl.force_fifo_dir = True
+
# All extra arguments given to uzbl_tabbed.py are interpreted as
# web-locations to opened in new tabs.
lasturi = len(uris)-1
diff --git a/docs/README.uzbl-event-manager b/docs/README.uzbl-event-manager
index 23e185c..da26847 100644
--- a/docs/README.uzbl-event-manager
+++ b/docs/README.uzbl-event-manager
@@ -26,15 +26,36 @@ MODE_CHANGE <mode>
### keycmd.py ###
- Tracks the currently entered command
-- Connects To: FOCUS_GAINED, FOCUS_LOST, KEY_PRESS, KEY_RELEASE, (APPEND_KEYCMD,
+- Connects To: KEY_PRESS, KEY_RELEASE, MOD_PRESS, MOD_RELEASE, (APPEND_KEYCMD,
IGNORE_KEY, INJECT_KEYCMD, KEYCMD_BACKSPACE, KEYCMD_DELETE,
- KEYCMD_EXEC_CURRENT, KEYCMD_STRIP_WORD, MODKEY_ADDITION, MODMAP,
+ KEYCMD_EXEC_CURRENT, KEYCMD_STRIP_WORD, KEYCMD_CLEAR, MODMAP,
SET_CURSOR_POS, SET_KEYCMD)
-- Emits: KEYCMD_UPDATE, KEYCMD_EXEC, MODCMD_UPDATE, MODCMD_EXEC
+- Emits: KEYCMD_UPDATE, KEYCMD_EXEC, MODCMD_UPDATE, MODCMD_EXEC, KEYCMD_CLEARED
+ MODCMD_CLEARED
Maintains a command line that is manipulated by simple keypresses and a number
of events.
+APPEND_KEYCMD <str>
+ Appends `str` to the end of the keycmd
+
+INJECT_KEYCMD <str>
+ Inserts `str` at the cursor position
+
+KEYCMD_BACKSPACE
+ Removes the character at the cursor position in the keycmd
+
+KEYCMD_DELETE
+ Removes the character after the cursor position in the keycmd
+
+KEYCMD_EXEC_CURRENT
+ Raise a KEYCMD_EXEC with the current keylet and then clear the keycmd
+
+KEYCMD_STRIP_WORD [<separator>]
+ Removes the last word from the keycmd, similar to readline ^W
+
+KEYCMD_CLEAR
+ Clears the keycmd and raises KEYCMD_CLEARED
### bind.py ###
- Provides support for key bindings
diff --git a/examples/config/config b/examples/config/config
index bcd6d3e..8c706df 100644
--- a/examples/config/config
+++ b/examples/config/config
@@ -4,9 +4,10 @@
# === Core settings ==========================================================
# common directory locations
-set prefix = @(echo $PREFIX)@
-set data_home = @(echo $XDG_DATA_HOME)@
-set cache_home = @(echo $XDG_CACHE_HOME)@
+set prefix = @(echo $PREFIX)@
+set data_home = @(echo $XDG_DATA_HOME)@
+set cache_home = @(echo $XDG_CACHE_HOME)@
+set config_home = @(echo $XDG_CONFIG_HOME)@
# Interface paths.
set fifo_dir = /tmp
@@ -90,12 +91,12 @@ set download_handler = sync_spawn @scripts_dir/download.sh
#@on_event CONFIG_CHANGED print Config changed: %1 = %2
# Scroll percentage calculation
-@on_event SCROLL_VERT set scroll_message = \@<(function(){var p='--';if(%3!=%2){p=(%1/(%3-%4));p=Math.round(10000*p)/100;};return p+'%';})()>\@
+@on_event SCROLL_VERT set scroll_message = \@<(function(){var p='--';if(%3<=%4){p=(%1/(%3-%4));p=Math.round(10000*p)/100;};return p+'%';})()>\@
# === Behaviour and appearance ===============================================
# Custom CSS can be defined here, including link follower hint styles
-set stylesheet_uri = file://@data_home/uzbl/style.css
+set stylesheet_uri = file://@config_home/uzbl/style.css
set show_status = 1
set status_top = 0
@@ -153,15 +154,11 @@ set useragent = Uzbl (Webkit @{WEBKIT_MAJOR}.@{WEBKIT_MINOR}) (@(+uname
@modmap <space> <Space>
@modmap <KP_Enter> <Enter>
-#modkey_addition <Key1> <Key2> <Result>
-@modkey_addition <Shift> <Ctrl> <Meta>
-@modkey_addition <Shift> <Tab> <Shift-Tab>
-@modkey_addition <Shift> <Insert> <Shift-Insert>
-
#ignore_key <glob>
@ignore_key <ISO_*>
@ignore_key <Shift>
@ignore_key <Multi_key>
+@ignore_key <Mod2>
# --- Bind aliases -----------------------------------------------------------
@@ -185,6 +182,7 @@ set ebind = @mode_bind global,-insert
# Resets keycmd and returns to default mode.
@on_event ESCAPE @set_mode
@on_event ESCAPE event KEYCMD_CLEAR
+@on_event ESCAPE js uzbl.follow.clearHints()
@bind <Escape> = event ESCAPE
@bind <Ctrl>[ = event ESCAPE
@@ -198,7 +196,7 @@ set ebind = @mode_bind global,-insert
@ebind <Delete> = event KEYCMD_DELETE
@ebind <Tab> = event START_COMPLETION
# Readline-ish bindings.
-@ebind <Ctrl>w = event KEYCMD_STRIP_WORD
+@ebind <Ctrl>w = event KEYCMD_STRIP_WORD \ -./&?=
@ebind <Ctrl>u = event SET_KEYCMD
@ebind <Ctrl>a = event SET_CURSOR_POS 0
@ebind <Ctrl>e = event SET_CURSOR_POS -1
@@ -267,6 +265,9 @@ set ebind = @mode_bind global,-insert
@cbind n = search
@cbind N = search_reverse
+# Print pages to a printer
+@cbind  <Ctrl>p = hardcopy
+
# Web searching binds
@cbind gg<Google:>_ = uri http://www.google.com/search?q=\@<encodeURIComponent(%r)>\@
@cbind ddg<DuckDuckGo:>_ = uri http://duckduckgo.com/?q=%s
@@ -285,8 +286,8 @@ set ebind = @mode_bind global,-insert
# Use socat to directly inject commands into uzbl-core and view events
# raised by uzbl-core:
-@cbind <Ctrl><Alt>t = sh 'xterm -e "socat unix-connect:\"$UZBL_SOCKET\" -"'
-#@cbind <Ctrl><Alt>t = sh 'urxvt -e socat unix-connect:"$UZBL_SOCKET" -'
+@cbind <Ctrl><Mod1>t = sh 'xterm -e "socat unix-connect:\"$UZBL_SOCKET\" -"'
+#@cbind <Ctrl><Mod1>t = sh 'urxvt -e socat unix-connect:"$UZBL_SOCKET" -'
# Uri opening prompts
@cbind o<uri:>_ = uri %s
@@ -300,6 +301,13 @@ set ebind = @mode_bind global,-insert
# Hard-bound bookmarks
@cbind gh = uri http://www.uzbl.org
+# New window binds
+@cbind gw = event REQ_NEW_WINDOW
+
+# SSL-ify bindings
+@cbind zs = uri \@(echo "$UZBL_URI" | sed -e 's/^http:/https:/')\@
+@cbind zS = event REQ_NEW_WINDOW \@(echo "$UZBL_URI" | sed -e 's/^http:/https:/')\@
+
# Yanking & pasting binds
@cbind yu = sh 'echo -n "$UZBL_URI" | xclip'
@cbind yU = sh 'echo -n "$1" | xclip' \@SELECTED_URI
@@ -314,7 +322,7 @@ set ebind = @mode_bind global,-insert
# Start a new uzbl instance from the page in primary selection
@cbind 'p = sh 'echo "event REQ_NEW_WINDOW $(xclip -o)" > "$UZBL_FIFO"'
# paste primary selection into keycmd at the cursor position
-@bind <Shift-Insert> = sh 'echo "event INJECT_KEYCMD $(xclip -o | sed s/\\\@/%40/g)" > "$UZBL_FIFO"'
+@bind <Shift><Insert> = sh 'echo "event INJECT_KEYCMD $(xclip -o | sed s/\\\@/%40/g)" > "$UZBL_FIFO"'
# Bookmark inserting binds
@cbind <Ctrl>b<tags:>_ = sh 'echo `printf "$UZBL_URI %s"` >> "$XDG_DATA_HOME"/uzbl/bookmarks'
@@ -325,6 +333,10 @@ set ebind = @mode_bind global,-insert
@cbind U = spawn @scripts_dir/load_url_from_history.sh
@cbind u = spawn @scripts_dir/load_url_from_bookmarks.sh
+# Temporary bookmarks
+@cbind <Ctrl>d = spawn @scripts_dir/insert_temp.sh
+@cbind D = spawn @scripts_dir/load_url_from_temps.sh
+
# Link following (similar to vimperator and konqueror)
# Set custom keys you wish to use for navigation. Some common examples:
set follow_hint_keys = 0123456789
@@ -333,7 +345,7 @@ set follow_hint_keys = 0123456789
#set follow_hint_keys = thsnd-rcgmvwb/;789aefijkopquxyz234
@cbind fl* = spawn @scripts_dir/follow.sh \@< uzbl.follow("\@follow_hint_keys", "%s", 0) >\@
@cbind Fl* = spawn @scripts_dir/follow.sh \@< uzbl.follow("\@follow_hint_keys", "%s", 1) >\@
-@cbind gi = spawn @scripts_dir/go_input.sh
+@cbind fi = spawn @scripts_dir/go_input.sh
# Form filler binds
# This script allows you to configure (per domain) values to fill in form
@@ -341,10 +353,10 @@ set follow_hint_keys = 0123456789
# This implementation allows you to save multiple profiles for each form
# (think about multiple accounts on some website).
set formfiller = spawn @scripts_dir/formfiller.sh
-@cbind za = @formfiller add
@cbind ze = @formfiller edit
@cbind zn = @formfiller new
@cbind zl = @formfiller load
+@cbind zo = @formfiller once
# --- Uzbl tabbed binds ------------------------------------------------------
@@ -370,7 +382,8 @@ set preset = event PRESET_TABS
@cbind gs<preset save:>_ = @preset save %s
@cbind glo<preset load:>_ = @preset load %s
@cbind gd<preset del:>_ = @preset del %s
-@cbind gli = @preset list
+# This doesn't work right now.
+#@cbind gli = @preset list
# === Context menu items =====================================================
diff --git a/examples/data/style.css b/examples/config/style.css
index ff055d1..a368aa0 100644
--- a/examples/data/style.css
+++ b/examples/config/style.css
@@ -1,12 +1,11 @@
#uzbl_link_hints > span {
z-index: 1000 !important;
- background-color: #aaff00 !important;
- border: 2px solid #556600 !important;
- margin: 0 !important;
- padding: 1px !important;
+ background-color: #333 !important;
+ margin: 0 !important;
+ padding: 3px !important;
- color: black !important;
+ color: #ccc !important;
font-size: 9px !important;
line-height: 9px !important;
font-weight: bold !important;
@@ -14,12 +13,16 @@
text-decoration: none !important;
-webkit-transform: translate(-5px,-5px);
- /* opacity: 0.7; */
+ opacity: 0.8;
+ -webkit-border-radius: 6px !important;
+ /* Play around with this, pretty fun things to do :) */
+ /* -webkit-transform: scale(1) rotate(0deg) translate(-6px,-5px) !important; */
}
/* we can have different colours for different types of hints! */
#uzbl_link_hints.new-window > span {
background-color: #ffff00 !important;
+ color: black !important;
}
/* vim:set et ts=4: */
diff --git a/examples/data/plugins/bind.py b/examples/data/plugins/bind.py
index 69fd863..fc8b392 100644
--- a/examples/data/plugins/bind.py
+++ b/examples/data/plugins/bind.py
@@ -372,11 +372,11 @@ def mode_changed(uzbl, mode):
uzbl.bindlet.reset()
-def match_and_exec(uzbl, bind, depth, keylet, bindlet):
+def match_and_exec(uzbl, bind, depth, modstate, keylet, bindlet):
(on_exec, has_args, mod_cmd, glob, more) = bind[depth]
cmd = keylet.modcmd if mod_cmd else keylet.keycmd
- if mod_cmd and keylet.held != mod_cmd:
+ if mod_cmd and modstate != mod_cmd:
return False
if has_args:
@@ -415,7 +415,7 @@ def match_and_exec(uzbl, bind, depth, keylet, bindlet):
return True
-def key_event(uzbl, keylet, mod_cmd=False, on_exec=False):
+def key_event(uzbl, modstate, keylet, mod_cmd=False, on_exec=False):
bindlet = uzbl.bindlet
depth = bindlet.depth
for bind in bindlet.get_binds():
@@ -423,7 +423,7 @@ def key_event(uzbl, keylet, mod_cmd=False, on_exec=False):
if (bool(t[MOD_CMD]) != mod_cmd) or (t[ON_EXEC] != on_exec):
continue
- if match_and_exec(uzbl, bind, depth, keylet, bindlet):
+ if match_and_exec(uzbl, bind, depth, modstate, keylet, bindlet):
return
bindlet.after()
diff --git a/examples/data/plugins/history.py b/examples/data/plugins/history.py
index 5e9e4e1..f42f86f 100644
--- a/examples/data/plugins/history.py
+++ b/examples/data/plugins/history.py
@@ -83,7 +83,7 @@ class History(object):
def __str__(self):
return "(History %s, %s)" % (self.cursor, self.prompt)
-def keycmd_exec(uzbl, keylet):
+def keycmd_exec(uzbl, modstate, keylet):
cmd = keylet.get_keycmd()
if cmd:
uzbl.history.add(cmd)
diff --git a/examples/data/plugins/keycmd.py b/examples/data/plugins/keycmd.py
index 928c597..1bb70e3 100644
--- a/examples/data/plugins/keycmd.py
+++ b/examples/data/plugins/keycmd.py
@@ -17,13 +17,10 @@ def uzbl_escape(str):
class Keylet(object):
- '''Small per-instance object that tracks all the keys held and characters
- typed.'''
+ '''Small per-instance object that tracks characters typed.'''
def __init__(self):
# Modcmd tracking
- self.held = set()
- self.ignored = set()
self.modcmd = ''
self.is_modcmd = False
@@ -33,7 +30,6 @@ class Keylet(object):
self.modmaps = {}
self.ignores = {}
- self.additions = {}
def get_keycmd(self):
@@ -48,7 +44,7 @@ class Keylet(object):
if not self.is_modcmd:
return ''
- return ''.join(self.held) + self.modcmd
+ return self.modcmd
def modmap_key(self, key):
@@ -65,28 +61,6 @@ class Keylet(object):
return key
- def find_addition(self, modkey):
- '''Key has just been pressed, check if this key + the held list
- results in a modkey addition. Return that addition and remove all
- modkeys that created it.'''
-
- # Intersection of (held list + modkey) and additions.
- added = (self.held | set([modkey])) & set(self.additions.keys())
- for key in added:
- if key == modkey or modkey in self.additions[key]:
- self.held -= self.additions[key]
- return key
-
- # Held list + ignored list + modkey.
- modkeys = self.held | self.ignored | set([modkey])
- for (key, value) in self.additions.items():
- if modkeys.issuperset(value):
- self.held -= value
- return key
-
- return modkey
-
-
def key_ignored(self, key):
'''Check if the given key is ignored by any ignore rules.'''
@@ -104,9 +78,6 @@ class Keylet(object):
if self.is_modcmd:
l.append('modcmd=%r' % self.get_modcmd())
- elif self.held:
- l.append('held=%r' % ''.join(sorted(self.held)))
-
if self.keycmd:
l.append('keycmd=%r' % self.get_keycmd())
@@ -132,10 +103,7 @@ def add_modmap(uzbl, key, map):
assert len(key)
modmaps = uzbl.keylet.modmaps
- if key[0] == "<" and key[-1] == ">":
- key = key[1:-1]
-
- modmaps[key] = map
+ modmaps[key.strip('<>')] = map.strip('<>')
uzbl.event("NEW_MODMAP", key, map)
@@ -171,45 +139,6 @@ def add_key_ignore(uzbl, glob):
uzbl.event('NEW_KEY_IGNORE', glob)
-def add_modkey_addition(uzbl, modkeys, result):
- '''Add a modkey addition definition.
-
- Examples:
- set mod_addition = request MODKEY_ADDITION
- @mod_addition <Shift> <Control> <Meta>
- @mod_addition <Left> <Up> <Left-Up>
- @mod_addition <Right> <Up> <Right-Up>
- ...
-
- Then:
- @bind <Right-Up> = <command1>
- @bind <Meta>o = <command2>
- ...
- '''
-
- additions = uzbl.keylet.additions
- modkeys = set(modkeys)
-
- assert len(modkeys) and result and result not in modkeys
-
- for (existing_result, existing_modkeys) in additions.items():
- if existing_result != result:
- assert modkeys != existing_modkeys
-
- additions[result] = modkeys
- uzbl.event('NEW_MODKEY_ADDITION', modkeys, result)
-
-
-def modkey_addition_parse(uzbl, modkeys):
- '''Parse modkey addition definition.'''
-
- keys = filter(None, map(unicode.strip, modkeys.split(" ")))
- keys = ['<%s>' % key.strip("<>") for key in keys if key.strip("<>")]
-
- assert len(keys) > 1
- add_modkey_addition(uzbl, keys[:-1], keys[-1])
-
-
def clear_keycmd(uzbl, *args):
'''Clear the keycmd for this uzbl instance.'''
@@ -220,15 +149,12 @@ def clear_keycmd(uzbl, *args):
uzbl.event('KEYCMD_CLEARED')
-def clear_modcmd(uzbl, clear_held=False):
+def clear_modcmd(uzbl):
'''Clear the modcmd for this uzbl instance.'''
k = uzbl.keylet
k.modcmd = ''
k.is_modcmd = False
- if clear_held:
- k.ignored = set()
- k.held = set()
del uzbl.config['modcmd']
uzbl.event('MODCMD_CLEARED')
@@ -244,28 +170,22 @@ def clear_current(uzbl):
clear_keycmd(uzbl)
-def focus_changed(uzbl, *args):
- '''Focus to the uzbl instance has now been lost which means all currently
- held keys in the held list will not get a KEY_RELEASE event so clear the
- entire held list.'''
-
- clear_modcmd(uzbl, clear_held=True)
-
-
-def update_event(uzbl, k, execute=True):
+def update_event(uzbl, modstate, k, execute=True):
'''Raise keycmd & modcmd update events.'''
- keycmd, modcmd = k.get_keycmd(), k.get_modcmd()
+ keycmd, modcmd = k.get_keycmd(), ''.join(modstate) + k.get_modcmd()
if k.is_modcmd:
- uzbl.event('MODCMD_UPDATE', k)
+ logger.debug('modcmd_update, %s' % modcmd)
+ uzbl.event('MODCMD_UPDATE', modstate, k)
else:
- uzbl.event('KEYCMD_UPDATE', k)
+ logger.debug('keycmd_update, %s' % keycmd)
+ uzbl.event('KEYCMD_UPDATE', modstate, k)
if uzbl.config.get('modcmd_updates', '1') == '1':
- new_modcmd = k.get_modcmd()
- if not new_modcmd:
+ new_modcmd = ''.join(modstate) + k.get_modcmd()
+ if not new_modcmd or not k.is_modcmd:
del uzbl.config['modcmd']
elif new_modcmd == modcmd:
@@ -293,54 +213,38 @@ def inject_str(str, index, inj):
return "%s%s%s" % (str[:index], inj, str[index:])
-def get_keylet_and_key(uzbl, key, add=True):
- '''Return the keylet and apply any transformations to the key as defined
- by the modmapping or modkey addition rules. Return None if the key is
- ignored.'''
-
+def parse_key_event(uzbl, key):
+ ''' Build a set from the modstate part of the event, and pass all keys through modmap '''
keylet = uzbl.keylet
- key = keylet.modmap_key(key)
- if len(key) == 1:
- return (keylet, key)
-
- modkey = "<%s>" % key.strip("<>")
-
- if keylet.key_ignored(modkey):
- if add:
- keylet.ignored.add(modkey)
-
- elif modkey in keylet.ignored:
- keylet.ignored.remove(modkey)
- modkey = keylet.find_addition(modkey)
-
- if keylet.key_ignored(modkey):
- return (keylet, None)
-
- return (keylet, modkey)
+ modstate, key = splitquoted(key)
+ modstate = set(['<%s>' % keylet.modmap_key(k) for k in modstate.split('|') if k])
+
+ key = keylet.modmap_key(key)
+ return modstate, key
def key_press(uzbl, key):
'''Handle KEY_PRESS events. Things done by this function include:
1. Ignore all shift key presses (shift can be detected by capital chars)
- 3. In non-modcmd mode:
+ 2. In non-modcmd mode:
a. append char to keycmd
- 4. If not in modcmd mode and a modkey was pressed set modcmd mode.
- 5. If in modcmd mode the pressed key is added to the held keys list.
- 6. Keycmd is updated and events raised if anything is changed.'''
+ 3. If not in modcmd mode and a modkey was pressed set modcmd mode.
+ 4. Keycmd is updated and events raised if anything is changed.'''
- (k, key) = get_keylet_and_key(uzbl, key.strip())
- if not key:
- return
+ k = uzbl.keylet
+ modstate, key = parse_key_event(uzbl, key)
+ k.is_modcmd = any(not k.key_ignored(m) for m in modstate)
- if key.lower() == '<space>' and not k.held and k.keycmd:
+ logger.debug('key press modstate=%s' % str(modstate))
+ if key.lower() == 'space' and not k.is_modcmd and k.keycmd:
k.keycmd = inject_str(k.keycmd, k.cursor, ' ')
k.cursor += 1
- elif not k.held and len(key) == 1:
-
+ elif not k.is_modcmd and len(key) == 1:
if uzbl.config.get('keycmd_events', '1') != '1':
+ # TODO, make a note on what's going on here
k.keycmd = ''
k.cursor = 0
del uzbl.config['keycmd']
@@ -349,33 +253,29 @@ def key_press(uzbl, key):
k.keycmd = inject_str(k.keycmd, k.cursor, key)
k.cursor += 1
- elif len(key) > 1:
- k.is_modcmd = True
- if key not in k.held:
- k.held.add(key)
+ elif len(key) == 1:
+ k.modcmd += key
else:
- k.is_modcmd = True
- k.modcmd += key
+ if not k.key_ignored('<%s>' % key):
+ modstate.add('<%s>' % key)
+ k.is_modcmd = True
- update_event(uzbl, k)
+ update_event(uzbl, modstate, k)
def key_release(uzbl, key):
'''Respond to KEY_RELEASE event. Things done by this function include:
- 1. Remove the key from the keylet held list.
- 2. If in a mod-command then raise a MODCMD_EXEC.
- 3. Check if any modkey is held, if so set modcmd mode.
- 4. Update the keycmd uzbl variable if anything changed.'''
-
- (k, key) = get_keylet_and_key(uzbl, key.strip(), add=False)
+ 1. If in a mod-command then raise a MODCMD_EXEC.
+ 2. Update the keycmd uzbl variable if anything changed.'''
+ k = uzbl.keylet
+ modstate, key = parse_key_event(uzbl, key)
- if key in k.held:
+ if len(key) > 1:
if k.is_modcmd:
- uzbl.event('MODCMD_EXEC', k)
+ uzbl.event('MODCMD_EXEC', modstate, k)
- k.held.remove(key)
clear_modcmd(uzbl)
@@ -385,7 +285,7 @@ def set_keycmd(uzbl, keycmd):
k = uzbl.keylet
k.keycmd = keycmd
k.cursor = len(keycmd)
- update_event(uzbl, k, False)
+ update_event(uzbl, set(), k, False)
def inject_keycmd(uzbl, keycmd):
@@ -394,7 +294,7 @@ def inject_keycmd(uzbl, keycmd):
k = uzbl.keylet
k.keycmd = inject_str(k.keycmd, k.cursor, keycmd)
k.cursor += len(keycmd)
- update_event(uzbl, k, False)
+ update_event(uzbl, set(), k, False)
def append_keycmd(uzbl, keycmd):
@@ -403,23 +303,29 @@ def append_keycmd(uzbl, keycmd):
k = uzbl.keylet
k.keycmd += keycmd
k.cursor = len(k.keycmd)
- update_event(uzbl, k, False)
+ update_event(uzbl, set(), k, False)
-def keycmd_strip_word(uzbl, sep):
+def keycmd_strip_word(uzbl, seps):
''' Removes the last word from the keycmd, similar to readline ^W '''
- sep = sep or ' '
+ seps = seps or ' '
k = uzbl.keylet
if not k.keycmd:
return
- head, tail = k.keycmd[:k.cursor].rstrip(sep), k.keycmd[k.cursor:]
- rfind = head.rfind(sep)
+ head, tail = k.keycmd[:k.cursor].rstrip(seps), k.keycmd[k.cursor:]
+ rfind = -1
+ for sep in seps:
+ p = head.rfind(sep)
+ if p >= 0 and rfind < p + 1:
+ rfind = p + 1
+ if rfind == len(head) and head[-1] in seps:
+ rfind -= 1
head = head[:rfind] if rfind + 1 else ''
k.keycmd = head + tail
k.cursor = len(head)
- update_event(uzbl, k, False)
+ update_event(uzbl, set(), k, False)
def keycmd_backspace(uzbl, *args):
@@ -431,7 +337,7 @@ def keycmd_backspace(uzbl, *args):
k.keycmd = k.keycmd[:k.cursor-1] + k.keycmd[k.cursor:]
k.cursor -= 1
- update_event(uzbl, k, False)
+ update_event(uzbl, set(), k, False)
def keycmd_delete(uzbl, *args):
@@ -442,14 +348,14 @@ def keycmd_delete(uzbl, *args):
return
k.keycmd = k.keycmd[:k.cursor] + k.keycmd[k.cursor+1:]
- update_event(uzbl, k, False)
+ update_event(uzbl, set(), k, False)
def keycmd_exec_current(uzbl, *args):
'''Raise a KEYCMD_EXEC with the current keylet and then clear the
keycmd.'''
- uzbl.event('KEYCMD_EXEC', uzbl.keylet)
+ uzbl.event('KEYCMD_EXEC', set(), uzbl.keylet)
clear_keycmd(uzbl)
@@ -476,7 +382,7 @@ def set_cursor_pos(uzbl, index):
cursor = len(k.keycmd)
k.cursor = cursor
- update_event(uzbl, k, False)
+ update_event(uzbl, set(), k, False)
# plugin init hook
@@ -485,8 +391,6 @@ def init(uzbl):
connect_dict(uzbl, {
'APPEND_KEYCMD': append_keycmd,
- 'FOCUS_GAINED': focus_changed,
- 'FOCUS_LOST': focus_changed,
'IGNORE_KEY': add_key_ignore,
'INJECT_KEYCMD': inject_keycmd,
'KEYCMD_BACKSPACE': keycmd_backspace,
@@ -496,7 +400,8 @@ def init(uzbl):
'KEYCMD_CLEAR': clear_keycmd,
'KEY_PRESS': key_press,
'KEY_RELEASE': key_release,
- 'MODKEY_ADDITION': modkey_addition_parse,
+ 'MOD_PRESS': key_press,
+ 'MOD_RELEASE': key_release,
'MODMAP': modmap_parse,
'SET_CURSOR_POS': set_cursor_pos,
'SET_KEYCMD': set_keycmd,
@@ -504,7 +409,6 @@ def init(uzbl):
export_dict(uzbl, {
'add_key_ignore': add_key_ignore,
- 'add_modkey_addition': add_modkey_addition,
'add_modmap': add_modmap,
'append_keycmd': append_keycmd,
'clear_current': clear_current,
diff --git a/examples/data/scripts/auth.py b/examples/data/scripts/auth.py
index 592a2c6..49fa41e 100755
--- a/examples/data/scripts/auth.py
+++ b/examples/data/scripts/auth.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
import gtk
import sys
diff --git a/examples/data/scripts/download.sh b/examples/data/scripts/download.sh
index c410ad2..dbc9caf 100755
--- a/examples/data/scripts/download.sh
+++ b/examples/data/scripts/download.sh
@@ -1,25 +1,63 @@
#!/bin/sh
-#
# uzbl's example configuration sets this script up as its download_handler.
-# when uzbl starts a download it runs this script.
+# this script is run when uzbl encounters a URL that it can't display, and when
+# a download is requested using the 'download' command.
+#
# if the script prints a file path to stdout, uzbl will save the download to
-# that path.
-# if nothing is printed to stdout, the download will be cancelled.
+# that path using it's internal downloader.
+#
+# if nothing is printed to stdout, the internal download will be cancelled.
+# you could do your own download handling in your script that way.
-. $UZBL_UTIL_DIR/uzbl-dir.sh
+# if $5 is set, it is the path that was passed to uzbl's "download" command.
+# we want to use that if it's available.
+[ -n "$5" ] && echo "$5" && exit
+
+. "$UZBL_UTIL_DIR/uzbl-dir.sh"
# the URL that is being downloaded
-uri=$1
+uri="$1"
+shift
+
+safe_uri="$( echo "$uri" | sed -e 's/\W/-/g' )"
# a filename suggested by the server or based on the URL
-suggested_filename=${2:-$(echo "$uri" | sed 's/\W/-/g')}
+suggested_filename="${1:-$safe_uri}"
+shift
# the mimetype of the file being downloaded
-content_type=$3
+content_type="$1"
+shift
# the size of the downloaded file in bytes. this is not always accurate, since
# the server might not have sent a size with its response headers.
-total_size=$4
+total_size="$1"
+shift
+
+case "$suggested_filename" in
+ # example: save torrents to a separate directory
+ #*.torrent)
+ # path="$UZBL_DOWNLOAD_DIR/torrents/$suggested_filename"
+ # ;;
+ # Default case
+ *)
+ path="$UZBL_DOWNLOAD_DIR/$suggested_filename"
+ ;;
+esac
+
+# Do nothing if we don't want to save the file
+[ -z "$path" ] && exit 0
+
+# Check if the file exists
+if [ ! -e "$path" ]; then
+ echo "$path"
+ exit 0
+fi
+
+# Try to make a unique filename
+count=1
+while [ -e "$path.$count" ]; do
+ count=$(( $count + 1 ))
+done
-# just save the file to the default directory with the suggested name
-echo $UZBL_DOWNLOAD_DIR/$suggested_filename
+echo "$path.$count"
diff --git a/examples/data/scripts/follow.js b/examples/data/scripts/follow.js
index 536256b..b7b0d82 100644
--- a/examples/data/scripts/follow.js
+++ b/examples/data/scripts/follow.js
@@ -98,12 +98,17 @@ uzbl.follow.elementInViewport = function(el) {
}
// Removes all hints/leftovers that might be generated
-// by this script.
-uzbl.follow.removeAllHints = function(doc) {
+// by this script in the given document.
+uzbl.follow.removeHints = function(doc) {
var elements = doc.getElementById(uzbldivid);
if (elements) elements.parentNode.removeChild(elements);
}
+// Clears all hints in every document
+uzbl.follow.clearHints = function() {
+ this.documents().forEach(uzbl.follow.removeHints);
+}
+
// Generate a hint for an element with the given label
// Here you can play around with the style of the hints!
uzbl.follow.generateHint = function(doc, el, label, top, left) {
@@ -153,7 +158,7 @@ uzbl.follow.reDrawHints = function(elems, chars) {
var positions = elements.map(uzbl.follow.elementPosition);
this.documents().forEach(function(doc) {
- uzbl.follow.removeAllHints(doc);
+ uzbl.follow.removeHints(doc);
if (!doc.body) return;
doc.hintdiv = doc.createElement('div');
doc.hintdiv.id = uzbldivid;
@@ -211,7 +216,7 @@ uzbl.follow.followLinks = function(follow) {
var s = follow.split('');
var linknr = this.labelToInt(follow);
- var followable = 'a, area, textarea, select, input:not([type=hidden]), button';
+ var followable = 'a, area, textarea, select, input:not([type=hidden]), button, *[onclick]';
var uri = 'a, area, frame, iframe';
//var focusable = 'a, area, textarea, select, input:not([type=hidden]), button, frame, iframe, applet, object';
//var desc = '*[title], img[alt], applet[alt], area[alt], input[alt]';
@@ -230,7 +235,7 @@ uzbl.follow.followLinks = function(follow) {
var el = elems[linknr];
// clear all of our hints
- this.documents().forEach(uzbl.follow.removeAllHints);
+ this.clearHints();
if (newwindow) {
// we're opening a new window using the URL attached to this element
diff --git a/examples/data/scripts/follow.sh b/examples/data/scripts/follow.sh
index 1f8947d..014793e 100755
--- a/examples/data/scripts/follow.sh
+++ b/examples/data/scripts/follow.sh
@@ -2,10 +2,12 @@
# This scripts acts on the return value of followLinks in follow.js
case "$1" in
- XXXEMIT_FORM_ACTIVEXXX)
- # a form element was selected
- printf 'event FORM_ACTIVE\nevent KEYCMD_CLEAR\n' > "$UZBL_FIFO" ;;
- XXXRESET_MODEXXX)
- # a link was selected, reset uzbl's input mode
- printf 'set mode=\nevent KEYCMD_CLEAR\n' > "$UZBL_FIFO" ;;
+ XXXEMIT_FORM_ACTIVEXXX)
+ # a form element was selected
+ printf 'event FORM_ACTIVE\nevent KEYCMD_CLEAR\n' > "$UZBL_FIFO"
+ ;;
+ XXXRESET_MODEXXX)
+ # a link was selected, reset uzbl's input mode
+ printf 'set mode=\nevent KEYCMD_CLEAR\n' > "$UZBL_FIFO"
+ ;;
esac
diff --git a/examples/data/scripts/formfiller.sh b/examples/data/scripts/formfiller.sh
index 3dc9dc4..c1171a0 100755
--- a/examples/data/scripts/formfiller.sh
+++ b/examples/data/scripts/formfiller.sh
@@ -66,22 +66,22 @@ ParseFields ()
field = $0
sub ( /[^:]*:/, "", field )
- if ( parts[2] ~ /(text|password|search)/ )
+ if ( parts[2] ~ /^(text|password|search)$/ )
printf( "js uzbl.formfiller.insert(\"%s\",\"%s\",\"%s\",0);\n",
parts[1], parts[2], field )
- else if ( parts[2] ~ /(checkbox|radio)/ )
+ else if ( parts[2] ~ /^(checkbox|radio)$/ )
printf( "js uzbl.formfiller.insert(\"%s\",\"%s\",\"%s\",%s);\n",
parts[1], parts[2], parts[3], field )
- else if ( parts[2] == "textarea" ) {
+ else if ( parts[2] ~ /^textarea$/ ) {
field = ""
while (getline) {
if ( /^%/ ) break
sub ( /^\\/, "" )
gsub ( /"/, "\\\"" )
gsub ( /\\/, "\\\\" )
- field = field $0 "\\n"
+ field = field $0 "\\\\n"
}
printf( "js uzbl.formfiller.insert(\"%s\",\"%s\",\"%s\",0);\n",
parts[1], parts[2], field )
@@ -116,7 +116,7 @@ Load ()
ParseProfile $option < "$file" \
| ParseFields \
- | sed 's/@/\\@/' \
+ | sed 's/@/\\@/g' \
> "$UZBL_FIFO"
}
@@ -132,7 +132,7 @@ Once ()
test -e "$tmpfile" &&
ParseFields < "$tmpfile" \
- | sed 's/@/\\@' \
+ | sed 's/@/\\@/g' \
> "$UZBL_FIFO"
}
diff --git a/examples/data/scripts/go_input.sh b/examples/data/scripts/go_input.sh
index ace0e79..9797788 100755
--- a/examples/data/scripts/go_input.sh
+++ b/examples/data/scripts/go_input.sh
@@ -1,5 +1,7 @@
#!/bin/sh
-case $(echo 'script @scripts_dir/go_input.js' | socat - unix-connect:"$UZBL_SOCKET") in
- *XXXEMIT_FORM_ACTIVEXXX*) echo 'event FORM_ACTIVE' > "$UZBL_FIFO" ;;
+case "$( echo "script @scripts_dir/go_input.js" | socat - "unix-connect:$UZBL_SOCKET" )" in
+ *XXXEMIT_FORM_ACTIVEXXX*)
+ echo "event FORM_ACTIVE" > "$UZBL_FIFO"
+ ;;
esac
diff --git a/examples/data/scripts/history.sh b/examples/data/scripts/history.sh
index 266d65d..0709b5e 100755
--- a/examples/data/scripts/history.sh
+++ b/examples/data/scripts/history.sh
@@ -1,7 +1,7 @@
#!/bin/sh
-. $UZBL_UTIL_DIR/uzbl-dir.sh
+. "$UZBL_UTIL_DIR/uzbl-dir.sh"
-[ -w "$UZBL_HISTORY_FILE" ] || [ ! -a "$UZBL_HISTORY_FILE" ] || exit 1
+>> "$UZBL_HISTORY_FILE" || exit 1
-echo $(date +'%Y-%m-%d %H:%M:%S')" $UZBL_URI $UZBL_TITLE" >> $UZBL_HISTORY_FILE
+echo "$( date +'%Y-%m-%d %H:%M:%S' ) $UZBL_URI $UZBL_TITLE" >> "$UZBL_HISTORY_FILE"
diff --git a/examples/data/scripts/insert_bookmark.sh b/examples/data/scripts/insert_bookmark.sh
index f67e67a..f310e49 100755
--- a/examples/data/scripts/insert_bookmark.sh
+++ b/examples/data/scripts/insert_bookmark.sh
@@ -1,15 +1,14 @@
#!/bin/sh
-. "$UZBL_UTIL_DIR"/uzbl-dir.sh
+. "$UZBL_UTIL_DIR/uzbl-dir.sh"
-[ -d "$UZBL_DATA_DIR" ] || exit 1
-[ -w "$UZBL_BOOKMARKS_FILE" ] || [ ! -a "$UZBL_BOOKMARKS_FILE" ] || exit 1
+>> "$UZBL_BOOKMARKS_FILE" || exit 1
which zenity >/dev/null 2>&1 || exit 2
-tags=$(zenity --entry --text="Enter space-separated tags for bookmark $UZBL_URI:")
-exitstatus=$?
-[ $exitstatus -eq 0 ] || exit $exitstatus
+tags="$( zenity --entry --text="Enter space-separated tags for bookmark $UZBL_URI:" )"
+exitstatus="$?"
+[ "$exitstatus" -eq 0 ] || exit "$exitstatus"
# TODO: check if already exists, if so, and tags are different: ask if you want to replace tags
echo "$UZBL_URI $tags" >> "$UZBL_BOOKMARKS_FILE"
diff --git a/examples/data/scripts/insert_temp.sh b/examples/data/scripts/insert_temp.sh
new file mode 100755
index 0000000..7ed8d22
--- /dev/null
+++ b/examples/data/scripts/insert_temp.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+. "$UZBL_UTIL_DIR/uzbl-dir.sh"
+
+>> "$UZBL_TEMPS_FILE" || exit 1
+
+echo "$UZBL_URI $UZBL_TITLE" >> "$UZBL_TEMPS_FILE"
diff --git a/examples/data/scripts/instance-select-wmii.sh b/examples/data/scripts/instance-select-wmii.sh
index 19d04e8..b2aadbb 100755
--- a/examples/data/scripts/instance-select-wmii.sh
+++ b/examples/data/scripts/instance-select-wmii.sh
@@ -1,6 +1,5 @@
#!/bin/sh
-
# This script allows you to focus another uzbl window
# It considers all uzbl windows in the current tag
# you can select one from a list, or go to the next/previous one
@@ -13,30 +12,30 @@
DMENU_SCHEME="wmii"
-. $UZBL_UTIL_DIR/dmenu.sh
+. "$UZBL_UTIL_DIR/dmenu.sh"
case "$1" in
- "list" )
- list=
+ "list")
+ list=""
# get window id's of uzbl clients. we could also get the label in one shot but it's pretty tricky
- for i in $(wmiir read /tag/sel/index | grep uzbl |cut -d ' ' -f2); do
- label=$(wmiir read /client/$i/label)
+ for i in $( wmiir read /tag/sel/index | grep uzbl | cut -d ' ' -f 2 ); do
+ label="$( wmiir read /client/$i/label )"
list="$list$i : $label\n"
done
- window=$(printf "$list\n" | $DMENU | cut -d ' ' -f1)
+ window="$( echo "$list" | $DMENU | cut -d ' ' -f 1 )"
wmiir xwrite /tag/sel/ctl "select client $window"
;;
- "next" )
- current=$(wmiir read /client/sel/ctl | head -n 1)
+ "next")
+ current="$( wmiir read /client/sel/ctl | head -n 1 )"
# find the next uzbl window and focus it
- next=$(wmiir read /tag/sel/index | grep -A 10000 " $current " | grep -m 1 uzbl | cut -d ' ' -f2)
+ next="$( wmiir read /tag/sel/index | grep -A 10000 " $current " | grep -m 1 uzbl | cut -d ' ' -f 2 )"
if [ -n "$next" ]; then
wmiir xwrite /tag/sel/ctl "select client $next"
fi
;;
- "prev" )
- current=$(wmiir read /client/sel/ctl | head -n 1)
- prev=$(wmiir read /tag/sel/index | grep -B 10000 " $current " | tac | grep -m 1 uzbl | cut -d ' ' -f2)
+ "prev")
+ current="$( wmiir read /client/sel/ctl | head -n 1 )"
+ prev="$( wmiir read /tag/sel/index | grep -B 10000 " $current " | tac | grep -m 1 uzbl | cut -d ' ' -f 2 )"
if [ -n "$prev" ]; then
wmiir xwrite /tag/sel/ctl "select client $prev"
fi
diff --git a/examples/data/scripts/load_cookies.sh b/examples/data/scripts/load_cookies.sh
index 17ec2ad..c7fcc58 100755
--- a/examples/data/scripts/load_cookies.sh
+++ b/examples/data/scripts/load_cookies.sh
@@ -1,20 +1,21 @@
#!/bin/sh
-if [ "$1" != "" ]; then
- cookie_file=$1
+if [ -n "$1" ]; then
+ cookie_file="$1"
+ shift
else
- cookie_file=${XDG_DATA_HOME:-$HOME/.local/share}/uzbl/cookies.txt
+ cookie_file="${XDG_DATA_HOME:-$HOME/.local/share}/uzbl/cookies.txt"
fi
awk -F \\t '
BEGIN {
- scheme["TRUE"] = "https";
- scheme["FALSE"] = "http";
+ scheme["TRUE"] = "https";
+ scheme["FALSE"] = "http";
}
$0 ~ /^#HttpOnly_/ {
-printf("add_cookie \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"\n", substr($1,length("#HttpOnly_"),length($1)), $3, $6, $7, scheme[$4], $5)
+ printf("add_cookie \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"\n", substr($1,length("#HttpOnly_"),length($1)), $3, $6, $7, scheme[$4], $5)
}
$0 !~ /^#/ {
-printf("add_cookie \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"\n", $1, $3, $6, $7, scheme[$4], $5)
+ printf("add_cookie \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"\n", $1, $3, $6, $7, scheme[$4], $5)
}
-' $cookie_file
+' "$cookie_file"
diff --git a/examples/data/scripts/load_url_from_bookmarks.sh b/examples/data/scripts/load_url_from_bookmarks.sh
index a5d9586..a03db4b 100755
--- a/examples/data/scripts/load_url_from_bookmarks.sh
+++ b/examples/data/scripts/load_url_from_bookmarks.sh
@@ -5,18 +5,18 @@
DMENU_SCHEME="bookmarks"
DMENU_OPTIONS="xmms vertical resize"
-. "$UZBL_UTIL_DIR"/dmenu.sh
-. "$UZBL_UTIL_DIR"/uzbl-dir.sh
+. "$UZBL_UTIL_DIR/dmenu.sh"
+. "$UZBL_UTIL_DIR/uzbl-dir.sh"
[ -r "$UZBL_BOOKMARKS_FILE" ] || exit 1
if [ -z "$DMENU_HAS_VERTICAL" ]; then
# because they are all after each other, just show the url, not their tags.
- goto=$(awk '{print $1}' "$UZBL_BOOKMARKS_FILE" | $DMENU)
+ goto="$( awk '{ print $1 }' "$UZBL_BOOKMARKS_FILE" | $DMENU )"
else
# show tags as well
- goto=$($DMENU < "$UZBL_BOOKMARKS_FILE" | awk '{print $1}')
+ goto="$( $DMENU < "$UZBL_BOOKMARKS_FILE" | cut -d ' ' -f 1 )"
fi
[ -n "$goto" ] && echo "uri $goto" > "$UZBL_FIFO"
-#[ -n "$goto" ] && echo "uri $goto" | socat - unix-connect:"$UZBL_SOCKET"
+#[ -n "$goto" ] && echo "uri $goto" | socat - "unix-connect:$UZBL_SOCKET"
diff --git a/examples/data/scripts/load_url_from_history.sh b/examples/data/scripts/load_url_from_history.sh
index 59ad492..24bfdce 100755
--- a/examples/data/scripts/load_url_from_history.sh
+++ b/examples/data/scripts/load_url_from_history.sh
@@ -3,21 +3,20 @@
DMENU_SCHEME="history"
DMENU_OPTIONS="xmms vertical resize"
-. "$UZBL_UTIL_DIR"/dmenu.sh
-. "$UZBL_UTIL_DIR"/uzbl-dir.sh
+. "$UZBL_UTIL_DIR/dmenu.sh"
+. "$UZBL_UTIL_DIR/uzbl-dir.sh"
[ -r "$UZBL_HISTORY_FILE" ] || exit 1
# choose from all entries, sorted and uniqued
-# goto=$(awk '{print $3}' $history_file | sort -u | dmenu -i)
if [ -z "$DMENU_HAS_VERTICAL" ]; then
- current=$(tail -n 1 "$UZBL_HISTORY_FILE" | awk '{print $3}');
- goto=$( (echo $current; awk '{print $3}' "$UZBL_HISTORY_FILE" | grep -v "^$current\$" | sort -u) | $DMENU)
+ current="$( tail -n 1 "$UZBL_HISTORY_FILE" | cut -d ' ' -f 3 )"
+ goto="$( ( echo "$current"; awk '{ print $3 }' "$UZBL_HISTORY_FILE" | grep -v "^$current\$" | sort -u ) | $DMENU )"
else
# choose an item in reverse order, showing also the date and page titles
# pick the last field from the first 3 fields. this way you can pick a url (prefixed with date & time) or type just a new url.
- goto=$(tac "$UZBL_HISTORY_FILE" | $DMENU | cut -d ' ' -f -3 | awk '{print $NF}')
+ goto="$( tac "$UZBL_HISTORY_FILE" | $DMENU | cut -d ' ' -f -3 | awk '{ print $NF }' )"
fi
[ -n "$goto" ] && echo "uri $goto" > "$UZBL_FIFO"
-#[ -n "$goto" ] && echo "uri $goto" | socat - unix-connect:"$UZBL_SOCKET"
+#[ -n "$goto" ] && echo "uri $goto" | socat - "unix-connect:$UZBL_SOCKET"
diff --git a/examples/data/scripts/load_url_from_temps.sh b/examples/data/scripts/load_url_from_temps.sh
new file mode 100755
index 0000000..b46687b
--- /dev/null
+++ b/examples/data/scripts/load_url_from_temps.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+DMENU_SCHEME="temps"
+DMENU_OPTIONS="xmms vertical resize"
+
+. "$UZBL_UTIL_DIR/dmenu.sh"
+. "$UZBL_UTIL_DIR/uzbl-dir.sh"
+
+[ -r "$UZBL_TEMPS_FILE" ] || exit 1
+
+if [ -z "$DMENU_HAS_VERTICAL" ]; then
+ # because they are all after each other, just show the url, not their titles.
+ goto=$( awk '{ print $1 }' "$UZBL_TEMPS_FILE" | $DMENU )
+else
+ # show titles
+ goto=$( $DMENU < "$UZBL_TEMPS_FILE" | cut -d ' ' -f 1 )
+fi
+
+sed -i -e "\<^$goto <d" $UZBL_TEMPS_FILE
+
+[ -n "$goto" ] && echo "uri $goto" > "$UZBL_FIFO"
+#[ -n "$goto" ] && echo "uri $goto" | socat - "unix-connect:$UZBL_SOCKET"
diff --git a/examples/data/scripts/session.sh b/examples/data/scripts/session.sh
index ee09cf2..4e7bfd1 100755
--- a/examples/data/scripts/session.sh
+++ b/examples/data/scripts/session.sh
@@ -18,28 +18,30 @@
if [ -z "$UZBL_UTIL_DIR" ]; then
# we're being run standalone, we have to figure out where $UZBL_UTIL_DIR is
# using the same logic as uzbl-browser does.
- UZBL_UTIL_DIR=${XDG_DATA_HOME:-$HOME/.local/share}/uzbl/scripts/util
+ UZBL_UTIL_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/uzbl/scripts/util"
if ! [ -d "$UZBL_UTIL_DIR" ]; then
- PREFIX=$(grep '^PREFIX' "$(which uzbl-browser)" | sed 's/.*=//')
- UZBL_UTIL_DIR=$PREFIX/share/uzbl/examples/data/scripts/util
+ PREFIX="$( grep '^PREFIX' "$( which uzbl-browser )" | sed -e 's/.*=//' )"
+ UZBL_UTIL_DIR="$PREFIX/share/uzbl/examples/data/scripts/util"
fi
fi
-. "$UZBL_UTIL_DIR"/uzbl-dir.sh
+. "$UZBL_UTIL_DIR/uzbl-dir.sh"
+
[ -d "$UZBL_DATA_DIR" ] || exit 1
-UZBL="uzbl-browser -c $UZBL_CONFIG_FILE" # add custom flags and whatever here.
+UZBL="uzbl-browser -c \"$UZBL_CONFIG_FILE\"" # add custom flags and whatever here.
-scriptfile=$(readlink -f $0) # this script
+scriptfile="$( readlink -f "$0" )" # this script
act="$1"
+shift
if [ -z "$act" ]; then
[ -f "$UZBL_SESSION_FILE" ] && act="launch" || act="endsession"
fi
case $act in
- "launch" )
- urls=$(cat "$UZBL_SESSION_FILE")
+ "launch")
+ urls="$( cat "$UZBL_SESSION_FILE" )"
if [ -z "$urls" ]; then
$UZBL
else
@@ -50,17 +52,17 @@ case $act in
fi
;;
- "endinstance" )
+ "endinstance")
if [ -z "$UZBL_FIFO" ]; then
echo "session manager: endinstance must be called from uzbl"
exit 1
fi
[ "$UZBL_URI" != "(null)" ] && echo "$UZBL_URI" >> "$UZBL_SESSION_FILE"
- echo exit > "$UZBL_FIFO"
+ echo "exit" > "$UZBL_FIFO"
;;
- "endsession" )
- for fifo in "$UZBL_FIFO_DIR"/uzbl_fifo_*; do
+ "endsession")
+ for fifo in "$UZBL_FIFO_DIR/uzbl_fifo_*"; do
if [ "$fifo" != "$UZBL_FIFO" ]; then
echo "spawn $scriptfile endinstance" > "$fifo"
fi
@@ -68,7 +70,7 @@ case $act in
[ -z "$UZBL_FIFO" ] || echo "spawn $scriptfile endinstance" > "$UZBL_FIFO"
;;
- * )
+ *)
echo "session manager: bad action"
echo "Usage: $scriptfile [COMMAND] where commands are:"
echo " launch - Restore a saved session or start a new one"
diff --git a/examples/data/scripts/util/dmenu.sh b/examples/data/scripts/util/dmenu.sh
index 354d7d1..0b7272e 100644
--- a/examples/data/scripts/util/dmenu.sh
+++ b/examples/data/scripts/util/dmenu.sh
@@ -30,6 +30,13 @@ case "$DMENU_SCHEME" in
SB="#ccffaa"
SF="#303030"
;;
+ # Temps
+ "temps" )
+ NB="#303030"
+ NF="khaki"
+ SB="#ccffaa"
+ SF="#303030"
+ ;;
# Default
* )
NB="#303030"
@@ -98,7 +105,7 @@ if dmenu --help 2>&1 | grep -q '\[-l <\?lines>\?\]'; then
fi
# Detect placement patch
-if dmenu --help 2>&1 | grep -q '\[-x <xoffset>\]'; then
+if dmenu --help 2>&1 | grep -q '\[-x <\?xoffset>\?\]'; then
DMENU_PLACE_X="-x"
DMENU_PLACE_Y="-y"
DMENU_PLACE_WIDTH="-w"
diff --git a/examples/data/scripts/util/uzbl-dir.sh b/examples/data/scripts/util/uzbl-dir.sh
index bb56954..82510d8 100644
--- a/examples/data/scripts/util/uzbl-dir.sh
+++ b/examples/data/scripts/util/uzbl-dir.sh
@@ -2,18 +2,19 @@
# Common directories and files used in scripts
# Common things first
-UZBL_DATA_DIR=${XDG_DATA_HOME:-$HOME/.local/share}/uzbl
-UZBL_CONFIG_DIR=${XDG_CONFIG_DIR:-$HOME/.config}/uzbl
+UZBL_DATA_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/uzbl"
+UZBL_CONFIG_DIR="${XDG_CONFIG_DIR:-$HOME/.config}/uzbl"
UZBL_FIFO_DIR=/tmp
UZBL_SOCKET_DIR=/tmp
# Directories
-UZBL_DOWNLOAD_DIR=${XDG_DOWNLOAD_DIR:-$HOME}
-UZBL_FORMS_DIR=$UZBL_DATA_DIR/dforms
+UZBL_DOWNLOAD_DIR="${XDG_DOWNLOAD_DIR:-$HOME}"
+UZBL_FORMS_DIR="$UZBL_DATA_DIR/dforms"
# Data files
-UZBL_CONFIG_FILE=$UZBL_CONFIG_DIR/config
-UZBL_COOKIE_FILE=$UZBL_DATA_DIR/cookies.txt
-UZBL_BOOKMARKS_FILE=$UZBL_DATA_DIR/bookmarks
-UZBL_HISTORY_FILE=$UZBL_DATA_DIR/history
-UZBL_SESSION_FILE=$UZBL_DATA_DIR/browser-session
+UZBL_CONFIG_FILE="$UZBL_CONFIG_DIR/config"
+UZBL_COOKIE_FILE="$UZBL_DATA_DIR/cookies.txt"
+UZBL_BOOKMARKS_FILE="$UZBL_DATA_DIR/bookmarks"
+UZBL_TEMPS_FILE="$UZBL_DATA_DIR/temps"
+UZBL_HISTORY_FILE="$UZBL_DATA_DIR/history"
+UZBL_SESSION_FILE="$UZBL_DATA_DIR/browser-session"
diff --git a/examples/data/scripts/util/uzbl-window.sh b/examples/data/scripts/util/uzbl-window.sh
index a7e92eb..4b96372 100644
--- a/examples/data/scripts/util/uzbl-window.sh
+++ b/examples/data/scripts/util/uzbl-window.sh
@@ -1,11 +1,11 @@
#!/bin/sh
# uzbl window detection
-UZBL_WIN_POS=$(xwininfo -id $UZBL_XID | \
- sed -ne 's/Corners:[ ]*[+-]\([0-9]*\)[+-]\([0-9]*\).*$/\1 \2/p')
-UZBL_WIN_SIZE=$(xwininfo -id $UZBL_XID | \
- sed -ne 's/-geometry[ ]*\([0-9]*\)x\([0-9]*\).*$/\1 \2/p')
-UZBL_WIN_POS_X=$(echo $UZBL_WIN_POS | cut -d\ -f1)
-UZBL_WIN_POS_Y=$(echo $UZBL_WIN_POS | cut -d\ -f2)
-UZBL_WIN_WIDTH=$(echo $UZBL_WIN_SIZE | cut -d\ -f1)
-UZBL_WIN_HEIGHT=$(echo $UZBL_WIN_SIZE | cut -d\ -f2)
+UZBL_WIN_POS="$( xwininfo -id "$UZBL_XID" | \
+ sed -n -e '[ ]*s/Corners:[ ]*[+-]\([0-9]*\)[+-]\([0-9]*\).*$/\1 \2/p' )"
+UZBL_WIN_SIZE="$( xwininfo -id "$UZBL_XID" | \
+ sed -n -e '[ ]*s/-geometry[ ]*\([0-9]*\)x\([0-9]*\).*$/\1 \2/p' )"
+UZBL_WIN_POS_X="$( echo "$UZBL_WIN_POS" | cut -d ' ' -f 1 )"
+UZBL_WIN_POS_Y="$( echo "$UZBL_WIN_POS" | cut -d ' ' -f 2 )"
+UZBL_WIN_WIDTH="$( echo "$UZBL_WIN_SIZE" | cut -d ' ' -f 1 )"
+UZBL_WIN_HEIGHT="$( echo "$UZBL_WIN_SIZE" | cut -d ' ' -f 2 )"
diff --git a/misc/cleanprocs-files.sh b/misc/cleanprocs-files.sh
deleted file mode 100755
index 463d1fb..0000000
--- a/misc/cleanprocs-files.sh
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/bash
-killall uzbl; killall strace;
-killall -9 uzbl; killall -9 strace
-
-rm -rf /tmp/uzbl_*
-
-echo "Uzbl processes:"
-ps aux | grep uzbl | grep -v grep
-echo "Uzbl /tmp entries:"
-ls -alh /tmp/uzbl* 2>/dev/null
diff --git a/misc/env.sh b/misc/env.sh
index 68377f2..f815c44 100755
--- a/misc/env.sh
+++ b/misc/env.sh
@@ -10,14 +10,21 @@
# Maybe we should spawn processes from here with an 'exec' at the end?
# Re-define our home location inside the sandbox dir.
-export HOME=$(pwd)/sandbox/home
+HOME=$(pwd)/sandbox/home
+export HOME
# Export default XDG_{DATA,CACHE,..}_HOME locations inside the sandbox
# directory according to defaults in the xdg specification.
# <http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html>
-export XDG_DATA_HOME=$HOME/.local/share
-export XDG_CACHE_HOME=$HOME/.cache
-export XDG_CONFIG_HOME=$HOME/.config
+XDG_DATA_HOME=$HOME/.local/share
+export XDG_DATA_HOME
+
+XDG_CACHE_HOME=$HOME/.cache
+export XDG_CACHE_HOME
+
+XDG_CONFIG_HOME=$HOME/.config
+export XDG_CONFIG_HOME
# Needed to run uzbl-browser etc from here.
-export PATH="$(pwd)/sandbox/usr/local/bin:$PATH"
+PATH="$(pwd)/sandbox/usr/local/bin:$PATH"
+export PATH
diff --git a/misc/fifotest.sh b/misc/fifotest.sh
deleted file mode 100755
index 8ad0593..0000000
--- a/misc/fifotest.sh
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/bash
-if [ -z "$1" ]
-then
- echo "Need fifo filename!" >&2
- exit 2
-fi
-while :
-do
- echo 'uri dns.be'
- echo 'uri dns.be' > $1
- sleep 2
- echo 'uri www.archlinux.org'
- echo 'uri www.archlinux.org' > $1
- sleep 2
- echo 'uri icanhascheezburger.com'
- echo 'uri icanhascheezburger.com' > $1
- sleep 2
- echo 'back'
- echo 'back' > $1
-done
diff --git a/src/callbacks.c b/src/callbacks.c
index bd50d81..bce399f 100644
--- a/src/callbacks.c
+++ b/src/callbacks.c
@@ -292,8 +292,11 @@ cmd_caret_browsing() {
void
set_current_encoding() {
- webkit_web_view_set_custom_encoding(uzbl.gui.web_view,
- uzbl.behave.current_encoding);
+ gchar *encoding = uzbl.behave.current_encoding;
+ if(strlen(encoding) == 0)
+ encoding = NULL;
+
+ webkit_web_view_set_custom_encoding(uzbl.gui.web_view, encoding);
}
@@ -550,7 +553,7 @@ key_press_cb (GtkWidget* window, GdkEventKey* event) {
(void) window;
if(event->type == GDK_KEY_PRESS)
- key_to_event(event->keyval, GDK_KEY_PRESS);
+ key_to_event(event->keyval, event->state, event->is_modifier, GDK_KEY_PRESS);
return uzbl.behave.forward_keys ? FALSE : TRUE;
}
@@ -560,7 +563,7 @@ key_release_cb (GtkWidget* window, GdkEventKey* event) {
(void) window;
if(event->type == GDK_KEY_RELEASE)
- key_to_event(event->keyval, GDK_KEY_RELEASE);
+ key_to_event(event->keyval, event->state, event->is_modifier, GDK_KEY_RELEASE);
return uzbl.behave.forward_keys ? FALSE : TRUE;
}
@@ -838,6 +841,11 @@ download_cb(WebKitWebView *web_view, WebKitDownload *download, gpointer user_dat
/* get the URI being downloaded */
const gchar *uri = webkit_download_get_uri(download);
+ /* get the destination path, if specified.
+ * this is only intended to be set when this function is trigger by an
+ * explicit download using uzbl's 'download' action. */
+ const gchar *destination = user_data;
+
if (uzbl.state.verbose)
printf("Download requested -> %s\n", uri);
@@ -884,6 +892,9 @@ download_cb(WebKitWebView *web_view, WebKitDownload *download, gpointer user_dat
gchar *total_size_s = g_strdup_printf("%d", total_size);
g_array_append_val(a, total_size_s);
+ if(destination)
+ g_array_append_val(a, destination);
+
GString *result = g_string_new ("");
run_parsed_command(c, a, result);
diff --git a/src/events.c b/src/events.c
index 58dddfc..62d6414 100644
--- a/src/events.c
+++ b/src/events.c
@@ -23,6 +23,8 @@ const char *event_table[LAST_EVENT] = {
"REQUEST_STARTING" ,
"KEY_PRESS" ,
"KEY_RELEASE" ,
+ "MOD_PRESS" ,
+ "MOD_RELEASE" ,
"COMMAND_EXECUTED" ,
"LINK_HOVER" ,
"TITLE_CHANGED" ,
@@ -158,11 +160,13 @@ vsend_event(int type, const gchar *custom_event, va_list vargs) {
g_string_append_printf (event_message, "%d", va_arg (vargs, int));
break;
case TYPE_STR:
+ /* a string that needs to be escaped */
g_string_append_c (event_message, '\'');
append_escaped (event_message, va_arg (vargs, char*));
g_string_append_c (event_message, '\'');
break;
case TYPE_FORMATTEDSTR:
+ /* a string has already been escaped */
g_string_append (event_message, va_arg (vargs, char*));
break;
case TYPE_NAME:
@@ -200,31 +204,106 @@ send_event(int type, const gchar *custom_event, ...) {
va_end (vargs);
}
+gchar *
+get_modifier_mask(guint state) {
+ GString *modifiers = g_string_new("");
+
+ if(state & GDK_MODIFIER_MASK) {
+ if(state & GDK_SHIFT_MASK)
+ g_string_append(modifiers, "Shift|");
+ if(state & GDK_LOCK_MASK)
+ g_string_append(modifiers, "ScrollLock|");
+ if(state & GDK_CONTROL_MASK)
+ g_string_append(modifiers, "Ctrl|");
+ if(state & GDK_MOD1_MASK)
+ g_string_append(modifiers,"Mod1|");
+ if(state & GDK_MOD2_MASK)
+ g_string_append(modifiers,"Mod2|");
+ if(state & GDK_MOD3_MASK)
+ g_string_append(modifiers,"Mod3|");
+ if(state & GDK_MOD4_MASK)
+ g_string_append(modifiers,"Mod4|");
+ if(state & GDK_MOD5_MASK)
+ g_string_append(modifiers,"Mod5|");
+ if(state & GDK_BUTTON1_MASK)
+ g_string_append(modifiers,"Button1|");
+ if(state & GDK_BUTTON2_MASK)
+ g_string_append(modifiers,"Button2|");
+ if(state & GDK_BUTTON3_MASK)
+ g_string_append(modifiers,"Button3|");
+ if(state & GDK_BUTTON4_MASK)
+ g_string_append(modifiers,"Button4|");
+ if(state & GDK_BUTTON5_MASK)
+ g_string_append(modifiers,"Button5|");
+
+ if(modifiers->str[modifiers->len-1] == '|')
+ g_string_truncate(modifiers, modifiers->len-1);
+ }
+
+ return g_string_free(modifiers, FALSE);
+}
+
+guint key_to_modifier(guint keyval) {
+ /* FIXME
+ * Should really use XGetModifierMapping and/or Xkb to get actual mod keys
+ */
+ switch(keyval) {
+ case GDK_KEY_Shift_L:
+ case GDK_KEY_Shift_R:
+ return GDK_SHIFT_MASK;
+ case GDK_KEY_Control_L:
+ case GDK_KEY_Control_R:
+ return GDK_CONTROL_MASK;
+ case GDK_KEY_Alt_L:
+ case GDK_KEY_Alt_R:
+ return GDK_MOD1_MASK;
+ case GDK_KEY_Super_L:
+ case GDK_KEY_Super_R:
+ return GDK_MOD4_MASK;
+ case GDK_KEY_ISO_Level3_Shift:
+ return GDK_MOD5_MASK;
+ default:
+ return 0;
+ }
+}
+
/* Transform gdk key events to our own events */
void
-key_to_event(guint keyval, gint mode) {
+key_to_event(guint keyval, guint state, guint is_modifier, gint mode) {
gchar ucs[7];
gint ulen;
gchar *keyname;
guint32 ukval = gdk_keyval_to_unicode(keyval);
+ gchar *modifiers = NULL;
+ guint mod = key_to_modifier (keyval);
+ /* Get modifier state including this key press/release */
+ modifiers = get_modifier_mask(mode == GDK_KEY_PRESS ? state | mod : state & ~mod);
+
+ if(is_modifier && mod) {
+ send_event(mode == GDK_KEY_PRESS ? MOD_PRESS : MOD_RELEASE, NULL,
+ TYPE_STR, modifiers,
+ TYPE_NAME, get_modifier_mask (mod),
+ NULL);
+ }
/* check for printable unicode char */
/* TODO: Pass the keyvals through a GtkIMContext so that
* we also get combining chars right
*/
- if(g_unichar_isgraph(ukval)) {
+ else if(g_unichar_isgraph(ukval)) {
ulen = g_unichar_to_utf8(ukval, ucs);
ucs[ulen] = 0;
- send_event(mode == GDK_KEY_PRESS ? KEY_PRESS : KEY_RELEASE,
- NULL, TYPE_FORMATTEDSTR, ucs, NULL);
+ send_event(mode == GDK_KEY_PRESS ? KEY_PRESS : KEY_RELEASE, NULL,
+ TYPE_STR, modifiers, TYPE_STR, ucs, NULL);
}
/* send keysym for non-printable chars */
else if((keyname = gdk_keyval_name(keyval))){
- send_event(mode == GDK_KEY_PRESS ? KEY_PRESS : KEY_RELEASE,
- NULL, TYPE_NAME, keyname , NULL);
+ send_event(mode == GDK_KEY_PRESS ? KEY_PRESS : KEY_RELEASE, NULL,
+ TYPE_STR, modifiers, TYPE_NAME, keyname, NULL);
}
+ g_free(modifiers);
}
/* vi: set et ts=4: */
diff --git a/src/events.h b/src/events.h
index bd519a6..0c40206 100644
--- a/src/events.h
+++ b/src/events.h
@@ -13,7 +13,8 @@
enum event_type {
LOAD_START, LOAD_COMMIT, LOAD_FINISH, LOAD_ERROR,
REQUEST_STARTING,
- KEY_PRESS, KEY_RELEASE, COMMAND_EXECUTED,
+ KEY_PRESS, KEY_RELEASE, MOD_PRESS, MOD_RELEASE,
+ COMMAND_EXECUTED,
LINK_HOVER, TITLE_CHANGED, GEOMETRY_CHANGED,
WEBINSPECTOR, NEW_WINDOW, SELECTION_CHANGED,
VARIABLE_SET, FIFO_SET, SOCKET_SET,
@@ -41,7 +42,10 @@ vsend_event(int type, const gchar *custom_event, va_list vargs);
void
send_event(int type, const gchar *custom_event, ...) G_GNUC_NULL_TERMINATED;
+gchar *
+get_modifier_mask(guint state);
+
void
-key_to_event(guint keyval, gint mode);
+key_to_event(guint keyval, guint state, guint is_modifier, int mode);
#endif
diff --git a/src/uzbl-core.c b/src/uzbl-core.c
index 6ea54a9..56d2f86 100644
--- a/src/uzbl-core.c
+++ b/src/uzbl-core.c
@@ -47,12 +47,15 @@ GOptionEntry entries[] = {
"Uri to load at startup (equivalent to 'uzbl <uri>' or 'set uri = URI' after uzbl has launched)", "URI" },
{ "verbose", 'v', 0, G_OPTION_ARG_NONE, &uzbl.state.verbose,
"Whether to print all messages or just errors.", NULL },
- { "name", 'n', 0, G_OPTION_ARG_STRING, &uzbl.state.instance_name,
+ { "named", 'n', 0, G_OPTION_ARG_STRING, &uzbl.state.instance_name,
"Name of the current instance (defaults to Xorg window id or random for GtkSocket mode)", "NAME" },
{ "config", 'c', 0, G_OPTION_ARG_STRING, &uzbl.state.config_file,
"Path to config file or '-' for stdin", "FILE" },
+ /* TODO: explain the difference between these two options */
{ "socket", 's', 0, G_OPTION_ARG_INT, &uzbl.state.socket_id,
- "Xembed Socket ID", "SOCKET" },
+ "Xembed socket ID, this window should embed itself", "SOCKET" },
+ { "embed", 'e', 0, G_OPTION_ARG_NONE, &uzbl.state.embed,
+ "Whether this window should expect to be embedded", NULL },
{ "connect-socket", 0, 0, G_OPTION_ARG_STRING_ARRAY, &uzbl.state.connect_socket_names,
"Connect to server socket for event managing", "CSOCKET" },
{ "print-events", 'p', 0, G_OPTION_ARG_NONE, &uzbl.state.events_stdout,
@@ -546,7 +549,9 @@ CommandInfo cmdlist[] =
{ "include", include, TRUE },
{ "show_inspector", show_inspector, 0 },
{ "add_cookie", add_cookie, 0 },
- { "delete_cookie", delete_cookie, 0 }
+ { "delete_cookie", delete_cookie, 0 },
+ { "clear_cookies", clear_cookies, 0 },
+ { "download", download, 0 }
};
void
@@ -720,6 +725,42 @@ delete_cookie(WebKitWebView *page, GArray *argv, GString *result) {
uzbl.net.soup_cookie_jar->in_manual_add = 0;
}
+
+void
+clear_cookies(WebKitWebView *page, GArray *argv, GString *result) {
+ (void) page; (void) argv; (void) result;
+
+ // Replace the current cookie jar with a new empty jar
+ soup_session_remove_feature (uzbl.net.soup_session,
+ SOUP_SESSION_FEATURE (uzbl.net.soup_cookie_jar));
+ g_object_unref (G_OBJECT (uzbl.net.soup_cookie_jar));
+ uzbl.net.soup_cookie_jar = uzbl_cookie_jar_new ();
+ soup_session_add_feature(uzbl.net.soup_session,
+ SOUP_SESSION_FEATURE (uzbl.net.soup_cookie_jar));
+}
+
+void
+download(WebKitWebView *web_view, GArray *argv, GString *result) {
+ (void) result;
+
+ const gchar *uri = argv_idx(argv, 0);
+ const gchar *destination = NULL;
+ if(argv->len > 1)
+ destination = argv_idx(argv, 1);
+
+ WebKitNetworkRequest *req = webkit_network_request_new(uri);
+ WebKitDownload *download = webkit_download_new(req);
+
+ download_cb(web_view, download, destination);
+
+ if(webkit_download_get_destination_uri(download))
+ webkit_download_start(download);
+ else
+ g_object_unref(download);
+
+ g_object_unref(req);
+}
+
void
act_dump_config() {
dump_config();
@@ -1111,8 +1152,6 @@ spawn_sh_sync(WebKitWebView *web_view, GArray *argv, GString *result) {
void
run_parsed_command(const CommandInfo *c, GArray *a, GString *result) {
- c->function(uzbl.gui.web_view, a, result);
-
/* send the COMMAND_EXECUTED event, except for set and event/request commands */
if(strcmp("set", c->key) &&
strcmp("event", c->key) &&
@@ -1123,12 +1162,18 @@ run_parsed_command(const CommandInfo *c, GArray *a, GString *result) {
guint i = 0;
while ((p = argv_idx(a, i++)))
g_string_append_printf(param, " '%s'", p);
+
+ /* might be destructive on array a */
+ c->function(uzbl.gui.web_view, a, result);
+
send_event(COMMAND_EXECUTED, NULL,
TYPE_NAME, c->key,
TYPE_FORMATTEDSTR, param->str,
NULL);
g_string_free(param, TRUE);
}
+ else
+ c->function(uzbl.gui.web_view, a, result);
if(result) {
g_free(uzbl.state.last_result);
@@ -1498,6 +1543,7 @@ create_window() {
GtkPlug*
create_plug() {
+ if(uzbl.state.embed) uzbl.state.socket_id = 0;
GtkPlug* plug = GTK_PLUG (gtk_plug_new (uzbl.state.socket_id));
g_signal_connect (G_OBJECT (plug), "destroy", G_CALLBACK (destroy_cb), NULL);
g_signal_connect (G_OBJECT (plug), "key-press-event", G_CALLBACK (key_press_cb), NULL);
@@ -1682,7 +1728,7 @@ initialize(int argc, char** argv) {
}
/* Embedded mode */
- if (uzbl.state.socket_id)
+ if (uzbl.state.socket_id || uzbl.state.embed)
uzbl.state.plug_mode = TRUE;
if (!g_thread_supported())
diff --git a/src/uzbl-core.h b/src/uzbl-core.h
index d8f8375..3fde5dc 100644
--- a/src/uzbl-core.h
+++ b/src/uzbl-core.h
@@ -107,6 +107,7 @@ typedef struct {
gchar* executable_path;
gchar* searchtx;
gboolean verbose;
+ gboolean embed;
GdkEventButton* last_button;
gchar* last_result;
gboolean plug_mode;
@@ -301,9 +302,6 @@ void handle_authentication (SoupSession *session,
SoupAuth *auth,
gboolean retrying,
gpointer user_data);
-void handle_cookies (SoupSession *session,
- SoupMessage *msg,
- gpointer user_data);
gboolean valid_name(const gchar* name);
void set_var(WebKitWebView *page, GArray *argv, GString *result);
void act_dump_config();
@@ -324,6 +322,8 @@ void include(WebKitWebView *page, GArray *argv, GString *result);
void show_inspector(WebKitWebView *page, GArray *argv, GString *result);
void add_cookie(WebKitWebView *page, GArray *argv, GString *result);
void delete_cookie(WebKitWebView *page, GArray *argv, GString *result);
+void clear_cookies(WebKitWebView *pag, GArray *argv, GString *result);
+void download(WebKitWebView *pag, GArray *argv, GString *result);
void builtins();
typedef void (*Command)(WebKitWebView*, GArray *argv, GString *result);