Skip to content

feat(devices): add Logitech Signature M650 - #116

Open
abdallah-azzouni wants to merge 6 commits into
mmaher88:masterfrom
abdallah-azzouni:feature/adding-M650
Open

feat(devices): add Logitech Signature M650#116
abdallah-azzouni wants to merge 6 commits into
mmaher88:masterfrom
abdallah-azzouni:feature/adding-M650

Conversation

@abdallah-azzouni

Copy link
Copy Markdown

Adds device descriptor for the Logitech Signature M650 (PID 0xb02a).

Verified on hardware via Bolt receiver on Linux (Nobara/Fedora).

Features confirmed via Solaar:

  • Battery: UNIFIED BATTERY {1004} ✓
  • Adjustable DPI: {2201}, range 400–4000, step 100 ✓
  • Reprogrammable controls: REPROG CONTROLS V4 {1B04} ✓
  • Low-res wheel: LOWRES WHEEL {2130} ✓
  • No SmartShift, no HiRes wheel, no thumb wheel, no gesture button

Controls (CIDs from live device):

  • Left/Right click (non-configurable)
  • Middle click, Back, Forward (configurable)

Status set to beta pending maintainer verification.
All 737 tests pass.

Copilot AI review requested due to automatic review settings May 1, 2026 11:28

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds support metadata for the Logitech Signature M650 (PID 0xb02a) by introducing a new device descriptor and registering it in the test/device listing surfaces.

Changes:

  • Add new devices/m650/descriptor.json descriptor (plus images) defining features, DPI range, controls, and hotspots for “Signature M650”.
  • Extend the device registry test matrix (kDevices[]) to include “Signature M650” coverage.
  • Add “Signature M650” to the Supported Devices table in README.md.

Reviewed changes

Copilot reviewed 3 out of 6 changed files in this pull request and generated 1 comment.

File Description
tests/test_device_registry.cpp Adds a new DeviceSpec entry for “Signature M650” and reformats the file.
devices/m650/descriptor.json Introduces the Signature M650 descriptor (features/DPI/controls/hotspots/images).
README.md Adds Signature M650 row to the supported devices table.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread devices/signature-m650/descriptor.json
@abdallah-azzouni
abdallah-azzouni force-pushed the feature/adding-M650 branch 2 times, most recently from b40c3cb to 21b11c3 Compare May 1, 2026 11:53
@abdallah-azzouni
abdallah-azzouni requested a review from Copilot May 1, 2026 12:05

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new device descriptor to support the Logitech Signature M650 (PID 0xb02a) within the existing JSON-driven device registry, along with registry tests and README documentation updates.

Changes:

  • Added devices/signature-m650/descriptor.json (plus referenced images) describing features, controls, hotspots, and DPI range for the Signature M650.
  • Extended tests/test_device_registry.cpp coverage by registering the new PID/name/spec expectations.
  • Updated the Supported Devices table in README.md to include Signature M650 (Beta).

Reviewed changes

Copilot reviewed 3 out of 6 changed files in this pull request and generated 2 comments.

File Description
tests/test_device_registry.cpp Adds a DeviceSpec entry for PID 0xb02a to validate registry loading and key descriptor properties.
devices/signature-m650/descriptor.json Introduces the Signature M650 device descriptor (features/DPI/controls/hotspots/images).
README.md Documents the Signature M650 as a supported (Beta) device in the devices table.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tests/test_device_registry.cpp Outdated
Comment thread devices/signature-m650/descriptor.json

@mmaher88 mmaher88 left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@abdallah-azzouni Thanks for this — the descriptor is in good shape and I validated it end to end before reviewing: rebases cleanly onto master, builds, 737/737 C++ + 9/9 tray tests pass, and both generate-readme-devices.py --check and generate_package_deps.py --check are green. The DeviceSpec entry is present (pid 0xb02a, matching productIds) and covered by the AllDevices instantiation, the three images are valid, and I cross-checked the feature flags against Logitech's published M650 specs — smartShift: false, thumbWheel: false, adjustableDpi with a 400–4000 range, and lowResWheel: true / hiResWheel: false all look right for this tier of mouse.

One change needed before merge:

devices/signature-m650/descriptor.json sets "gestureButton": false inside features, but that key doesn't exist in devices/schema.json. The features object is additionalProperties: false, so the descriptor is not schema-conformant. It's also never parsed — grep for gestureButton in src/core/devices/JsonDevice.cpp turns up nothing, so it's inert JSON rather than a functional bug.

Please either:

  • drop the key (simplest — the M650 has no gesture button, and omitting a flag already means "unsupported"), or
  • rename it to mouseGesture, which is the real, parsed flag, if you meant to declare it explicitly as false.

