From 109fd078f41a5b465042ffd132c06287caef4efd Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Sat, 13 May 2023 08:44:50 +0100 Subject: [PATCH] popcon: use E.stopEventPropagation() for the drag handler --- apps/widhid/README.md | 1 + apps/widhid/wid.js | 71 ++------------------------------- apps/widhid/wid.ts | 93 +++++-------------------------------------- 3 files changed, 14 insertions(+), 151 deletions(-) diff --git a/apps/widhid/README.md b/apps/widhid/README.md index 7651d74eb..652a2ed49 100644 --- a/apps/widhid/README.md +++ b/apps/widhid/README.md @@ -13,6 +13,7 @@ Swipe down to enable - note the icon changes from blue to orange, indicating it' All other watch interaction is disabled for 3 seconds, to prevent clashing taps/drags - this period is extended as you continue to alter the volume, play/pause and jump between tracks. +Requires espruino firmware > 2v17 to avoid event handler clashes. # Setup / Technical details diff --git a/apps/widhid/wid.js b/apps/widhid/wid.js index b361b6453..dd411513e 100644 --- a/apps/widhid/wid.js +++ b/apps/widhid/wid.js @@ -10,34 +10,14 @@ var dragging = false; var activeTimeout; var waitForRelease = true; - var mayInterceptSwipe = function () { - if (Bangle.CLKINFO_FOCUS) - return 0; - if (Bangle.CLOCK) - return 1; - var swipes = Bangle["#onswipe"]; - if (typeof swipes === "function") { - if (swipes !== onSwipe) - return swipes.length > 1; - } - else if (swipes) { - for (var _i = 0, swipes_1 = swipes; _i < swipes_1.length; _i++) { - var handler = swipes_1[_i]; - if (handler !== onSwipe && (handler === null || handler === void 0 ? void 0 : handler.length) > 1) - return 0; - } - } - if (Bangle["#ondrag"]) - return 0; - return 1; - }; var onSwipe = (function (_lr, ud) { - if (ud > 0 && !activeTimeout && mayInterceptSwipe()) { + if (ud > 0 && !activeTimeout && !Bangle.CLKINFO_FOCUS) { listen(); Bangle.buzz(20); } }); var onDrag = (function (e) { + E.stopEventPropagation && E.stopEventPropagation(); if (e.b === 0) { var wasDragging = dragging; dragging = false; @@ -99,9 +79,9 @@ var listen = function () { var wasActive = !!activeTimeout; if (!wasActive) { - suspendOthers(); waitForRelease = true; Bangle.on("drag", onDrag); + Bangle["#ondrag"] = [onDrag].concat(Bangle["#ondrag"].filter(function (f) { return f !== onDrag; })); redraw(); } if (activeTimeout) @@ -109,7 +89,6 @@ activeTimeout = setTimeout(function () { activeTimeout = undefined; Bangle.removeListener("drag", onDrag); - resumeOthers(); redraw(); }, 3000); }; @@ -148,48 +127,4 @@ var toggle = function () { return sendHid(0x10); }; var up = function () { return sendHid(0x40); }; var down = function () { return sendHid(0x80); }; - var touchEvents = { - tap: null, - gesture: null, - aiGesture: null, - swipe: null, - touch: null, - drag: null, - stroke: null, - }; - var suspendOthers = function () { - for (var event_ in touchEvents) { - var event = event_; - var handlers = Bangle["#on".concat(event)]; - if (!handlers) - continue; - var newEvents = void 0; - if (handlers instanceof Array) - newEvents = handlers.filter(function (f) { return f; }); - else - newEvents = [handlers]; - for (var _i = 0, newEvents_1 = newEvents; _i < newEvents_1.length; _i++) { - var handler = newEvents_1[_i]; - Bangle.removeListener(event, handler); - } - touchEvents[event] = newEvents; - } - }; - var resumeOthers = function () { - for (var event_ in touchEvents) { - var event = event_; - var handlers = touchEvents[event]; - touchEvents[event] = null; - if (handlers) - for (var _i = 0, handlers_1 = handlers; _i < handlers_1.length; _i++) { - var handler = handlers_1[_i]; - try { - Bangle.on(event, handler); - } - catch (e) { - console.log("couldn't restore \"".concat(event, "\" handler:"), e); - } - } - } - }; })(); diff --git a/apps/widhid/wid.ts b/apps/widhid/wid.ts index a85725569..3291c188d 100644 --- a/apps/widhid/wid.ts +++ b/apps/widhid/wid.ts @@ -1,9 +1,4 @@ (() => { - type BangleEventKeys = "tap" | "gesture" | "aiGesture" | "swipe" | "touch" | "drag" | "stroke"; - type BangleEvents = { - [key in BangleEventKeys as `#on${key}`]?: Handler | (Handler | undefined)[] - }; - const settings: Settings = require("Storage").readJSON("setting.json", true) || { HID: false } as Settings; if (settings.HID !== "kbmedia") { console.log("widhid: can't enable, HID setting isn't \"kbmedia\""); @@ -18,40 +13,18 @@ let activeTimeout: number | undefined; let waitForRelease = true; - // If the user shows a menu, we want to temporarily disable ourselves - // - // We could detect showing of a menu by overriding E.showMenu - // and to detect hiding of a menu, we hook setUI - // - // Perhaps easier to check Bangle.swipeHandler - set by setUI, - // called by E.showMenu - const mayInterceptSwipe = () => { - if((Bangle as BangleExt).CLKINFO_FOCUS) return 0; - if(Bangle.CLOCK) return 1; - - const swipes = (Bangle as BangleEvents)["#onswipe"]; - if(typeof swipes === "function"){ - if(swipes !== onSwipe) - return swipes.length > 1; // second argument is up/down - }else if(swipes){ - for(const handler of swipes) - if(handler !== onSwipe && handler?.length > 1) - return 0; - } - - if((Bangle as BangleEvents)["#ondrag"]) return 0; - return 1; - }; - const onSwipe = ((_lr, ud) => { // do these checks in order of cheapness - if(ud! > 0 && !activeTimeout && mayInterceptSwipe()){ + if(ud! > 0 && !activeTimeout && !(Bangle as BangleExt).CLKINFO_FOCUS){ listen(); Bangle.buzz(20); } }) satisfies SwipeCallback; const onDrag = (e => { + // Espruino/35c8cb9be11 + (E as any).stopEventPropagation && (E as any).stopEventPropagation(); + if(e.b === 0){ // released const wasDragging = dragging; @@ -108,9 +81,14 @@ const listen = () => { const wasActive = !!activeTimeout; if(!wasActive){ - suspendOthers(); waitForRelease = true; // wait for first touch up before accepting gestures + Bangle.on("drag", onDrag); + // move our drag to the start of the event listener array + (Bangle as any)["#ondrag"] = [onDrag].concat( + (Bangle as any)["#ondrag"].filter((f: unknown) => f !== onDrag) + ); + redraw(); } @@ -119,7 +97,6 @@ activeTimeout = undefined; Bangle.removeListener("drag", onDrag); - resumeOthers(); redraw(); }, 3000); @@ -174,54 +151,4 @@ const toggle = () => /*DEBUG ? console.log("toggle") : */ sendHid(0x10); const up = () => /*DEBUG ? console.log("up") : */ sendHid(0x40); const down = () => /*DEBUG ? console.log("down") : */ sendHid(0x80); - - // similarly to the lightswitch app, we tangle with the listener arrays to - // disable event handlers - type Handler = () => void; - const touchEvents: { - [key in BangleEventKeys]: null | Handler[] - } = { - tap: null, - gesture: null, - aiGesture: null, - swipe: null, - touch: null, - drag: null, - stroke: null, - }; - - const suspendOthers = () => { - for(const event_ in touchEvents){ - const event = event_ as BangleEventKeys; - const handlers = (Bangle as BangleEvents)[`#on${event}`]; - - if(!handlers) continue; - - let newEvents; - if(handlers instanceof Array) - newEvents = handlers.filter(f=>f) as Handler[]; - else - newEvents = [handlers /* single fn */]; - - for(const handler of newEvents) - Bangle.removeListener(event, handler); - - touchEvents[event] = newEvents; - } - }; - const resumeOthers = () => { - for(const event_ in touchEvents){ - const event = event_ as BangleEventKeys; - const handlers = touchEvents[event]; - touchEvents[event] = null; - - if(handlers) - for(const handler of handlers) - try{ - Bangle.on(event as any, handler); - }catch(e){ - console.log(`couldn't restore "${event}" handler:`, e); - } - } - }; })()