From 41620600cc69ec50e04b53785a9918f9eccb2c60 Mon Sep 17 00:00:00 2001 From: かっこかり <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Mon, 16 Feb 2026 19:23:30 +0900 Subject: fix(frontend): ウィンドウのドラッグ・サイズ変更のポインターをキャプチャするように (#17159) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(frontend): ウィンドウのドラッグ・サイズ変更のポインターをキャプチャするように * Update Changelog * fix --- CHANGELOG.md | 1 + packages/frontend/src/components/MkWindow.vue | 115 ++++++++++++++++---------- 2 files changed, 74 insertions(+), 42 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 02254f6f32..0e93939ac7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ - Fix: mCaptchaが正しく動作しない問題を修正 - Fix: 非ログイン時にリバーシの対局が表示されない問題を修正 - Fix: ノートの詳細表示でリアクションが全件表示されない問題を修正 +- Fix: 動画埋め込みプレイヤーなどの一部ウィンドウで、ウィンドウのサイズ変更や移動が正常に行えない問題を修正 - Fix: 画像エフェクトの修正 - 塗りつぶし・モザイク・ぼかしエフェクトを回転させると歪む問題を修正 - モザイクの格子のサイズが画像の縦横比によって長方形となる問題を修正 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 - + @@ -39,14 +39,14 @@ SPDX-License-Identifier: AGPL-3.0-only @@ -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 { -- cgit v1.2.3-freya