For reference, the schema's allowed features keys are: adjustableDpi, angleSnapping, battery, colorLedEffects, crown, extendedDpi, extendedReportRate, forceSensingButton, gestureV2, gkey, hapticFeedback, hiResScrolling, hiResWheel, leftRightSwap, lowResWheel, mkeys, mouseGesture, onboardProfiles, persistentRemappableAction, pointerSpeed, reportRate, reprogControls, rgbEffects, smartShift, smoothScroll, surfaceTuning, thumbWheel.

Worth noting this is our gap as much as yours: CI doesn't currently validate descriptors against schema.json, so nothing flagged it automatically. I'm tracking that as a separate improvement.

Once that key is fixed this is good to merge — no code changes needed, it's a clean descriptor-only addition exactly as the capability-dispatch architecture intends. Thanks for contributing a device!

mmaher88 and others added 5 commits August 1, 2026 20:01
…maher88#113)

* feat: semantic action presets with per-DE invocation

Adds a semantic action preset layer so Show Desktop / Task Switcher /
Switch Desktop L/R / Screenshot / Close Window / Calculator actions
fire correctly on the active DE, with profiles portable across DEs and
immune to user shortcut rebinds.

Architecture
- ActionPreset + ActionPresetRegistry in Core/Domain, static catalog
  bundled as Qt resource at :/logitune/actions.json
- IDesktopIntegration::variantKey() and resolveNamedAction(id), each
  DE impl owns its resolution strategy
- KDE: kglobalaccel DBus, binding-independent
- GNOME: gsettings lookup of the user's live binding plus a keystroke
  transform; empty binding returns nullopt so the picker greys out
- Generic: returns nullopt for everything (no portable bindings in v1)
- ButtonAction::PresetRef new type variant; old raw keystroke / DBus /
  app-launch payloads keep working unchanged
- ButtonActionDispatcher resolves PresetRef at fire time on both the
  button-press and gesture-release paths; resolved actions go through
  ActionExecutor::executeAction
- ActionFilterModel has two gates for preset rows: registry support
  and live-binding resolution
- AppRoot owns the registry, loads from resource, injects into KDE
  and GNOME impls
- Gesture sub-direction picker uses a second ActionFilterModel with
  gestureMode set so gesture-incompatible types are filtered out

What changed
- Seven ActionModel rows migrated to PresetRef payloads
- ActionExecutor::parseDBusAction accepts an optional fifth field for
  kglobalaccel's invokeShortcut argument
- ProfileOrchestrator preserves PresetRef across reload (was decaying
  to Default and getting overwritten on next save)
- Gestures now store full ButtonActions; dispatcher gesture-release
  path resolves PresetRef the same way as button-press
- Action picker grouped into category sections (Device, Edit, Media,
  Navigation, Other, System, Window, Workspace)
- Media controls combo flattened: Next track, Previous track, Stop
  are direct keystroke entries
- Picker highlights the currently-bound action; gesture-direction
  picker also highlights Keyboard shortcut for captured combos
- ActionsPanel hosts the gesture sub-form as a contextual loader
  alongside keystrokeComponent and descriptionComponent. The gesture
  button is no longer structurally special: any button assigned
  gesture-trigger uses the same panel
- Window starts at ~70% of available screen with a 1080x720 floor,
  hard minimum 640x480 to keep snap-tiling working

Profile compatibility
- All existing profile payloads (keystroke:, dbus:, app-launch:,
  media:, default, dpi-cycle, smartshift-toggle) keep parsing and
  firing correctly. No auto-upgrade.

Wiki docs (Architecture.md, Adding-a-Desktop-Environment.md, system
overview diagram) updated to document ActionPresetRegistry,
variantKey(), resolveNamedAction(), category roles, GestureActionModel,
and per-DE resolution strategy.

Closes mmaher88#110

* docs(wiki): reflect dual ActionFilterModel + ActionPresetRegistry in diagrams

Architecture.md updates picked up after the squash:

- logitune-core row lists ActionPresetRegistry plus the new
  variantKey / resolveNamedAction virtuals on the DE impls.
- MVVM-C diagram adds GestureActionModel to the ViewModel band and
  ActionPresetRegistry + IDesktopIntegration to the Model band, with
  arrows for the preset-variant gate, the live-binding gate, the
  dispatcher's PresetRef resolution, and the IDI -> APR variantData
  lookup.
- Model registration code block uses the real QML names
  (ActionModel, GestureActionModel) and adds the second singleton.
- Surrounding prose explains the two ActionFilterModel instances
  (regular vs gestureMode) and what each filter hides.
- Model registration flowchart renames the AFM node and adds a
  parallel GestureActionModel node.

* feat(actions-panel): match category in search filter

Searching e.g. 'media' now surfaces all media-controls entries even
when the entered text doesn't appear in the action name. Useful when
the user remembers the category but not the exact action label.
…efaults.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@abdallah-azzouni

Copy link
Copy Markdown
Author

@mmaher88 Thanks for the thorough review. I removed the gestureButton key from descriptor.json. it's not in the schema and wasn't being parsed anywhere, so dropping it was the simplest fix. Should be schema-conformant now and ready for another look.

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.

3 participants