Last active
July 14, 2024 13:47
-
-
Save cxx/7f3cbd24745fffae34fbcdfdae0a76a1 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name Presto Gestures | |
// @namespace https://x.com/cxx | |
// @version 0.1.2 | |
// @description Opera-like mouse gestures with middle mouse button instead of right | |
// @match *://*/* | |
// @grant GM_openInTab | |
// @grant window.close | |
// ==/UserScript== | |
(function() { | |
"use strict"; | |
const BTN_LEFT_MASK = 1; | |
const BTN_RIGHT_MASK = 2; | |
const BTN_MIDDLE_MASK = 4; | |
const BTN_BACK_MASK = 8; | |
const BTN_FORWARD_MASK = 16; | |
let gestureButtons = BTN_MIDDLE_MASK; | |
let threshold = 50; | |
let gestures = [ | |
{ gesture: "L", action: () => history.back() }, | |
{ gesture: "R", action: () => history.forward() }, | |
{ gesture: "UL", action: goToParentDirectory }, | |
{ gesture: "UD", action: () => location.reload() }, | |
{ gesture: "U", action: () => stop() }, | |
{ gesture: "D", action: () => GM_openInTab("about:newtab", false) }, | |
{ gesture: "DU", action: () => GM_openInTab(location.toString()) }, | |
{ gesture: "DR", action: () => close() } | |
]; | |
function goToParentDirectory() { | |
const url = new URL(location.toString()); | |
url.pathname = url.pathname.replace(/[^/]*\/?$/, ""); | |
url.search = ""; | |
url.hash = ""; | |
location.assign(url.toString()); | |
} | |
function initGesture(x, y) { | |
start = { x: x, y: y }; | |
strokes = ""; | |
} | |
function updateGesture(x, y) { | |
let direction; | |
const dx = x - start.x; | |
const dy = y - start.y; | |
if (Math.abs(dx) > Math.abs(dy)) | |
direction = (dx < 0) ? "L" : "R"; | |
else | |
direction = (dy < 0) ? "U" : "D"; | |
if (strokes.endsWith(direction)) | |
start = { x: x, y: y }; | |
else if (Math.abs(dx) > threshold || Math.abs(dy) > threshold) { | |
start = { x: x, y: y }; | |
strokes += direction; | |
} | |
} | |
function endGesture() { | |
const found = gestures.find((item) => item.gesture == strokes); | |
if (found) | |
found.action(); | |
start = null; | |
strokes = ""; | |
} | |
let start = null; | |
let strokes = ""; | |
addEventListener("mousedown", (event) => { | |
if (event.buttons == gestureButtons) | |
initGesture(event.clientX, event.clientY); | |
}); | |
addEventListener("mousemove", (event) => { | |
if (start) | |
updateGesture(event.clientX, event.clientY); | |
}); | |
addEventListener("mouseup", (event) => { | |
if (strokes.length > 0) { | |
event.preventDefault(); | |
event.stopPropagation(); | |
} | |
}, true); | |
addEventListener("auxclick", (event) => { | |
if (strokes.length > 0) { | |
event.preventDefault(); | |
event.stopPropagation(); | |
} | |
endGesture(); | |
}, true); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment