Skip to content

Commit 4162060

Browse files
fix(frontend): ウィンドウのドラッグ・サイズ変更のポインターをキャプチャするように (#17159)
* fix(frontend): ウィンドウのドラッグ・サイズ変更のポインターをキャプチャするように * Update Changelog * fix
1 parent b5121dc commit 4162060

2 files changed

Lines changed: 74 additions & 42 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
- Fix: mCaptchaが正しく動作しない問題を修正
2828
- Fix: 非ログイン時にリバーシの対局が表示されない問題を修正
2929
- Fix: ノートの詳細表示でリアクションが全件表示されない問題を修正
30+
- Fix: 動画埋め込みプレイヤーなどの一部ウィンドウで、ウィンドウのサイズ変更や移動が正常に行えない問題を修正
3031
- Fix: 画像エフェクトの修正
3132
- 塗りつぶし・モザイク・ぼかしエフェクトを回転させると歪む問題を修正
3233
- モザイクの格子のサイズが画像の縦横比によって長方形となる問題を修正

packages/frontend/src/components/MkWindow.vue

Lines changed: 73 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ SPDX-License-Identifier: AGPL-3.0-only
2020
<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>
2121
</template>
2222
</span>
23-
<span :class="$style.headerTitle" @mousedown.prevent="onHeaderMousedown" @touchstart.prevent="onHeaderMousedown">
23+
<span :class="$style.headerTitle" @pointerdown.prevent="onHeaderPointerdown">
2424
<slot name="header"></slot>
2525
</span>
2626
<span :class="$style.headerRight">
@@ -39,14 +39,14 @@ SPDX-License-Identifier: AGPL-3.0-only
3939
</div>
4040
</div>
4141
<template v-if="canResize && !minimized">
42-
<div :class="$style.handleTop" @mousedown.prevent="onTopHandleMousedown"></div>
43-
<div :class="$style.handleRight" @mousedown.prevent="onRightHandleMousedown"></div>
44-
<div :class="$style.handleBottom" @mousedown.prevent="onBottomHandleMousedown"></div>
45-
<div :class="$style.handleLeft" @mousedown.prevent="onLeftHandleMousedown"></div>
46-
<div :class="$style.handleTopLeft" @mousedown.prevent="onTopLeftHandleMousedown"></div>
47-
<div :class="$style.handleTopRight" @mousedown.prevent="onTopRightHandleMousedown"></div>
48-
<div :class="$style.handleBottomRight" @mousedown.prevent="onBottomRightHandleMousedown"></div>
49-
<div :class="$style.handleBottomLeft" @mousedown.prevent="onBottomLeftHandleMousedown"></div>
42+
<div :class="$style.handleTop" @pointerdown.prevent="onTopHandlePointerdown"></div>
43+
<div :class="$style.handleRight" @pointerdown.prevent="onRightHandlePointerdown"></div>
44+
<div :class="$style.handleBottom" @pointerdown.prevent="onBottomHandlePointerdown"></div>
45+
<div :class="$style.handleLeft" @pointerdown.prevent="onLeftHandlePointerdown"></div>
46+
<div :class="$style.handleTopLeft" @pointerdown.prevent="onTopLeftHandlePointerdown"></div>
47+
<div :class="$style.handleTopRight" @pointerdown.prevent="onTopRightHandlePointerdown"></div>
48+
<div :class="$style.handleBottomRight" @pointerdown.prevent="onBottomRightHandlePointerdown"></div>
49+
<div :class="$style.handleBottomLeft" @pointerdown.prevent="onBottomLeftHandlePointerdown"></div>
5050
</template>
5151
</div>
5252
</Transition>
@@ -70,20 +70,39 @@ type WindowButton = {
7070
const minHeight = 50;
7171
const minWidth = 250;
7272
73-
function dragListen(fn: (ev: MouseEvent | TouchEvent) => void) {
74-
window.addEventListener('mousemove', fn);
75-
window.addEventListener('touchmove', fn);
76-
window.addEventListener('mouseleave', dragClear.bind(null, fn));
77-
window.addEventListener('mouseup', dragClear.bind(null, fn));
78-
window.addEventListener('touchend', dragClear.bind(null, fn));
73+
function dragListen(fn: (ev: PointerEvent) => void) {
74+
window.addEventListener('pointermove', fn);
75+
const clear = () => {
76+
dragClear(fn);
77+
};
78+
window.addEventListener('pointerup', clear, { once: true });
79+
window.addEventListener('pointercancel', clear, { once: true });
80+
window.addEventListener('blur', clear, { once: true });
7981
}
8082
81-
function dragClear(fn: (ev: MouseEvent | TouchEvent) => void) {
82-
window.removeEventListener('mousemove', fn);
83-
window.removeEventListener('touchmove', fn);
84-
window.removeEventListener('mouseleave', dragClear as any);
85-
window.removeEventListener('mouseup', dragClear as any);
86-
window.removeEventListener('touchend', dragClear as any);
83+
function dragClear(fn: (ev: PointerEvent) => void) {
84+
window.removeEventListener('pointermove', fn);
85+
}
86+
87+
function capturePointer(evt: PointerEvent) {
88+
const target = evt.currentTarget;
89+
if (!(target instanceof HTMLElement)) return;
90+
if (!target.setPointerCapture) return;
91+
92+
try {
93+
target.setPointerCapture(evt.pointerId);
94+
} catch {
95+
return;
96+
}
97+
98+
const release = () => {
99+
if (target.hasPointerCapture(evt.pointerId)) {
100+
target.releasePointerCapture(evt.pointerId);
101+
}
102+
};
103+
104+
window.addEventListener('pointerup', release, { once: true });
105+
window.addEventListener('pointercancel', release, { once: true });
87106
}
88107
89108
const props = withDefaults(defineProps<{
@@ -209,15 +228,17 @@ function onDblClick() {
209228
}
210229
}
211230
212-
function getPositionX(event: MouseEvent | TouchEvent) {
213-
return 'touches' in event && event.touches.length > 0 ? event.touches[0].clientX : 'clientX' in event ? event.clientX : 0;
231+
function getPositionX(event: PointerEvent) {
232+
return event.clientX;
214233
}
215234
216-
function getPositionY(event: MouseEvent | TouchEvent) {
217-
return 'touches' in event && event.touches.length > 0 ? event.touches[0].clientY : 'clientY' in event ? event.clientY : 0;
235+
function getPositionY(event: PointerEvent) {
236+
return event.clientY;
218237
}
219238
220-
function onHeaderMousedown(evt: MouseEvent | TouchEvent) {
239+
function onHeaderPointerdown(evt: PointerEvent) {
240+
capturePointer(evt);
241+
221242
// 右クリックはコンテキストメニューを開こうとした可能性が高いため無視
222243
if ('button' in evt && evt.button === 2) return;
223244
@@ -289,7 +310,9 @@ function onHeaderMousedown(evt: MouseEvent | TouchEvent) {
289310
}
290311
291312
// 上ハンドル掴み時
292-
function onTopHandleMousedown(evt: MouseEvent | TouchEvent) {
313+
function onTopHandlePointerdown(evt: PointerEvent) {
314+
capturePointer(evt);
315+
293316
const main = rootEl.value;
294317
// どういうわけかnullになることがある
295318
if (main == null) return;
@@ -317,7 +340,9 @@ function onTopHandleMousedown(evt: MouseEvent | TouchEvent) {
317340
}
318341
319342
// 右ハンドル掴み時
320-
function onRightHandleMousedown(evt: MouseEvent | TouchEvent) {
343+
function onRightHandlePointerdown(evt: PointerEvent) {
344+
capturePointer(evt);
345+
321346
const main = rootEl.value;
322347
if (main == null) return;
323348
@@ -342,7 +367,9 @@ function onRightHandleMousedown(evt: MouseEvent | TouchEvent) {
342367
}
343368
344369
// 下ハンドル掴み時
345-
function onBottomHandleMousedown(evt: MouseEvent | TouchEvent) {
370+
function onBottomHandlePointerdown(evt: PointerEvent) {
371+
capturePointer(evt);
372+
346373
const main = rootEl.value;
347374
if (main == null) return;
348375
@@ -367,7 +394,9 @@ function onBottomHandleMousedown(evt: MouseEvent | TouchEvent) {
367394
}
368395
369396
// 左ハンドル掴み時
370-
function onLeftHandleMousedown(evt: MouseEvent | TouchEvent) {
397+
function onLeftHandlePointerdown(evt: PointerEvent) {
398+
capturePointer(evt);
399+
371400
const main = rootEl.value;
372401
if (main == null) return;
373402
@@ -394,27 +423,27 @@ function onLeftHandleMousedown(evt: MouseEvent | TouchEvent) {
394423
}
395424
396425
// 左上ハンドル掴み時
397-
function onTopLeftHandleMousedown(evt: MouseEvent | TouchEvent) {
398-
onTopHandleMousedown(evt);
399-
onLeftHandleMousedown(evt);
426+
function onTopLeftHandlePointerdown(evt: PointerEvent) {
427+
onTopHandlePointerdown(evt);
428+
onLeftHandlePointerdown(evt);
400429
}
401430
402431
// 右上ハンドル掴み時
403-
function onTopRightHandleMousedown(evt: MouseEvent | TouchEvent) {
404-
onTopHandleMousedown(evt);
405-
onRightHandleMousedown(evt);
432+
function onTopRightHandlePointerdown(evt: PointerEvent) {
433+
onTopHandlePointerdown(evt);
434+
onRightHandlePointerdown(evt);
406435
}
407436
408437
// 右下ハンドル掴み時
409-
function onBottomRightHandleMousedown(evt: MouseEvent | TouchEvent) {
410-
onBottomHandleMousedown(evt);
411-
onRightHandleMousedown(evt);
438+
function onBottomRightHandlePointerdown(evt: PointerEvent) {
439+
onBottomHandlePointerdown(evt);
440+
onRightHandlePointerdown(evt);
412441
}
413442
414443
// 左下ハンドル掴み時
415-
function onBottomLeftHandleMousedown(evt: MouseEvent | TouchEvent) {
416-
onBottomHandleMousedown(evt);
417-
onLeftHandleMousedown(evt);
444+
function onBottomLeftHandlePointerdown(evt: PointerEvent) {
445+
onBottomHandlePointerdown(evt);
446+
onLeftHandlePointerdown(evt);
418447
}
419448
420449
// 高さを適用
@@ -566,6 +595,7 @@ defineExpose({
566595
overflow: hidden;
567596
text-overflow: ellipsis;
568597
cursor: move;
598+
touch-action: none;
569599
}
570600
571601
.content {
@@ -579,6 +609,7 @@ $handleSize: 8px;
579609
580610
.handle {
581611
position: absolute;
612+
touch-action: none;
582613
}
583614
584615
.handleTop {

0 commit comments

Comments
 (0)