]> git.gir.st - VimFx.git/blob - extension/lib/main.coffee
WIP: workarounds
[VimFx.git] / extension / lib / main.coffee
1 # This file pulls in all the different parts of VimFx, initializes them, and
2 # stiches them together.
3
4 button = require('./button')
5 config = require('./config')
6 defaults = require('./defaults')
7 help = require('./help')
8 {applyMigrations} = require('./legacy')
9 MarkerContainer = require('./marker-container')
10 messageManager = require('./message-manager')
11 migrations = require('./migrations')
12 modes = require('./modes')
13 options = require('./options')
14 {parsePref} = require('./parse-prefs')
15 prefs = require('./prefs')
16 UIEventManager = require('./events')
17 utils = require('./utils')
18 VimFx = require('./vimfx')
19 # @if TESTS
20 test = require('../test/index')
21 # @endif
22
23 {AddonManager} = Cu.import('resource://gre/modules/AddonManager.jsm', {})
24
25 module.exports = (data, reason) ->
26 if 0 # TODO: check if workarounds necessary; move to better location; implement callbacks; localize
27 utils.showPopupNotification(
28 'vimfx-require-workaround',
29 'VimFx needs to apply some about:config changes to function properly',
30 {'label':'Apply automatically', 'accessKey': 'A', 'callback': ()=>{}},
31 [{'label':'See details', 'accessKey': 'S', 'callback': ()=>{}},
32 {'label':'Ignore', 'accessKey': 'I', 'callback': ()=>{}}]
33 )
34 # Set default prefs and apply migrations as early as possible.
35 prefs.default.init()
36 applyMigrations(migrations)
37
38 parsedOptions = {}
39 for pref of defaults.all_options
40 parsedOptions[pref] = parsePref(pref)
41 vimfx = new VimFx(modes, parsedOptions)
42 vimfx.id = data.id
43 vimfx.version = data.version
44 AddonManager.getAddonByID(vimfx.id).then( (info) -> vimfx.info = info )
45
46 utils.loadCss("#{ADDON_PATH}/skin/style.css")
47
48 options.observe(vimfx)
49
50 prefs.observe('', (pref) ->
51 if pref.startsWith('mode.') or pref.startsWith('custom.')
52 vimfx.createKeyTrees()
53 else if pref of defaults.all_options
54 value = parsePref(pref)
55 vimfx.options[pref] = value
56 )
57
58 button.injectButton(vimfx)
59
60 setWindowAttribute = (window, name, value) ->
61 window.document.documentElement.setAttribute("vimfx-#{name}", value)
62
63 onModeDisplayChange = (data) ->
64 window = data.vim?.window ? data.event.originalTarget.ownerGlobal
65
66 # The 'modeChange' event provides the `vim` object that changed mode, but
67 # it might not be the current `vim` anymore so always get the current one.
68 return unless vim = vimfx.getCurrentVim(window)
69
70 setWindowAttribute(window, 'mode', vim.mode)
71 vimfx.emit('modeDisplayChange', {vim})
72
73 vimfx.on('modeChange', onModeDisplayChange)
74 vimfx.on('TabSelect', onModeDisplayChange)
75
76 vimfx.on('focusTypeChange', ({vim}) ->
77 setWindowAttribute(vim.window, 'focus-type', vim.focusType)
78 )
79
80 # `config.load` sends a 'loadConfig' message to all frame scripts, but it is
81 # intenionally run _before_ the frame scripts are loaded. Even if it is run
82 # after the frame scripts have been `messageManager.load`ed, we cannot know
83 # when it is ready to receive messages. Instead, the frame scripts trigger
84 # their 'loadConfig' code manually.
85 config.load(vimfx)
86 vimfx.on('shutdown', -> messageManager.send('unloadConfig'))
87
88 # Since VimFx has its own Caret mode, it doesn’t make much sense having
89 # Firefox’s Caret mode always own, so make sure that it is disabled (or
90 # enabled if the user has chosen to explicitly have it always on.)
91 vimfx.resetCaretBrowsing()
92
93 module.onShutdown(->
94 # Make sure that users are not left with Firefox’s own Caret mode
95 # accidentally enabled.
96 vimfx.resetCaretBrowsing()
97
98 # Make sure to run the below lines in this order. The second line results in
99 # removing all message listeners in frame scripts, including the one for
100 # 'unloadConfig' (see above).
101 vimfx.emit('shutdown')
102 messageManager.send('shutdown')
103 )
104
105 windows = new WeakSet()
106 messageManager.listen('tabCreated', (data, callback, browser) ->
107 # Frame scripts are run in more places than we need. Tell those not to do
108 # anything.
109 unless browser.getAttribute('messagemanagergroup') == 'browsers'
110 callback(false)
111 return
112
113 window = browser.ownerGlobal
114 vimfx.addVim(browser)
115
116 unless windows.has(window)
117 windows.add(window)
118 eventManager = new UIEventManager(vimfx, window)
119 eventManager.addListeners(vimfx, window)
120 setWindowAttribute(window, 'mode', 'normal')
121 setWindowAttribute(window, 'focus-type', 'none')
122 module.onShutdown(->
123 MarkerContainer.remove(window)
124 help.removeHelp(window)
125 )
126
127 callback(true)
128 )
129
130 # For tabs not visited yet since a session restore (“pending” tabs), Firefox
131 # seems to not load the frame script immediately, but instead remember the URI
132 # and load it when the user eventually visits that tab. If VimFx is updated
133 # during that time this means that the below URI is saved several times, and
134 # will be loaded that many times. Therefore the URI is changed with each
135 # build, causing remembered URIs to point to non-existent files.
136 messageManager.load("#{ADDON_PATH}/content/bootstrap-frame-#{BUILD_TIME}.js")
137
138 # @if TESTS
139 runTests = true
140 messageManager.listen('runTests', (data, callback) ->
141 # Running the regular tests inside this callback means that there will be a
142 # `window` available for tests, if they need one.
143 test(vimfx) if runTests
144 callback(runTests)
145 runTests = false
146 )
147 # @endif
Imprint / Impressum