macOS: cached CGMainDisplayID goes stale after display re-enumeration; all mouse input collapses to (0,0)

Đang mở
#150 1 bình luận 0 reaction 0 người được giao Xem trên GitHub

Chưa có ai nhận issue này.

Đánh giá

Độ khó
3/5
Thời gian dự kiến
1-2 ngày
Mức phù hợp với người mới
68/100
Loại issue
Lỗi
Độ rõ ràng
Khá rõ ràng
Mức độ hoạt động
Sôi nổi
Công nghệ
cpp, macos
Lĩnh vực
desktop, operating-systems

Hướng nghiên cứu

Start in macos_backend.cpp around line 387 and trace MacosInputState, submit_absolute_motion(), and post_mouse(), focusing on how the cached display ID is used after display re-enumeration. Reproduce the monitor reconnect scenario and verify that both absolute and relative mouse input continue to map to the current display rather than a zero-sized bounds rectangle.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

Bug

On macOS, MacosInputState caches CGMainDisplayID() once at construction (macos_backend.cpp:387). When the display later re-enumerates (monitor power cycle, DisplayPort link renegotiation), macOS assigns a new display ID and the cached ID becomes invalid. From that point on:

  • submit_absolute_motion() calls CGDisplayBounds(state_->display) on the stale ID, which returns a zero rect. scale_absolute_axis() then returns 0 for display_size <= 0, so every absolute mouse event is mapped to (0,0) — the cursor is pinned to the top-left corner.
  • post_mouse() clamps the target location into that same zero rect (std::clamp(raw, origin, origin + size - 1)), so relative motion is also trapped — observed cursor positions oscillate only between (0,0) and (-1,-1).

Restarting the consumer process (re-creating the state, hence re-caching the current display ID) restores input until the next display re-enumeration.

Evidence (observed via Sunshine v2026.914.233613 on Mac mini M4, macOS arm64)

  • Main display ID changes across monitor reconnects: 10 → 12 → 1 over consecutive days.
  • While the bug is active:
    • CGDisplayBounds(staleId 12)(0,0,0,0)
    • CGDisplayBounds(CGMainDisplayID() = 1)(0,0,1920,1080)
    • Client input packets arrive (UDP control channel has traffic), video capture is unaffected (capture re-enumerates per session), but the cursor never leaves the origin.
  • After restarting Sunshine, input works again — until the display ID changes once more.

Reproduction

  1. Start a libvirtualhid consumer (e.g. Sunshine) and note the main display ID.
  2. Force the display to re-enumerate: power-cycle the monitor, or unplug/replug it (many DP/USB-C monitors do this on their own when entering deep sleep).
  3. Send absolute or relative mouse input — cursor stays pinned at (0,0).

Suggested fix

Either:

  • Resolve the display at event time (CGMainDisplayID() in submit_absolute_motion / post_mouse instead of the cached value), or
  • Register CGDisplayRegisterReconfigurationCallback and update the cached display / display_scaling on reconfiguration events.

Additionally, guard against zero-sized CGDisplayBounds results (invalid/offline display) instead of clamping into a degenerate rect — e.g. fall back to CGMainDisplayID() bounds.

Happy to provide more diagnostics if needed.

Ngôn ngữ chính
C++
Star
57
Fork
15
Merge trung bình
11 giờ 15 phút
Pull request đã merge (30 ngày)
33

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của LizardByte/libvirtualhid

Tất cả issue của LizardByte/libvirtualhid

Issue tương tự

Thêm issue về C++

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.