Skip to content

fix(screen-mirror): grant display-capture permission in Electron executables#276

Closed
Muneerali199 wants to merge 10 commits into
AOSSIE-Org:mainfrom
Muneerali199:fix/screen-mirror-v2
Closed

fix(screen-mirror): grant display-capture permission in Electron executables#276
Muneerali199 wants to merge 10 commits into
AOSSIE-Org:mainfrom
Muneerali199:fix/screen-mirror-v2

Conversation

@Muneerali199

@Muneerali199 Muneerali199 commented Mar 9, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Add setPermissionRequestHandler and setPermissionCheckHandler to BrowserWindow session so getDisplayMedia is not silently denied in packaged builds (Bug [Bug]: Screen Mirror in Executatbles #254)
  • Add macOS screen recording permission check at app startup with user dialog
  • Add contextIsolation/nodeIntegration webPreferences for security
  • Add macOS activate handler for dock re-open behavior
  • Restrict permission handlers to http://localhost:3000 origin and display-capture/screen permissions only

Changes

  • electron/main.cjs: Added screen capture permission handlers

Testing

  • Test screen mirroring on packaged Windows/Linux executable (not dev mode)
  • Verify permission dialog appears on macOS if screen recording not granted

Summary by CodeRabbit

  • New Features

    • Added on-screen gamepad overlay with virtual joystick and action buttons for controller input
    • Added interactive arcade-style mini-game demo playable via gamepad
    • Integrated gamepad controls into the trackpad interface with dedicated toggle buttons
  • Chores

    • Enhanced Electron security with stricter context isolation and screen capture permission handling

- Add GamepadUI component with virtual joysticks and buttons
- Add useGamepad hook for touch/click handling with throttling
- Update WebSocket server to handle gamepad messages
- Update InputHandler to process gamepad inputs with deadzone
- Add gamepad toggle to ControlBar

Implements AOSSIE-Org#223
- Merge upstream/main (InputHandler try-catch hardening, websocket cleanup)
- Remove server-side gamepad relay (aligns with upstream revert of that feature)
- Remove useGamepad.ts hook (no longer needed; demo is client-side only)
- Fix GamepadButton: tabIndex=-1, e.preventDefault() on all pointer events, touch-none to suppress mobile keyboard
- Fix onBlur guard in trackpad.tsx to not re-focus hidden input when gamepad/demo is active
- Fix toggleDemo to close keyboard on open
- Add GamepadDemo: space-shooter canvas game showcasing all four buttons and joystick
- Add Play button to ControlBar to launch demo mode
GamepadDemo.tsx:
- Convert game loop to delta-time (rAF timestamp + dt = min((ts-lastTs)/1000, 0.1))
- All speeds in units/sec, timers in seconds, particles use dt-scaled damping
- Bootstrap frame skips physics on first tick; dt capped at 100ms to survive tab resume

GamepadUI.tsx:
- Add pointer capture in Joystick: setPointerCapture on start, releasePointerCapture on end
  so drags outside the element boundary still track correctly
- Add useEffect to reset state and emit zeroed snapshot when visible becomes false,
  preventing stale button/stick state from persisting after overlay closes

ControlBar.tsx:
- Replace onPointerDown with onClick on Gamepad and Demo toggle buttons for keyboard accessibility
- Add aria-pressed={gamepadOpen} and aria-pressed={demoOpen} to expose toggle state to assistive tech

trackpad.tsx + useGamepad.ts + websocket.ts:
- Restore useGamepad hook (re-created from deleted file) with GamepadState import
  from GamepadUI instead of the removed types.tsx definition
- Restore sendGamepadState call in handleGamepadStateChange so host receives controller input
- Re-add 'gamepad' to VALID_INPUT_TYPES whitelist in websocket.ts

InputHandler.ts:
- Fix held-stick bug: derive dx/dy from current deflection (currLeftX * SCALE)
  instead of packet-to-packet delta so holding stick moves cursor continuously
- Add payload validation/normalisation in handleGamepad: clamp axis values to [-1,1],
  coerce to Number with 0 fallback, guard buttons object, use safe ?. / ?? lookups
  throughout to prevent NaN or throws from malformed packets
- GamepadUI: setPointerCapture on button onPointerDown + onLostPointerCapture
  handler; removes onPointerLeave so held touches are never cancelled by drag
- useGamepad: replace drop-on-throttle with pendingState ref + delayed flush
  so the last state in every throttle window is always delivered
- InputHandler: remove early return on null prev; use zeroed baseline instead
  so first-packet button presses are never dropped
- InputHandler: replace single previousGamepadState field with per-socket Map
  to eliminate cross-client state leakage; add clearSocketState() method
- websocket: pass ws socket to handleMessage; call clearSocketState on close
- InputHandler: add LT/RT release-edge detection; key handler respects
  press=true/false for hold vs release vs tap semantics
@coderabbitai

coderabbitai Bot commented Mar 9, 2026

Copy link
Copy Markdown
Contributor

Caution

Review failed

Pull request was closed or merged during review

Walkthrough

This PR adds gamepad/controller input support to the application, including new UI components for on-screen joystick and buttons, a game demo component, state management with debouncing, and server-side input handling with button mapping and deadzone normalization.

Changes

Cohort / File(s) Summary
Configuration
biome.json
Extended ignore list to include generated src/tokens.json file.
Electron App Setup
electron/main.cjs
Added session/permission handling, strict webPreferences (contextIsolation, nodeIntegration), screen-capture permission checks for localhost:3000, window lifecycle management, and app.activate handler for macOS.
Gamepad UI Components
src/components/Gamepad/GamepadUI.tsx, src/components/Gamepad/GamepadDemo.tsx
Introduced GamepadUI with drag-based joystick and four colorized action buttons synced to GamepadState; added GamepadDemo mini-game with arcade-style rendering, collision detection, scoring, wave progression, and real-time gamepad input processing via requestAnimationFrame.
UI Integration
src/components/Trackpad/ControlBar.tsx
Added gamepadOpen, onGamepadToggle, demoOpen, and onDemoToggle props; rendered Gamepad and Demo toggle buttons with active state styling.
Gamepad State Management
src/hooks/useGamepad.ts
Introduced useGamepad hook that debounces/throttles GamepadState updates before dispatching over remote connection, with diffing to avoid redundant sends and 16ms throttle window.
Route Integration
src/routes/trackpad.tsx
Integrated GamepadUI and GamepadDemo components with visibility toggles; added gamepad state synchronization via useGamepad hook; updated ControlBar with gamepad/demo toggle props.
Type Definitions
src/types.tsx
Added GamepadState interface (left/right sticks, button map), GamepadMessage type, and extended InputMessageType union to include "gamepad".
Server Input Handling
src/server/InputHandler.ts, src/server/websocket.ts
Implemented gamepad message handling with per-socket state tracking, deadzone normalization, movement delta computation, and button-to-action mapping (a/b/x/y/lb/rb/lt/rt/dpad); integrated WebSocket instance passing to correlate input with connections; added clearSocketState lifecycle cleanup.

Sequence Diagram

sequenceDiagram
    participant User
    participant GamepadUI
    participant useGamepad
    participant WebSocket as WebSocket (Client)
    participant WSServer as WebSocket (Server)
    participant InputHandler

    User->>GamepadUI: Interact (joystick/buttons)
    GamepadUI->>GamepadUI: Update internal state
    GamepadUI->>useGamepad: onStateChange(gamepadState)
    useGamepad->>useGamepad: Diff & throttle check
    alt Throttle window passed or forced flush
        useGamepad->>WebSocket: Send gamepad message
    else Within throttle window
        useGamepad->>useGamepad: Queue as pending
        useGamepad->>useGamepad: Schedule debounced flush
    end
    WebSocket->>WSServer: Transmit gamepad message
    WSServer->>InputHandler: handleMessage(msg, ws)
    InputHandler->>InputHandler: Apply deadzone normalization
    InputHandler->>InputHandler: Detect button state changes
    InputHandler->>InputHandler: Generate move/key events
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~70 minutes

Possibly related PRs

Suggested labels

Typescript Lang

Poem

🎮 A joystick springs to life,
Buttons dance in digital light,
The rabbit hops with delight—
Input blooms where code took flight! ✨

🚥 Pre-merge checks | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description documents the permission handling changes clearly but omits mention of the extensive gamepad UI/demo features, hooks, and server-side input handler changes present in the changeset. Update the description to include all major changes: gamepad UI components, GamepadDemo, useGamepad hook, and InputHandler modifications. Alternatively, split the gamepad feature into a separate PR if intended as distinct work.
Title check ❓ Inconclusive The PR title accurately describes the main fix: adding display-capture permission handling in Electron builds. However, the changeset includes substantial additional features (gamepad UI, demo component, input handler enhancements) that are not mentioned in the title. The title focuses on the permission fix but omits the significant gamepad input feature addition. Consider clarifying whether this PR should address both concerns or be split into separate PRs.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@Muneerali199 Muneerali199 deleted the fix/screen-mirror-v2 branch March 9, 2026 08:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant