aboutsummaryrefslogtreecommitdiff
path: root/config.dot/luakit.link/webview.lua
diff options
context:
space:
mode:
authorSilvio Rhatto <rhatto@riseup.net>2017-09-21 21:39:54 -0300
committerSilvio Rhatto <rhatto@riseup.net>2017-09-21 21:39:54 -0300
commitfc24ecca542a10deefc789342f373e8d6a4a43cb (patch)
treef3e11c3a14e156a145778c200219c86058e9805c /config.dot/luakit.link/webview.lua
parent562adce657add8aaf2c80597fc54fa0a906c2287 (diff)
downloadluakit-fc24ecca542a10deefc789342f373e8d6a4a43cb.tar.gz
luakit-fc24ecca542a10deefc789342f373e8d6a4a43cb.tar.bz2
Stable config
Diffstat (limited to 'config.dot/luakit.link/webview.lua')
-rw-r--r--config.dot/luakit.link/webview.lua360
1 files changed, 360 insertions, 0 deletions
diff --git a/config.dot/luakit.link/webview.lua b/config.dot/luakit.link/webview.lua
new file mode 100644
index 0000000..e3fbfe6
--- /dev/null
+++ b/config.dot/luakit.link/webview.lua
@@ -0,0 +1,360 @@
+--------------------------
+-- WebKit WebView class --
+--------------------------
+
+local window = require("window")
+local lousy = require("lousy")
+local globals = require("globals")
+
+-- Webview class table
+local webview = {}
+
+lousy.signal.setup(webview, true)
+
+local web_module = require_web_module("webview_wm")
+
+web_module:add_signal("form-active", function (_, page_id)
+ for _, w in pairs(window.bywidget) do
+ if w.view.id == page_id then
+ w.view:emit_signal("form-active")
+ end
+ end
+end)
+
+web_module:add_signal("navigate", function (_, page_id, uri)
+ msg.verbose("Got luakit:// -> file:// navigation: %s", uri)
+ for _, w in pairs(window.bywidget) do
+ if w.view.id == page_id then w.view.uri = uri end
+ end
+end)
+
+local webview_state = setmetatable({}, { __mode = "k" })
+
+-- Table of functions which are called on new webview widgets.
+local init_funcs = {
+ -- Set useragent
+ set_useragent = function (view)
+ view.user_agent = globals.useragent
+ end,
+
+ -- Update window and tab titles
+ title_update = function (view)
+ view:add_signal("property::title", function (v)
+ local w = webview.window(v)
+ if w and w.view == v then
+ w:update_win_title()
+ end
+ end)
+ end,
+
+ -- Clicking a form field automatically enters insert mode.
+ form_insert_mode = function (view)
+ -- Emit root-active event in button release to prevent "missing"
+ -- buttons or links when the input bar hides.
+ view:add_signal("button-press", function (v, _, button, context)
+ if button == 1 then
+ v:emit_signal(context.editable and "form-active" or "root-active")
+ end
+ end)
+ view:add_signal("form-active", function (v)
+ local w = webview.window(v)
+ if not w.mode.passthrough then
+ w:set_mode("insert")
+ end
+ end)
+ view:add_signal("root-active", function (v)
+ local w = webview.window(v)
+ if w.mode.reset_on_focus ~= false then
+ w:set_mode()
+ end
+ end)
+ view:add_signal("load-status", function (v, status, _, err)
+ if status == "finished" or (status == "failed" and err == "Load request cancelled") then
+ web_module:emit_signal(v, "load-finished")
+ end
+ end)
+ end,
+
+ -- Try to match a button event to a users button binding else let the
+ -- press hit the webview.
+ button_bind_match = function (view)
+ view:add_signal("button-release", function (v, mods, button, context)
+ local w = webview.window(v)
+ if w:hit(mods, button, { context = context }) then
+ return true
+ end
+ end)
+ end,
+
+ -- Reset the mode on navigation
+ mode_reset_on_nav = function (view)
+ view:add_signal("load-status", function (v, status)
+ local w = webview.window(v)
+ if status == "provisional" and w and w.view == v then
+ if w.mode.reset_on_navigation ~= false then
+ w:set_mode()
+ end
+ end
+ end)
+ end,
+
+ -- Action to take on mime type decision request.
+ mime_decision = function (view)
+ -- Return true to accept or false to reject from this signal.
+ view:add_signal("mime-type-decision", function (_, uri, mime)
+ msg.info("Requested link: %s (%s)", uri, mime)
+ -- i.e. block binary files like *.exe
+ --if mime == "application/octet-stream" then
+ -- return false
+ --end
+ end)
+ end,
+
+ -- Action to take on window open request.
+ --window_decision = function (view, w)
+ -- view:add_signal("new-window-decision", function (v, uri, reason)
+ -- if reason == "link-clicked" then
+ -- window.new({uri})
+ -- else
+ -- w:new_tab(uri)
+ -- end
+ -- return true
+ -- end)
+ --end,
+
+ create_webview = function (view)
+ -- Return a newly created webview in a new tab
+ view:add_signal("create-web-view", function (v)
+ return webview.window(v):new_tab(nil, { private = v.private })
+ end)
+ end,
+
+ popup_fix_open_link_label = function (view)
+ view:add_signal("populate-popup", function (_, menu)
+ for _, item in ipairs(menu) do
+ if type(item) == "table" then
+ -- Optional underscore represents alt-key shortcut letter
+ item[1] = string.gsub(item[1], "New (_?)Window", "New %1Tab")
+ end
+ end
+ end)
+ end,
+}
+
+-- These methods are present when you index a window instance and no window
+-- method is found in `window.methods`. The window then checks if there is an
+-- active webview and calls the following methods with the given view instance
+-- as the first argument. All methods must take `view` & `w` as the first two
+-- arguments.
+webview.methods = {
+ -- Reload with or without ignoring cache
+ reload = function (view, _, bypass_cache)
+ if bypass_cache then
+ view:reload_bypass_cache()
+ else
+ view:reload()
+ end
+ end,
+
+ -- Toggle source view
+ toggle_source = function (view, _, show)
+ if show == nil then
+ view.view_source = not view.view_source
+ else
+ view.view_source = show
+ end
+ view:reload()
+ end,
+
+ -- Zoom functions
+ zoom_in = function (view, _, step)
+ step = step or globals.zoom_step or 0.1
+ view.zoom_level = view.zoom_level + step
+ end,
+
+ zoom_out = function (view, _, step)
+ step = step or globals.zoom_step or 0.1
+ view.zoom_level = math.max(0.01, view.zoom_level) - step
+ end,
+
+ zoom_set = function (view, _, level)
+ view.zoom_level = level or 1.0
+ end,
+
+ -- History traversing functions
+ back = function (view, _, n)
+ view:go_back(n or 1)
+ view:emit_signal("go-back-forward", -(n or 1))
+ end,
+
+ forward = function (view, _, n)
+ view:go_forward(n or 1)
+ view:emit_signal("go-back-forward", (n or 1))
+ end,
+}
+
+function webview.methods.scroll(view, w, new)
+ local s = view.scroll
+ for _, axis in ipairs{ "x", "y" } do
+ -- Relative px movement
+ if rawget(new, axis.."rel") then
+ s[axis] = s[axis] + new[axis.."rel"]
+
+ -- Relative page movement
+ elseif rawget(new, axis .. "pagerel") then
+ s[axis] = s[axis] + math.ceil(s[axis.."page_size"] * new[axis.."pagerel"])
+
+ -- Absolute px movement
+ elseif rawget(new, axis) then
+ local n = new[axis]
+ if n == -1 then
+ local dir = axis == "x" and "Width" or "Height"
+ local js = string.format([=[
+ Math.max(window.document.documentElement.scroll%s - window.inner%s, 0)
+ ]=], dir, dir)
+ w.view:eval_js(js, { callback = function (max)
+ s[axis] = max
+ end})
+ else
+ s[axis] = n
+ end
+
+ -- Absolute page movement
+ elseif rawget(new, axis.."page") then
+ s[axis] = math.ceil(s[axis.."page_size"] * new[axis.."page"])
+
+ -- Absolute percent movement
+ elseif rawget(new, axis .. "pct") then
+ local dir = axis == "x" and "Width" or "Height"
+ local js = string.format([=[
+ Math.max(window.document.documentElement.scroll%s - window.inner%s, 0)
+ ]=], dir, dir)
+ w.view:eval_js(js, { callback = function (max)
+ s[axis] = math.ceil(max * (new[axis.."pct"]/100))
+ end})
+ end
+ end
+end
+
+local wrap_widget_metatable
+do
+ local wrapped = false
+ wrap_widget_metatable = function (view)
+ if wrapped then return end
+ wrapped = true
+
+ local mt = getmetatable(view)
+ local oi = mt.__index
+ mt.__index = function (w, k)
+ if (k == "uri" or k == "session_state") and oi(w, "type") == "webview" then
+ local ws = webview_state[w]
+ if not next(ws.blockers) then return oi(w, k) end
+ local ql = ws.queued_location or {}
+ if k == "uri" then
+ return ql.uri or oi(w, k)
+ end
+ if k == "session_state" then
+ return ql.session_state or oi(w, k)
+ end
+ end
+ return oi(w, k)
+ end
+ end
+end
+
+function webview.new(opts)
+ assert(opts)
+ local view = widget{type = "webview", private = opts.private}
+
+ webview_state[view] = { blockers = {} }
+ wrap_widget_metatable(view)
+
+ -- Call webview init functions
+ for _, func in pairs(init_funcs) do
+ func(view)
+ end
+ webview.emit_signal("init", view)
+
+ return view
+end
+
+luakit.idle_add(function ()
+ local undoclose = package.loaded.undoclose
+ if not undoclose then return end
+ undoclose.add_signal("save", function (view)
+ if view.private then return false end
+ end)
+end)
+
+function webview.window(view)
+ assert(type(view) == "widget" and view.type == "webview")
+ return window.ancestor(view)
+end
+
+function webview.modify_load_block(view, name, enable)
+ assert(type(view) == "widget" and view.type == "webview")
+ assert(type(name) == "string")
+
+ local ws = webview_state[view]
+ ws.blockers[name] = enable and true or nil
+ msg.verbose("%s %s %s", view, name, enable and "block" or "unblock")
+
+ if not next(ws.blockers) and ws.queued_location then
+ msg.verbose("fully unblocked %s", view)
+ local queued = ws.queued_location
+ ws.queued_location = nil
+ webview.set_location(view, queued)
+ end
+end
+
+function webview.set_location(view, arg)
+ assert(type(view) == "widget" and view.type == "webview")
+ assert(type(arg) == "string" or type(arg) == "table")
+
+ -- Always execute JS URIs immediately, even when webview is blocked
+ if type(arg) == "string" and arg:match("^javascript:") then
+ local js = string.match(arg, "^javascript:(.+)$")
+ return view:eval_js(luakit.uri_decode(js))
+ end
+
+ if type(arg) == "string" then arg = { uri = arg } end
+ assert(arg.uri or arg.session_state)
+
+ local ws = webview_state[view]
+ if next(ws.blockers) then
+ ws.queued_location = arg
+ if arg.uri then view:emit_signal("property::uri") end
+ return
+ end
+
+ if arg.session_state then
+ view.session_state = arg.session_state
+ if view.uri == "about:blank" and arg.uri then
+ view.uri = arg.uri
+ end
+ else
+ view.uri = arg.uri
+ end
+end
+
+-- Insert webview method lookup on window structure
+table.insert(window.indexes, 1, function (w, k)
+ if k == "view" then
+ local view = w.tabs[w.tabs:current()]
+ if view and type(view) == "widget" and view.type == "webview" then
+ w.view = view
+ return view
+ end
+ end
+ -- Lookup webview method
+ local func = webview.methods[k]
+ if not func then return end
+ local view = w.view
+ if view then
+ return function (_, ...) return func(view, w, ...) end
+ end
+end)
+
+return webview
+
+-- vim: et:sw=4:ts=8:sts=4:tw=80