diff --git a/src/client/graphics/layers/PerformanceOverlay.ts b/src/client/graphics/layers/PerformanceOverlay.ts index bf6f64272..3da3809c8 100644 --- a/src/client/graphics/layers/PerformanceOverlay.ts +++ b/src/client/graphics/layers/PerformanceOverlay.ts @@ -72,7 +72,6 @@ export class PerformanceOverlay extends LitElement implements Layer { private fpsHistory: number[] = []; private lastSecondTime: number = 0; private framesThisSecond: number = 0; - private dragStart: { x: number; y: number } = { x: 0, y: 0 }; private tickExecutionTimes: number[] = []; private tickDelayTimes: number[] = []; private tickTimestamps: number[] = []; @@ -88,6 +87,11 @@ export class PerformanceOverlay extends LitElement implements Layer { pendingWidthPx: number; } | null = null; + private dragState: { + pointerId: number; + dragStart: { x: number; y: number }; + } | null = null; + // Smoothed per-layer render timings (EMA over recent frames) private layerStats: Map< string, @@ -154,13 +158,18 @@ export class PerformanceOverlay extends LitElement implements Layer { font-size: 12px; z-index: 9999; user-select: none; - cursor: move; + cursor: default; transition: none; box-sizing: border-box; width: var(--overlay-width, min(460px, calc(100vw - 16px))); max-width: calc(100vw - 16px); max-height: calc(100vh - 16px); + overflow: hidden; + } + + .overlay-scroll { overflow: auto; + max-height: calc(100vh - 56px); } .performance-overlay.dragging { @@ -169,6 +178,21 @@ export class PerformanceOverlay extends LitElement implements Layer { opacity: 0.5; } + .drag-handle { + position: absolute; + top: 0; + left: 0; + right: 12px; /* leave space for the resize handle */ + height: 32px; + cursor: grab; + touch-action: none; + pointer-events: auto; + } + + .performance-overlay.dragging .drag-handle { + cursor: grabbing; + } + .performance-line { margin: 2px 0; } @@ -377,6 +401,14 @@ export class PerformanceOverlay extends LitElement implements Layer { this.resizeState = null; } + if (!visible && this.dragState) { + globalThis.removeEventListener("pointermove", this.onDragPointerMove); + globalThis.removeEventListener("pointerup", this.onDragPointerUp); + globalThis.removeEventListener("pointercancel", this.onDragPointerUp); + this.dragState = null; + this.isDragging = false; + } + this.requestUpdate(); } @@ -386,35 +418,11 @@ export class PerformanceOverlay extends LitElement implements Layer { this.userSettings.set("settings.performanceOverlay", nextVisible); } - private handleMouseDown = (e: MouseEvent) => { - // Don't start dragging if clicking on close button - const target = e.target as HTMLElement; - if ( - target.classList.contains("close-button") || - target.classList.contains("reset-button") || - target.classList.contains("copy-json-button") || - target.classList.contains("collapse-button") || - target.classList.contains("resize-handle") - ) { - return; - } + private onDragPointerMove = (e: PointerEvent) => { + if (!this.dragState || e.pointerId !== this.dragState.pointerId) return; - this.isDragging = true; - this.dragStart = { - x: e.clientX - this.position.x, - y: e.clientY - this.position.y, - }; - - document.addEventListener("mousemove", this.handleMouseMove); - document.addEventListener("mouseup", this.handleMouseUp); - e.preventDefault(); - }; - - private handleMouseMove = (e: MouseEvent) => { - if (!this.isDragging) return; - - const newX = e.clientX - this.dragStart.x; - const newY = e.clientY - this.dragStart.y; + const newX = e.clientX - this.dragState.dragStart.x; + const newY = e.clientY - this.dragState.dragStart.y; const margin = 8; const viewportWidth = window.innerWidth; @@ -436,20 +444,44 @@ export class PerformanceOverlay extends LitElement implements Layer { this.requestUpdate(); }; - private handleMouseUp = () => { + private onDragPointerUp = (e: PointerEvent) => { + if (!this.dragState || e.pointerId !== this.dragState.pointerId) return; + + globalThis.removeEventListener("pointermove", this.onDragPointerMove); + globalThis.removeEventListener("pointerup", this.onDragPointerUp); + globalThis.removeEventListener("pointercancel", this.onDragPointerUp); + + this.dragState = null; this.isDragging = false; - document.removeEventListener("mousemove", this.handleMouseMove); - document.removeEventListener("mouseup", this.handleMouseUp); + this.requestUpdate(); + }; + + private handleDragPointerDown = (e: PointerEvent) => { + e.preventDefault(); + e.stopPropagation(); + + this.isDragging = true; + this.dragState = { + pointerId: e.pointerId, + dragStart: { + x: e.clientX - this.position.x, + y: e.clientY - this.position.y, + }, + }; + + globalThis.addEventListener("pointermove", this.onDragPointerMove); + globalThis.addEventListener("pointerup", this.onDragPointerUp); + globalThis.addEventListener("pointercancel", this.onDragPointerUp); }; private onResizePointerMove = (e: PointerEvent) => { if (!this.resizeState || e.pointerId !== this.resizeState.pointerId) return; const margin = 8; - const minWidthPx = 260; const viewportWidth = window.innerWidth; const left = Math.max(margin, Math.min(this.position.x, viewportWidth)); - const maxWidthPx = Math.max(minWidthPx, viewportWidth - left - margin); + const maxWidthPx = Math.max(120, viewportWidth - left - margin); + const minWidthPx = Math.min(260, maxWidthPx); const delta = e.clientX - this.resizeState.startClientX; const nextWidth = this.resizeState.startWidthPx + delta; @@ -937,8 +969,11 @@ export class PerformanceOverlay extends LitElement implements Layer {
-