diff options
author | Brendan Taylor <whateley@gmail.com> | 2011-04-30 08:17:40 -0600 |
---|---|---|
committer | Brendan Taylor <whateley@gmail.com> | 2011-04-30 08:17:40 -0600 |
commit | ceeba25242492db44091a4c87b046a25527d2f59 (patch) | |
tree | 5687dda2e9847b28ba48974d5246654eca281311 | |
parent | b0d2559157d0b060e2a2c2c33f08bed5f9cfaf51 (diff) | |
parent | cd7ff839afd2af2ec78868d91eca7fd4a2d4f117 (diff) |
Merge branch 'experimental' into scrollbars
39 files changed, 788 insertions, 741 deletions
@@ -1,6 +1,8 @@ uzbl-core *.o +*.lo *.pyc +*.sw[a-z] *~ tags -uzbl-cookie-manager +sandbox @@ -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> @@ -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: @@ -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); |