Simon Lydell [Wed, 16 Mar 2016 18:26:07 +0000 (19:26 +0100)]
Fix text input focus issues in non-multi-process
Sometimes when focusing text inputs, it wouldn't really be focused and VimFx
wouldn't recognize it as editable. This was because of commit 33d1fdeb, where I
somehow looked for the 'context' attribute instead of the 'contextmenu'
attribute.
Simon Lydell [Sun, 13 Mar 2016 11:55:49 +0000 (12:55 +0100)]
Disallow old version of VimFx to communicate with new version
Commit 865fdaba attempted to fix an issue where frame script message listeners
from the old version of VimFx wasn't shut down properly when VimFx was updated.
Since then, the problem has become very rare, but unfortunately still happens
occasionally. I really have no idea why it can still happen. It might even be
that there's nothing that can be done due to the way Firefox works.
This commit tries to make any leftover frame script message listeners useless,
by adding the `BUILD_TIME` in all message names.
Simon Lydell [Sun, 13 Mar 2016 08:13:31 +0000 (09:13 +0100)]
Simplify and improve Find mode auto-enter and -exit
In rare circumstances I've found that if you enter Find mode (via the `/`
command) very quickly after just having opened a new foreground tab which loads
a bit slowly, you could sometimes end up with the findbar focused but still in
Normal mode. This should no longer happen.
Simon Lydell [Wed, 9 Mar 2016 06:43:55 +0000 (07:43 +0100)]
Clarify the blacklist option
- Improve wording in the Add-ons Manager. Explicitly say that the list is space
separated, since several users had problems with that.
- Add default example blacklist patterns. It's much easier to adapt an example
than to write something from scratch (or copy-paste). The default patterns are
for example.com and example.org which are reserved for documentation purposes,
so it doesn't matter that those get blacklisted by default.
Simon Lydell [Mon, 7 Mar 2016 08:14:28 +0000 (09:14 +0100)]
Improve click simulation
- Don't leak 'command' events to web pages. They're only needed for XUL.
- Don't generate 'mousedown' and 'mouseup' when simlating clicks for browser UI
elements. They seem to sometimes trigger some buttons' actions twice. It also
caused background tabs to be selected before closed when clicking on their
close button, which caused the selected tab to change. However, an exception
had to be made for tabs. 'mousedown' seems to be the only relevant event
there.
Simon Lydell [Sun, 6 Mar 2016 19:35:25 +0000 (20:35 +0100)]
Improve `Cu.import`s
- Fixed two cases where things were accidentally imported into the global scope.
- Consistenly prefer the explicit `{a, b} = Cu.import('...', {})` style, rather
than the implicit import-all-into-global-scope `Cu.import('...')` style.
Simon Lydell [Sat, 5 Mar 2016 14:33:32 +0000 (15:33 +0100)]
Let `gL` deal with unvisited tabs instead of unread ones
Firefox considers a tab to be "unread" if it finishes loading in the background.
This means that if the current tab is loading, but very slowly, and you
therefore switch to another tab while waiting for it to finish, you can't use
`gl` to go back to the slowly-loading tab when it's done, because then it would
be marked as "unread", forcing you to use `gL` instead. This often tripped me
up.
This commit uses the notion of "unvisited" instead of "unread". This works much
better.
Simon Lydell [Sat, 5 Mar 2016 12:59:01 +0000 (13:59 +0100)]
Fix `gi` after searching issues on github
After searching for issues on github, the search input gets removed from the DOM
and replaced with a new one. This means that the last focused text input is no
longer on the page, but `gi` still tried to focus it. This commit checks that
the last focused element really is present in the DOM first.
Simon Lydell [Sat, 5 Mar 2016 12:29:52 +0000 (13:29 +0100)]
Fix focusType after searching issues on github
When searching for issues on github, the results are fetched with AJAX and then
inserted into the page. More accurately, the fetched content _replaces_ already
existing content on the page, including the search input. It turns out that
neither 'focus' nor 'blur' events are fired when a focused text input is removed
from the DOM (even though that actually blurs it and focuses `<body>`). This
caused VimFx to believe that the text input was still focused, which meant that
you had to press `<escape>` before you could use any VimFx commands. Using a
`MutationObserver`, this commit temporarily observes the currently focused
element (unless `focusType == 'none'`, because that's unnecessary and might
degrade performance). If the element gets removed, the current `focusType` is
updated, fixing the problem.
To check if an element gets removed from the DOM requires observing the _entire_
document tree, recursively. The `utils.onRemoved` function did (wrongly) not do
that, so it had to be updated.
Because of the update to `utils.onRemoved`, this commit also removes the
`MutationObserver`s for scrollable elements. The reason they were added in the
first place was to try to reduce memory consumption by pruning the list of
scrollable elements from elements removed from the DOM. However, the observers
were buggy: They were only triggered if _only_ the scrollable element was
removed, not if one of its parents were removed. Since this "buggy" behavior has
been used for quite some time now and it hasn't caused any memory problems, one
can draw the conclusion that the observers are not needed. That's good, because
it means that there's no need to add observers for the entire document on
basically _every_ page.
Simon Lydell [Mon, 29 Feb 2016 12:50:48 +0000 (13:50 +0100)]
Harden the `f` commands
It sucks that you can't trust the DOM. It sucks that on rare occasions, pressing
`f` shows no hints, but still enters Hints mode, leaving a
“element.href.startsWith is not a function” (or similar) error in the browser
console.
This commit tries to harden against such cases, by never trusting DOM properties
or methods to exist and be of the correct type. CoffeeScripts `?` is awesome for
this.
Simon Lydell [Sun, 28 Feb 2016 15:55:23 +0000 (16:55 +0100)]
Streamline `vimfx.on` events
_Always_ pass an object with event-specific properties, instead of sometimes
passing data directly. This is more consistent, and more future-proof since it
allows passing additional data without breaking backwards compatibility.
Simon Lydell [Sun, 28 Feb 2016 15:24:41 +0000 (16:24 +0100)]
Simplify the `config_file_directory` pref
- Set it to a normal system path, and let Firefox add `file://` and handle
Windows paths.
- Expand path starting with `~/` or `~\` to the user's home directory.
Simon Lydell [Sat, 27 Feb 2016 16:39:30 +0000 (17:39 +0100)]
Fix mutation errors in some `f` commands
For example, `2f` is supposed to open the first link in a new background tab and
the second link in the current tab. However, both were opened in background tabs
due to accidental mutation.
Simon Lydell [Fri, 26 Feb 2016 14:17:42 +0000 (15:17 +0100)]
Only allow `<late>` in single-key shortcuts
Previously, it was allowed in any shortcut sequence, but it only made a
difference for the last character. It really only makes sense to use `<late>`
with singe-key shortcuts.
Simon Lydell [Fri, 26 Feb 2016 13:31:33 +0000 (14:31 +0100)]
Use `prefs.get` directly in events-frame.coffee
... instead of using `messageManager.get`. This avoids synchronous messages,
which is a good thing. It violates the nice principle of only using the parsed
options of the `vimfx` object, but it doesn't really matter right now since only
four prefs are used in events-frame.coffee and they need little to none parsing.
One could probably pass the entire `vimfx.options` object down to frame scripts
when they start up and send updates whenever it updates, but let's do that when
a need for it comes up.
Simon Lydell [Fri, 26 Feb 2016 08:55:14 +0000 (09:55 +0100)]
Save the focusType instead of getting it on every keydown
This is simpler and more efficient. Also, we were basically already storing the
current focusType, since the button uses it to grey out when a text is focused.
Config API changes:
- `match` objects no longer have a `focus` property. It has been replaced with
the `likelyConflict` property. (Theoretically a breaking change.)
- `vim.focusType` is now available and contains the current focus type.
- The `focusTypeChange` event now passes only the current `vim` object to
listeners, instead of an object of data. Use `vim.focusType` to get the new
focusType. (Theoretically a breaking change.)
> Fix "invokeListener is not a function" uncaught errors
The commit indeed solved the above problem, but apparently replaced it with
another. When `invokeListener` has been `null`ed out, a copy of it can try to
reference things that also have been `null`ed out. So instead of storing copies
of it, we now check if the function exists before calling it. Otherwise, simply
do nothing. This commit also applies this to _all_ places `invokeListener` is
used.
Simon Lydell [Wed, 24 Feb 2016 12:29:13 +0000 (13:29 +0100)]
Improve Ignore mode and the blacklist
When you reloaded the page or visited some other page in the same time while in
Ignore mode, you'd always end up in Normal mode (unless the newly loaded page
was blacklisted). Now, you stay in Ignore mode in that case. This lets you press
`i` and browse around in that tab in Ignore mode, without having to press `i`
again any time a full page reload is caused.
However, if Ignore mode was entered automatically because of the blacklist, it
is also exited as expected if you browse to a non-blacklisted page.
This new behavior is possible by tracking the "type" of the Ignore mode. There
are currently two types, 'explicit' and 'blacklist', which correspond to the
above two cases.
Simon Lydell [Wed, 24 Feb 2016 07:03:39 +0000 (08:03 +0100)]
Fix issues when updating VimFx
After having updated VimFx, trying to use the `f` command on toggle buttons
often failed. This was because the frame script message listeners from the old
version wasn't shut down properly, which resulted in there being _two_ listeners
for the message to simulate a click on an element. The effects of this was
especially noticeable on toggle buttons, because clicking a toggle button twice
is a no-op. That gave the impression of VimFx failing to simulate a click at
all.
I think this erraneous shutdown behavior must have been introduced in commit 24b701e9, which switched from a synchronous message passing to an asynchronous
one in bootstrap.coffee. Previously, the shutdown message listener for frame
scripts had to be added after a timeout. Since mentioned commit, that timeout is
added in the response callback for the mentioned asynchronous message, which
should make the timeout unnecessary, but the timeout was still kept in that
commit. It shouldn't matter, but somehow it does. Removing the timeout fixes the
double message listeners problem, and does not seem to re-introduce the problems
that were fixed be adding the timeout in the first place (commit ec3a4394).
Simon Lydell [Tue, 23 Feb 2016 08:13:46 +0000 (09:13 +0100)]
Fix `@popupPassThrough` for menus in frames
When a menu, such as a context menu is open, VimFx is automatically disabled to
allow using the access keys of the open menu, as well as pressing `<escape>` to
close the menu. However, this used not to work for the context menus in the
devtools and in about:config. Now it does.
This also fixes a bug where VimFx stopped being automatically disabled after
closing a sub-menu of a context menu.
Simon Lydell [Tue, 23 Feb 2016 07:54:42 +0000 (08:54 +0100)]
Treat everything in the devtools as adjustable
Many things in the devtools can be "adjusted" with the arrow keys. For example,
if you `console.log` an object you can click it to get an interactive inspection
tree of that object. The tree can be navigated using the arrow keys, but not if
you, for example, use the arrow keys for VimFx's scrolling commands. With this
commit, that is no longer a problem.
Simon Lydell [Sun, 21 Feb 2016 14:35:12 +0000 (15:35 +0100)]
Replace element `instanceof` checks with `.localName`
KISS.
Note: `instanceof` checks are still often useful for XUL elements, because some
interfaces are extended by several elements.
Also note that `.localName` is used instead of `.nodeName` because many XUL
pages embed HTML elements. When mixing namespaces like that, the `.nodeName`s of
HTML elements will start with `html:`, while `.localName` skips the prefix.
`.localName` also nicely always returns valid HTML node names in lowercase.
Simon Lydell [Mon, 22 Feb 2016 18:29:26 +0000 (19:29 +0100)]
Split `gl` into `gl` and `gL`
`gl` selects the most recent tab. Simple, right? But what if you open a
background tab? Which is the most recent tab now? Or if you open several
background tabs?
Previously, if you opened several background tabs and then pressed `gl`, the
last opened new background tab would be selected. That behavior just happened to
be.
In my opinion, it is more consistent if `gl` always selects the last _visited_
tab. An unread background tab has _not_ been visited (yet). This commit makes
this change.
If there is only one visited tab (but possibly several unread tabs), a
notification is shown telling that there is no most recent tab.
The `gL` command selects the oldest unread tab. This is useful when having
opened a bunch of background tabs. `gL` then lets you step them through in the
order you opened them. (If there are no unread tabs, a notification is shown.)
In other words, `gl` deals with _visited_ tabs only (from now on), while `gL`
deals with _unread_ tabs only.
The motivation for this commit came from piroor/treestyletab#874.
Mentioned commit attempted to fix a problem where `vim.mode` could be
`undefined` in some `vimfx.on(...)` listeners. The button uses such an event
listener, and uses `vim.mode` in the key for a `translate(key)` call, which
caused `translate` to throw an error. This was because `vim.mode` wasn't set
until after a timeout. The fix was to emit the events after the same timeout.
However, the above solution is very unreliable, and the problem still slipped
through every now and then.
The reason the first timeout was added in the first place was to allow calling
`vimfx.getCurrentVim()` inside `vimfx.on(...)` listeners. This commit removes
both timeouts, while still preserving that behavior by splitting the contructor
of `Vim` into a new method, `._start`. This should be bullet-proof, less hacky
and faster.
Simon Lydell [Sun, 21 Feb 2016 14:05:49 +0000 (15:05 +0100)]
Add partial support for the wasavi extension
It's editor is now recognized as an editable element, but pressing `<escape>` in
its insert mode still blurs the editor instead of exiting its insert mode.
(`<escape>`) should ideally only blur in wasavi's normal mode.
- `element.style.zIndex`: Always string.
- `element.style.zIndex = value`: Turns `value` into a string.
- `a = '5'; a++`: `a` is now `6`.
- `element.style.zIndex++`: If the previous value was `'5'`, the new value is
`'6'`. This method was used before above commit.
- `element.style.zIndex += 1`: If the previous value was `'5'`, the new value is
`'51'`. This was introduced by above commit.
The above really shows that you should always be explicit about types. Since
`element.style.zIndex` is always a string, `element.style.zIndex++` was a
terrible hack that happened to work, but caused a bug when it was rewritten to
a seemingly equivalent expression.
This commit first reads the `z-index` of the element and explicitly makes it a
`Number`, allowing incrementing to work as expected.
Simon Lydell [Fri, 19 Feb 2016 06:55:41 +0000 (07:55 +0100)]
Reduce unnecessary vertical code alignment
While it may look nice many times, it causes annoying merge conflicts.
Especially aligning all `require(...)` calls has bitten me many times, since
adding or removing one often requires reformatting the entire block.
This commit attempts to remove vertical alignment (especially around `=`) for
the sake of smaller diffs and simpler merges.
Vertical alignment has been kept, though, where it really makes the code easier
to read and you're likely to edit all of the aligned lines anyway if changing
one of them. The most common example is code dealing with X and Y coordinates
and having to do the same thing to both of them. Only the words X, Y, left,
right, top, bottom, width, height etc. differ between the lines. It's easier to
see that they are really up-to-date with each other if the common parts are
aligned.
Simon Lydell [Thu, 28 Jan 2016 21:05:54 +0000 (22:05 +0100)]
Rework programmatic customization of VimFx
- The public API has been removed. While the idea of allowing other extensions
to extend VimFx is neat, I don't think it'll ever be used. KISS. As a
replacement, the config files have become more top-notch.
- The former public API is now the config file API.
- Config files are no longer regular add-ons. We used to provide a boilerplate
for such an add-on, which consisted of a bunch of files users most likely
wouldn't touch as well as `config.js` and `frame.js`. Now, the concept of
`config.js` and `frame.js` has been kept, but they are loaded directly, if the
path to their parent directory is given in the `config_file_directory` pref.
This is much easier and simpler, and does not require the user to install a
version of Firefox with the ability to install unsign add-ons (or having to go
through the hassle of actually signing the "config file add-on").
- `zr` reloads the config file(s). This is possible because of the above point
and is much nicer than having to restart Firefox every time you change your
config (or setting up something like the Extension Auto-Installer).
- `vimfx.send(...)` and `vimfx.listen(...)` have been added, to make it easier
to create custom commands that interact with web page content, which is quite
common. These are basically `messageManager.send` and `messageManager.listen`.
To make the API simpler, instead of passing the name of the callback message
to listeners and having to do `messageManager.send(callback, data)` to respond
to a message, a real callback _function_ is now passed instead, which does the
message sending behind the scenes. This also resulted in some nice code
cleanup overall.
- `vimfx.off(...)` has been added, to remove `vimfx.on(...)` listeners. This is
mostly used internally. Since `zr` allows reloading the config file,
everything in it must be undoable.
- By loading `frame.js` directly, it is now possible to pass a real API to it,
rather than relying on `VimFx*` properties on the global frame script object.
- The new, "real" frame script API now has tests. This involved adding support
for running tests in frame scripts.