summaryrefslogtreecommitdiff
path: root/packages/frontend/src
diff options
context:
space:
mode:
Diffstat (limited to 'packages/frontend/src')
-rw-r--r--packages/frontend/src/components/MkWindow.vue115
1 files changed, 73 insertions, 42 deletions
diff --git a/packages/frontend/src/components/MkWindow.vue b/packages/frontend/src/components/MkWindow.vue
index 7fb77da476..c79bf44794 100644
--- a/packages/frontend/src/components/MkWindow.vue
+++ b/packages/frontend/src/components/MkWindow.vue
@@ -20,7 +20,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<button v-for="button in buttonsLeft" v-tooltip="button.title" class="_button" :class="[$style.headerButton, { [$style.highlighted]: button.highlighted }]" @click="button.onClick"><i :class="button.icon"></i></button>
</template>
</span>
- <span :class="$style.headerTitle" @mousedown.prevent="onHeaderMousedown" @touchstart.prevent="onHeaderMousedown">
+ <span :class="$style.headerTitle" @pointerdown.prevent="onHeaderPointerdown">
<slot name="header"></slot>
</span>
<span :class="$style.headerRight">
@@ -39,14 +39,14 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
</div>
<template v-if="canResize && !minimized">
- <div :class="$style.handleTop" @mousedown.prevent="onTopHandleMousedown"></div>
- <div :class="$style.handleRight" @mousedown.prevent="onRightHandleMousedown"></div>
- <div :class="$style.handleBottom" @mousedown.prevent="onBottomHandleMousedown"></div>
- <div :class="$style.handleLeft" @mousedown.prevent="onLeftHandleMousedown"></div>
- <div :class="$style.handleTopLeft" @mousedown.prevent="onTopLeftHandleMousedown"></div>
- <div :class="$style.handleTopRight" @mousedown.prevent="onTopRightHandleMousedown"></div>
- <div :class="$style.handleBottomRight" @mousedown.prevent="onBottomRightHandleMousedown"></div>
- <div :class="$style.handleBottomLeft" @mousedown.prevent="onBottomLeftHandleMousedown"></div>
+ <div :class="$style.handleTop" @pointerdown.prevent="onTopHandlePointerdown"></div>
+ <div :class="$style.handleRight" @pointerdown.prevent="onRightHandlePointerdown"></div>
+ <div :class="$style.handleBottom" @pointerdown.prevent="onBottomHandlePointerdown"></div>
+ <div :class="$style.handleLeft" @pointerdown.prevent="onLeftHandlePointerdown"></div>
+ <div :class="$style.handleTopLeft" @pointerdown.prevent="onTopLeftHandlePointerdown"></div>
+ <div :class="$style.handleTopRight" @pointerdown.prevent="onTopRightHandlePointerdown"></div>
+ <div :class="$style.handleBottomRight" @pointerdown.prevent="onBottomRightHandlePointerdown"></div>
+ <div :class="$style.handleBottomLeft" @pointerdown.prevent="onBottomLeftHandlePointerdown"></div>
</template>
</div>
</Transition>
@@ -70,20 +70,39 @@ type WindowButton = {
const minHeight = 50;
const minWidth = 250;
-function dragListen(fn: (ev: MouseEvent | TouchEvent) => void) {
- window.addEventListener('mousemove', fn);
- window.addEventListener('touchmove', fn);
- window.addEventListener('mouseleave', dragClear.bind(null, fn));
- window.addEventListener('mouseup', dragClear.bind(null, fn));
- window.addEventListener('touchend', dragClear.bind(null, fn));
+function dragListen(fn: (ev: PointerEvent) => void) {
+ window.addEventListener('pointermove', fn);
+ const clear = () => {
+ dragClear(fn);
+ };
+ window.addEventListener('pointerup', clear, { once: true });
+ window.addEventListener('pointercancel', clear, { once: true });
+ window.addEventListener('blur', clear, { once: true });
}
-function dragClear(fn: (ev: MouseEvent | TouchEvent) => void) {
- window.removeEventListener('mousemove', fn);
- window.removeEventListener('touchmove', fn);
- window.removeEventListener('mouseleave', dragClear as any);
- window.removeEventListener('mouseup', dragClear as any);
- window.removeEventListener('touchend', dragClear as any);
+function dragClear(fn: (ev: PointerEvent) => void) {
+ window.removeEventListener('pointermove', fn);
+}
+
+function capturePointer(evt: PointerEvent) {
+ const target = evt.currentTarget;
+ if (!(target instanceof HTMLElement)) return;
+ if (!target.setPointerCapture) return;
+
+ try {
+ target.setPointerCapture(evt.pointerId);
+ } catch {
+ return;
+ }
+
+ const release = () => {
+ if (target.hasPointerCapture(evt.pointerId)) {
+ target.releasePointerCapture(evt.pointerId);
+ }
+ };
+
+ window.addEventListener('pointerup', release, { once: true });
+ window.addEventListener('pointercancel', release, { once: true });
}
const props = withDefaults(defineProps<{
@@ -209,15 +228,17 @@ function onDblClick() {
}
}
-function getPositionX(event: MouseEvent | TouchEvent) {
- return 'touches' in event && event.touches.length > 0 ? event.touches[0].clientX : 'clientX' in event ? event.clientX : 0;
+function getPositionX(event: PointerEvent) {
+ return event.clientX;
}
-function getPositionY(event: MouseEvent | TouchEvent) {
- return 'touches' in event && event.touches.length > 0 ? event.touches[0].clientY : 'clientY' in event ? event.clientY : 0;
+function getPositionY(event: PointerEvent) {
+ return event.clientY;
}
-function onHeaderMousedown(evt: MouseEvent | TouchEvent) {
+function onHeaderPointerdown(evt: PointerEvent) {
+ capturePointer(evt);
+
// 右クリックはコンテキストメニューを開こうとした可能性が高いため無視
if ('button' in evt && evt.button === 2) return;
@@ -289,7 +310,9 @@ function onHeaderMousedown(evt: MouseEvent | TouchEvent) {
}
// 上ハンドル掴み時
-function onTopHandleMousedown(evt: MouseEvent | TouchEvent) {
+function onTopHandlePointerdown(evt: PointerEvent) {
+ capturePointer(evt);
+
const main = rootEl.value;
// どういうわけかnullになることがある
if (main == null) return;
@@ -317,7 +340,9 @@ function onTopHandleMousedown(evt: MouseEvent | TouchEvent) {
}
// 右ハンドル掴み時
-function onRightHandleMousedown(evt: MouseEvent | TouchEvent) {
+function onRightHandlePointerdown(evt: PointerEvent) {
+ capturePointer(evt);
+
const main = rootEl.value;
if (main == null) return;
@@ -342,7 +367,9 @@ function onRightHandleMousedown(evt: MouseEvent | TouchEvent) {
}
// 下ハンドル掴み時
-function onBottomHandleMousedown(evt: MouseEvent | TouchEvent) {
+function onBottomHandlePointerdown(evt: PointerEvent) {
+ capturePointer(evt);
+
const main = rootEl.value;
if (main == null) return;
@@ -367,7 +394,9 @@ function onBottomHandleMousedown(evt: MouseEvent | TouchEvent) {
}
// 左ハンドル掴み時
-function onLeftHandleMousedown(evt: MouseEvent | TouchEvent) {
+function onLeftHandlePointerdown(evt: PointerEvent) {
+ capturePointer(evt);
+
const main = rootEl.value;
if (main == null) return;
@@ -394,27 +423,27 @@ function onLeftHandleMousedown(evt: MouseEvent | TouchEvent) {
}
// 左上ハンドル掴み時
-function onTopLeftHandleMousedown(evt: MouseEvent | TouchEvent) {
- onTopHandleMousedown(evt);
- onLeftHandleMousedown(evt);
+function onTopLeftHandlePointerdown(evt: PointerEvent) {
+ onTopHandlePointerdown(evt);
+ onLeftHandlePointerdown(evt);
}
// 右上ハンドル掴み時
-function onTopRightHandleMousedown(evt: MouseEvent | TouchEvent) {
- onTopHandleMousedown(evt);
- onRightHandleMousedown(evt);
+function onTopRightHandlePointerdown(evt: PointerEvent) {
+ onTopHandlePointerdown(evt);
+ onRightHandlePointerdown(evt);
}
// 右下ハンドル掴み時
-function onBottomRightHandleMousedown(evt: MouseEvent | TouchEvent) {
- onBottomHandleMousedown(evt);
- onRightHandleMousedown(evt);
+function onBottomRightHandlePointerdown(evt: PointerEvent) {
+ onBottomHandlePointerdown(evt);
+ onRightHandlePointerdown(evt);
}
// 左下ハンドル掴み時
-function onBottomLeftHandleMousedown(evt: MouseEvent | TouchEvent) {
- onBottomHandleMousedown(evt);
- onLeftHandleMousedown(evt);
+function onBottomLeftHandlePointerdown(evt: PointerEvent) {
+ onBottomHandlePointerdown(evt);
+ onLeftHandlePointerdown(evt);
}
// 高さを適用
@@ -566,6 +595,7 @@ defineExpose({
overflow: hidden;
text-overflow: ellipsis;
cursor: move;
+ touch-action: none;
}
.content {
@@ -579,6 +609,7 @@ $handleSize: 8px;
.handle {
position: absolute;
+ touch-action: none;
}
.handleTop {