diff --git a/webapp/src/App.vue b/webapp/src/App.vue
index 917f5dcd..671e3d39 100644
--- a/webapp/src/App.vue
+++ b/webapp/src/App.vue
@@ -243,7 +243,9 @@ export default {
eventBus.emit("globalTogglePreview", false);
},
- // Handle global mouse wheel events to be associated with navigation
+ /**
+ * Handle global mouse wheel events to be associated with navigation
+ */
wheelMonitor: function (event) {
// Only capture scroll if the event target's parent contains the "scrollTarget" class
if (
@@ -261,6 +263,13 @@ export default {
}
},
+ /**
+ * Jog for key-presses.
+ *
+ * This is a similar to the function in stageControlButtons.vue however it uses
+ * uses the key repeat to fire in case a key up is missed. It debounes any
+ * request to jog that is too recent after the last jog.
+ */
jog(x, y, z) {
// Manually debounce extra requests from keyboard repeat rate.
// This is used rather than and interval in case of missing a repeat.
@@ -279,6 +288,13 @@ export default {
eventBus.emit("globalUpdatePositionEvent");
},
+ /**
+ * Stop jogging on key-up
+ *
+ * This is also similar to the function in stageControlButtons.vue. It handles
+ * stopping jogging and resetting the `lastJogTime` so there is no delay when
+ * starting a new jog after an old jog finished.
+ */
jogStop() {
this.invokeAction("stage", "jog", { stop: true });
this.lastJogTime = 0;
@@ -287,6 +303,9 @@ export default {
}, 100);
},
+ /**
+ * Track which keys are still down on keypress (or key repeat).
+ */
updateJogFromKeys() {
let x = 0,
y = 0,
diff --git a/webapp/src/components/tabContentComponents/controlComponents/stageControlButtons.vue b/webapp/src/components/tabContentComponents/controlComponents/stageControlButtons.vue
index 158823d2..f75a08a4 100644
--- a/webapp/src/components/tabContentComponents/controlComponents/stageControlButtons.vue
+++ b/webapp/src/components/tabContentComponents/controlComponents/stageControlButtons.vue
@@ -12,9 +12,9 @@
v-if="showDpad"
id="up-button"
class="uk-button uk-button-primary dpad-btn"
- @mousedown.left="jog(0, 1, 0)"
- @mouseup="jogStop()"
- @mouseOut="jogStop()"
+ @pointerdown="jog($event, 0, 1, 0)"
+ @pointerup="jogStop()"
+ @mouseLeave="jogStop()"
>
arrow_upward
@@ -23,9 +23,9 @@
v-if="showDpad"
id="left-button"
class="uk-button uk-button-primary dpad-btn"
- @mousedown.left="jog(-1, 0, 0)"
- @mouseup="jogStop()"
- @mouseOut="jogStop()"
+ @pointerdown="jog($event, -1, 0, 0)"
+ @pointerup="jogStop()"
+ @pointercancel="jogStop()"
>
arrow_back
@@ -34,9 +34,9 @@
v-if="showDpad"
id="right-button"
class="uk-button uk-button-primary dpad-btn"
- @mousedown.left="jog(1, 0, 0)"
- @mouseup="jogStop()"
- @mouseOut="jogStop()"
+ @pointerdown="jog($event, 1, 0, 0)"
+ @pointerup="jogStop()"
+ @pointercancel="jogStop()"
>
arrow_forward
@@ -45,9 +45,9 @@
v-if="showDpad"
id="down-button"
class="uk-button uk-button-primary dpad-btn"
- @mousedown.left="jog(0, -1, 0)"
- @mouseup="jogStop()"
- @mouseOut="jogStop()"
+ @pointerdown="jog($event, 0, -1, 0)"
+ @pointerup="jogStop()"
+ @pointercancel="jogStop()"
>
arrow_downward
@@ -56,9 +56,9 @@
v-if="showFocusControls"
id="focus-out-button"
class="uk-button uk-button-primary dpad-btn"
- @mousedown.left="jog(0, 0, -1)"
- @mouseup="jogStop()"
- @mouseOut="jogStop()"
+ @pointerdown="jog($event, 0, 0, -1)"
+ @pointerup="jogStop()"
+ @pointercancel="jogStop()"
>
remove
@@ -67,9 +67,9 @@
v-if="showFocusControls"
id="focus-in-button"
class="uk-button uk-button-primary dpad-btn"
- @mousedown.left="jog(0, 0, 1)"
- @mouseup="jogStop()"
- @mouseOut="jogStop()"
+ @pointerdown="jog($event, 0, 0, 1)"
+ @pointerup="jogStop()"
+ @pointercancel="jogStop()"
>
add
@@ -98,10 +98,24 @@ export default {
jogTime: 300,
}),
methods: {
- jog(x, y, z) {
+ /**
+ * Jog d-pad and focus buttons.
+ *
+ * This is a similar to the function in App.vue, however it uses an Interval rather
+ * than the one in App.vue that uses key repeats.
+ */
+ jog(keyevent, x, y, z) {
+ // Only respond to primary button (left mouse / primary touch)
+ if (keyevent.button !== 0) return;
+
if (this.jogIntervalId) {
clearInterval(this.jogIntervalId);
}
+
+ // Designate this element to get the pointers next pointerup event wherever that
+ // pointer is.
+ keyevent.target.setPointerCapture(keyevent.pointerId);
+
const navigationInvert = this.$store.state.navigationInvert;
let invokeJog = () =>
this.invokeAction("stage", "jog", {
@@ -112,6 +126,12 @@ export default {
invokeJog();
this.jogIntervalId = setInterval(invokeJog, this.jogTime);
},
+ /**
+ * Stop jogging from d-pad and focus buttons.
+ *
+ * This is a similar to the function in App.vue, but it is designed to clear the
+ * interval used with the d-pad and focus buttons.
+ */
jogStop() {
if (this.jogIntervalId) {
clearInterval(this.jogIntervalId);