From 895f649ef1c02eb1477d44acb0ffb7da096c4e37 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Fri, 15 Mar 2024 14:01:37 +0100 Subject: [PATCH] :bug: Stop drag events when the user focus out the application --- .../app/main/data/workspace/drawing/box.cljs | 8 +------ .../main/data/workspace/drawing/curve.cljs | 19 ++++++---------- .../app/main/data/workspace/interactions.cljs | 8 ++----- .../app/main/data/workspace/path/drawing.cljs | 12 +++------- .../app/main/data/workspace/path/edition.cljs | 8 ++----- .../main/data/workspace/path/selection.cljs | 13 +++-------- .../app/main/data/workspace/path/streams.cljs | 4 +--- .../app/main/data/workspace/selection.cljs | 13 ++++------- .../app/main/data/workspace/transforms.cljs | 19 ++++------------ .../app/main/ui/workspace/viewport/hooks.cljs | 7 ++++-- frontend/src/app/util/mouse.cljs | 22 ++++++++++++++++++- 11 files changed, 53 insertions(+), 80 deletions(-) diff --git a/frontend/src/app/main/data/workspace/drawing/box.cljs b/frontend/src/app/main/data/workspace/drawing/box.cljs index 76a6c3ce8..a595a8c3f 100644 --- a/frontend/src/app/main/data/workspace/drawing/box.cljs +++ b/frontend/src/app/main/data/workspace/drawing/box.cljs @@ -78,13 +78,7 @@ (ptk/reify ::handle-drawing ptk/WatchEvent (watch [_ state stream] - (let [stopper (rx/merge - (->> stream - (rx/filter mse/mouse-event?) - (rx/filter mse/mouse-up-event?)) - (->> stream - (rx/filter #(= % :interrupt)))) - + (let [stopper (mse/drag-stopper stream) layout (get state :workspace-layout) zoom (dm/get-in state [:workspace-local :zoom] 1) diff --git a/frontend/src/app/main/data/workspace/drawing/curve.cljs b/frontend/src/app/main/data/workspace/drawing/curve.cljs index 8a2194962..5c0d98898 100644 --- a/frontend/src/app/main/data/workspace/drawing/curve.cljs +++ b/frontend/src/app/main/data/workspace/drawing/curve.cljs @@ -28,11 +28,6 @@ (def simplify-tolerance 0.3) -(defn stopper-event? - [{:keys [type] :as event}] - (and (mse/mouse-event? event) - (= type :up))) - (defn- insert-point [point] (ptk/reify ::insert-point @@ -104,13 +99,13 @@ (ptk/reify ::handle-drawing ptk/WatchEvent (watch [_ _ stream] - (let [stopper (rx/filter stopper-event? stream) - mouse (rx/sample 10 ms/mouse-position) - shape (cts/setup-shape {:type :path - :initialized? true - :frame-id uuid/zero - :parent-id uuid/zero - :segments []})] + (let [stopper (mse/drag-stopper stream) + mouse (rx/sample 10 ms/mouse-position) + shape (cts/setup-shape {:type :path + :initialized? true + :frame-id uuid/zero + :parent-id uuid/zero + :segments []})] (rx/concat (rx/of #(update % :workspace-drawing assoc :object shape)) (->> mouse diff --git a/frontend/src/app/main/data/workspace/interactions.cljs b/frontend/src/app/main/data/workspace/interactions.cljs index 5708ca3c4..1aad31f2f 100644 --- a/frontend/src/app/main/data/workspace/interactions.cljs +++ b/frontend/src/app/main/data/workspace/interactions.cljs @@ -193,9 +193,7 @@ (watch [_ state stream] (let [initial-pos @ms/mouse-position selected (wsh/lookup-selected state) - stopper (->> stream - (rx/filter mse/mouse-event?) - (rx/filter mse/mouse-up-event?))] + stopper (mse/drag-stopper stream)] (when (= 1 (count selected)) (rx/concat (->> ms/mouse-position @@ -305,9 +303,7 @@ (watch [_ state stream] (let [initial-pos @ms/mouse-position selected (wsh/lookup-selected state) - stopper (->> stream - (rx/filter mse/mouse-event?) - (rx/filter mse/mouse-up-event?))] + stopper (mse/drag-stopper stream)] (when (= 1 (count selected)) (let [page-id (:current-page-id state) objects (wsh/lookup-page-objects state page-id) diff --git a/frontend/src/app/main/data/workspace/path/drawing.cljs b/frontend/src/app/main/data/workspace/path/drawing.cljs index af492bc0f..f536f3369 100644 --- a/frontend/src/app/main/data/workspace/path/drawing.cljs +++ b/frontend/src/app/main/data/workspace/path/drawing.cljs @@ -139,9 +139,7 @@ (rx/map #(drag-handler position idx prefix %)) (rx/take-until (rx/merge - (->> stream - (rx/filter mse/mouse-event?) - (rx/filter mse/mouse-up-event?)) + (mse/drag-stopper stream) (->> stream (rx/filter helpers/end-path-event?)))))] @@ -166,9 +164,7 @@ ptk/WatchEvent (watch [_ state stream] (let [stopper (rx/merge - (->> stream - (rx/filter mse/mouse-event?) - (rx/filter mse/mouse-up-event?)) + (mse/drag-stopper stream) (->> stream (rx/filter helpers/end-path-event?))) @@ -197,9 +193,7 @@ (gpt/point? down-event)) (let [stopper (rx/merge - (->> stream - (rx/filter mse/mouse-event?) - (rx/filter mse/mouse-up-event?)) + (mse/drag-stopper stream) (->> stream (rx/filter helpers/end-path-event?))) diff --git a/frontend/src/app/main/data/workspace/path/edition.cljs b/frontend/src/app/main/data/workspace/path/edition.cljs index 51d688707..164e37acb 100644 --- a/frontend/src/app/main/data/workspace/path/edition.cljs +++ b/frontend/src/app/main/data/workspace/path/edition.cljs @@ -150,9 +150,7 @@ (ptk/reify ::drag-selected-points ptk/WatchEvent (watch [_ state stream] - (let [stopper (->> stream - (rx/filter mse/mouse-event?) - (rx/filter mse/mouse-up-event?)) + (let [stopper (mse/drag-stopper stream) id (dm/get-in state [:workspace-local :edition]) @@ -279,9 +277,7 @@ (not alt?))))) (rx/take-until (rx/merge - (->> stream - (rx/filter mse/mouse-event?) - (rx/filter mse/mouse-up-event?)) + (mse/drag-stopper stream) (->> stream (rx/filter streams/finish-edition?))))) diff --git a/frontend/src/app/main/data/workspace/path/selection.cljs b/frontend/src/app/main/data/workspace/path/selection.cljs index 028a6ec3b..b2256b3c9 100644 --- a/frontend/src/app/main/data/workspace/path/selection.cljs +++ b/frontend/src/app/main/data/workspace/path/selection.cljs @@ -10,7 +10,6 @@ [app.common.geom.point :as gpt] [app.common.geom.rect :as grc] [app.common.geom.shapes :as gsh] - [app.main.data.workspace.common :as dwc] [app.main.data.workspace.path.state :as st] [app.main.streams :as ms] [app.util.mouse :as mse] @@ -119,15 +118,9 @@ (ptk/reify ::handle-area-selection ptk/WatchEvent (watch [_ state stream] - (let [zoom (get-in state [:workspace-local :zoom] 1) - stopper (rx/merge - (->> stream - (rx/filter mse/mouse-event?) - (rx/filter mse/mouse-up-event?)) - (->> stream - (rx/filter dwc/interrupt?))) - - from-p @ms/mouse-position] + (let [zoom (get-in state [:workspace-local :zoom] 1) + stopper (mse/drag-stopper stream) + from-p @ms/mouse-position] (rx/concat (->> ms/mouse-position (rx/map #(grc/points->rect [from-p %])) diff --git a/frontend/src/app/main/data/workspace/path/streams.cljs b/frontend/src/app/main/data/workspace/path/streams.cljs index 9f55e92a0..38d0efd50 100644 --- a/frontend/src/app/main/data/workspace/path/streams.cljs +++ b/frontend/src/app/main/data/workspace/path/streams.cljs @@ -53,9 +53,7 @@ start (-> @ms/mouse-position to-pixel-snap) stopper (rx/merge - (->> st/stream - (rx/filter mse/mouse-event?) - (rx/filter mse/mouse-up-event?)) + (mse/drag-stopper st/stream) (->> st/stream (rx/filter finish-edition?))) diff --git a/frontend/src/app/main/data/workspace/selection.cljs b/frontend/src/app/main/data/workspace/selection.cljs index 3f22275b9..ca4200c11 100644 --- a/frontend/src/app/main/data/workspace/selection.cljs +++ b/frontend/src/app/main/data/workspace/selection.cljs @@ -27,6 +27,7 @@ [app.main.data.modal :as md] [app.main.data.workspace.changes :as dch] [app.main.data.workspace.collapse :as dwc] + [app.main.data.workspace.edition :as dwe] [app.main.data.workspace.libraries-helpers :as dwlh] [app.main.data.workspace.specialized-panel :as-alias dwsp] [app.main.data.workspace.state-helpers :as wsh] @@ -63,14 +64,8 @@ (ptk/reify ::handle-area-selection ptk/WatchEvent (watch [_ state stream] - (let [zoom (dm/get-in state [:workspace-local :zoom] 1) - stopper (rx/merge - (->> stream - (rx/filter mse/mouse-event?) - (rx/filter mse/mouse-up-event?)) - (->> stream - (rx/filter interrupt?))) - + (let [zoom (dm/get-in state [:workspace-local :zoom] 1) + stopper (mse/drag-stopper stream) init-position @ms/mouse-position init-selrect (grc/make-rect @@ -155,7 +150,7 @@ objects (wsh/lookup-page-objects state page-id)] (rx/of (dwc/expand-all-parents [id] objects) - :interrupt + (dwe/clear-edition-mode) ::dwsp/interrupt)))))) (defn select-prev-shape diff --git a/frontend/src/app/main/data/workspace/transforms.cljs b/frontend/src/app/main/data/workspace/transforms.cljs index fc8ee350d..c52cd2fbb 100644 --- a/frontend/src/app/main/data/workspace/transforms.cljs +++ b/frontend/src/app/main/data/workspace/transforms.cljs @@ -257,9 +257,7 @@ (watch [_ state stream] (let [initial-position @ms/mouse-position - stopper (->> stream - (rx/filter mse/mouse-event?) - (rx/filter mse/mouse-up-event?)) + stopper (mse/drag-stopper stream) layout (:workspace-layout state) page-id (:current-page-id state) focus (:workspace-focus-selected state) @@ -370,10 +368,7 @@ ptk/WatchEvent (watch [_ _ stream] - (let [stopper (->> stream - (rx/filter mse/mouse-event?) - (rx/filter mse/mouse-up-event?)) - + (let [stopper (mse/drag-stopper stream) group (gsh/shapes->rect shapes) group-center (grc/rect->center group) initial-angle (gpt/angle @ms/mouse-position group-center) @@ -436,10 +431,7 @@ (watch [_ state stream] (let [initial (deref ms/mouse-position) - stopper (->> stream - (rx/filter mse/mouse-event?) - (rx/filter mse/mouse-up-event?)) - + stopper (mse/drag-stopper stream) zoom (get-in state [:workspace-local :zoom] 1) ;; We toggle the selection so we don't have to wait for the event @@ -518,10 +510,7 @@ duplicate-move-started? (get-in state [:workspace-local :duplicate-move-started?] false) - stopper (->> stream - (rx/filter mse/mouse-event?) - (rx/filter mse/mouse-up-event?)) - + stopper (mse/drag-stopper stream) layout (get state :workspace-layout) zoom (get-in state [:workspace-local :zoom] 1) focus (:workspace-focus-selected state) diff --git a/frontend/src/app/main/ui/workspace/viewport/hooks.cljs b/frontend/src/app/main/ui/workspace/viewport/hooks.cljs index 1a8c45567..c2d4ab55b 100644 --- a/frontend/src/app/main/ui/workspace/viewport/hooks.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/hooks.cljs @@ -32,6 +32,7 @@ [app.util.dom :as dom] [app.util.globals :as globals] [app.util.keyboard :as kbd] + [app.util.mouse :as mse] [beicon.v2.core :as rx] [beicon.v2.operators :as rxo] [goog.events :as events] @@ -42,7 +43,8 @@ (let [on-key-down (actions/on-key-down) on-key-up (actions/on-key-up) on-mouse-wheel (actions/on-mouse-wheel zoom) - on-paste (actions/on-paste disable-paste in-viewport? workspace-read-only?)] + on-paste (actions/on-paste disable-paste in-viewport? workspace-read-only?) + on-blur (mf/use-fn #(st/emit! (mse/->BlurEvent)))] (mf/use-layout-effect (mf/deps on-key-down on-key-up on-mouse-wheel on-paste workspace-read-only?) @@ -52,7 +54,8 @@ ;; bind with passive=false to allow the event to be cancelled ;; https://stackoverflow.com/a/57582286/3219895 (events/listen js/window EventType.WHEEL on-mouse-wheel #js {:passive false}) - (events/listen js/window EventType.PASTE on-paste)]] + (events/listen js/window EventType.PASTE on-paste) + (events/listen js/window EventType.BLUR on-blur)]] (fn [] (doseq [key keys] (events/unlistenByKey key)))))))) diff --git a/frontend/src/app/util/mouse.cljs b/frontend/src/app/util/mouse.cljs index b7771eba2..4576ed325 100644 --- a/frontend/src/app/util/mouse.cljs +++ b/frontend/src/app/util/mouse.cljs @@ -4,11 +4,14 @@ ;; ;; Copyright (c) KALEIDOS INC -(ns app.util.mouse) +(ns app.util.mouse + (:require + [beicon.v2.core :as rx])) (defrecord MouseEvent [type ctrl shift alt meta]) (defrecord PointerEvent [source pt ctrl shift alt meta]) (defrecord ScrollEvent [point]) +(defrecord BlurEvent []) (defn mouse-event? [v] @@ -22,6 +25,10 @@ [v] (instance? ScrollEvent v)) +(defn blur-event? + [v] + (instance? BlurEvent v)) + (defn mouse-down-event? [^MouseEvent v] (= :down (.-type v))) @@ -61,3 +68,16 @@ (defn get-pointer-shift-mod [^PointerEvent ev] (.-shift ev)) + +(defn drag-stopper + "Creates a stream to stop drag events. Takes into account the mouse and also + if the window loses focus or the esc key is pressed." + [stream] + (rx/merge + (->> stream + (rx/filter blur-event?)) + (->> stream + (rx/filter mouse-event?) + (rx/filter mouse-up-event?)) + (->> stream + (rx/filter #(= % :interrupt)))))