Skip to content

NSEvent/xbox-controller-mapper

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

919 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

English | 简体中文

ControllerKeys — Gamepad-to-Keyboard Remapper for macOS

A native macOS app that remaps game controllers to keyboard shortcuts, mouse input, macros, scripts, webhooks, and system commands — turning any gamepad into a full desktop input device. Supports Xbox Series X|S, Xbox Elite Series 2, PS5 DualSense, PS4 DualShock 4, Nintendo Joy-Con, Switch Pro Controller, and 300+ third-party gamepads. Features DualSense touchpad and gyroscope mouse control, swipe typing, a JavaScript scripting engine, and per-app profile auto-switching.

Website & Documentation | Download | Discord Community

ControllerKeys - Button Mappings

Use Cases

  • Vibe coding from the couch — map shortcuts, run macros, and pair with voice transcription (e.g., VoiceInk) for full hands-free coding
  • Couch computing & media browsing — navigate macOS, switch apps, scroll, and type from across the room
  • Accessibility — alternative input for users who can't use a keyboard/mouse; works with macOS Accessibility Zoom
  • Streaming & content creation — trigger OBS scenes, mute/unmute, fire webhooks, and show button overlays on stream
  • Presentations — laser pointer overlay, app switching, and clicker-style navigation with any gamepad

Why This App?

There are other controller mapping apps for macOS, but none offered everything I needed:

Feature ControllerKeys Joystick Mapper Enjoyable Controlly
DualSense touchpad + quadrant mapping
Multi-touch gestures (tap, pinch, pan)
Gyroscope aiming & gesture detection
JavaScript scripting engine
Swipe typing on-screen keyboard
Chord mappings (button combos)
Button sequence combos
Layers (alternate mapping sets)
Per-mapping haptic feedback
Macros & system commands
HTTP webhooks & OBS control
On-screen keyboard & command wheel
Community profiles (25+)
App-specific profile auto-switching
Stream overlay for OBS
Xbox Elite Series 2 paddles
Nintendo Joy-Con & Pro Controller
DualSense Edge (Pro) support
DualShock 4 (PS4) touchpad & gyro
DualSense LED & microphone control
Drag-and-drop mapping swap
Usage stats & Controller Wrapped
Third-party controllers (~313)
Native Apple Silicon
Actively maintained (2026)
Open source

Joystick Mapper hasn't been updated in years and lacks modern controller support. Enjoyable is abandoned since 2014. Controlly is solid but doesn't support touchpad gestures, on-screen keyboard, or scripting. Steam's controller mapping only works within Steam games, not system-wide.

Features

  • Button Mapping: Map any controller button to keyboard shortcuts

    • Modifier-only mappings (⌘, ⌥, ⇧, ⌃)
    • Key-only mappings
    • Modifier + Key combinations
    • Long-hold for alternate actions
    • Double-tap for additional actions
    • Simulate key repeat while held (for games that need repeated key-down events)
    • Chording (multiple buttons → single action)
    • Button sequences (ordered combos, e.g., Up-Up-Down-Down)
    • Per-mapping haptic feedback
    • Custom hints to label your mappings
    • Drag-and-drop to swap mappings between buttons
    • Hover connector lines between buttons and their actions
  • Layers: Create alternate button mapping sets activated by holding a designated button

    • Up to 3 layers total (base + 2 additional)
    • Momentary activation while holding the activator button
    • Fallthrough behavior for unmapped buttons
    • Name your layers (e.g., "Combat Mode", "Navigation")
    • Per-layer lightbar color on DualSense/DualShock 4 (auto-assigned from a 12-color palette)
  • JavaScript Scripting: Write custom automation scripts powered by JavaScriptCore

    • Full API: press(), hold(), click(), type(), paste(), delay(), shell(), openURL(), openApp(), notify(), haptic(), and more
    • App-aware scripting with app.name, app.bundleId, app.is() for context-sensitive actions
    • Trigger context (trigger.button, trigger.pressType, trigger.holdDuration)
    • screenshotWindow() API for capturing the focused window
    • Per-script persistent state that survives across invocations
    • Built-in example gallery with ready-to-use scripts
    • Script editor with syntax reference and AI prompt assistant
  • Macros: Multi-step action sequences

    • Key Press, Type Text, Delay, Paste, Shell Command, Webhook, and OBS steps
    • Configurable typing speed
    • Assignable to buttons, chords, long-hold, and double-tap
  • System Commands: Automate actions beyond key presses

    • Launch App: Open any application
    • Shell Command: Run terminal commands silently or in a terminal window
    • Open Link: Open URLs in your default browser
  • HTTP Webhooks: Send HTTP requests from controller buttons and chords

    • Supports GET, POST, PUT, DELETE, and PATCH methods
    • Configurable headers and request body
    • Response handling with configurable retry (exponential backoff), timeout, and follow-up shell commands
    • Visual feedback showing response status above cursor
    • Haptic feedback on success or failure
  • OBS WebSocket Commands: Control OBS Studio directly from controller buttons

  • Joystick Control:

    • Left joystick → Mouse movement (or WASD keys)
    • Right joystick → Scrolling (or Arrow keys)
    • Configurable sensitivity and deadzone
    • Hold modifier (RT by default) for precise mouse movement with cursor highlight
    • Disable option to turn off stick input entirely
  • Gyroscope Aiming & Gestures (DualSense/DualShock 4):

    • Gyro aiming: Use the gyroscope for precise mouse control in focus mode
    • 1-Euro filter for jitter-free smoothing with responsive tracking
    • Gesture mappings: Tilt forward/back and steer left/right to trigger actions
    • Per-profile gesture sensitivity and cooldown sliders
    • DualShock 4 gyro parsed from raw HID reports with auto-calibration
  • Touchpad Control (DualSense/DualShock 4):

    • Single-finger tap or click → Left click
    • Two-finger tap or click → Right click
    • Two finger swipe → Scrolling
    • Two finger pinch → Zoom in/out
    • Quadrant remapping: Split the touchpad into 4 regions with separate touch and click actions
  • On-Screen Keyboard, Commands, and Apps: Use the on-screen keyboard widget to quickly select apps, commands, or keyboard keys

    • Swipe typing: Slide across letters to type words (SHARK2 algorithm)
    • D-pad navigation with floating highlight
    • Easily enter configurable text strings and commands in Terminal with a single click
    • Use built-in variables to customize text output
    • Show and hide apps in customizable app bar
    • Website links with favicons
    • Media key controls (playback, volume, brightness)
    • Global keyboard shortcut to toggle visibility
    • Auto-scaling to fit smaller displays
  • Command Wheel: GTA 5-inspired radial menu for quick app/website switching

    • Navigate with right stick, release to activate
    • Haptic feedback during navigation
    • Modifier key to toggle between apps and websites
    • Force quit and new window actions at full stick deflection
  • Stream Overlay for OBS: Floating overlay showing active button presses for stream capture

  • Laser Pointer Overlay: On-screen pointer for presentations

  • Directory Navigator: Controller-driven file browser overlay

    • Right stick navigation, B to confirm, Y to dismiss
    • Mouse support and position memory
  • Cursor Hints: Visual feedback showing executed actions above the cursor

    • Shows action name or macro name when buttons are pressed
    • Badges for double-tap (2×), long-press (⏱), and chord (⌘) actions
    • Held modifier feedback with purple "hold" badge
  • Controller Wrapped: Usage stats with shareable personality-typed cards

    • Track every button press, macro, webhook, app launch, and more
    • Streak tracking and personality typing based on usage patterns
    • Copy shareable card to clipboard for social media
  • Profile System: Create and switch between multiple mapping profiles

    • Community profiles: Browse and import pre-made profiles
    • App-specific auto-switching: Link profiles to applications
    • Stream Deck V2 profile import
    • Custom profile icons
  • Visual Interface: Interactive controller-shaped UI for easy configuration

    • Auto-scaling UI based on window size
    • Button mapping swap to quickly exchange mappings between two buttons
    • VoiceOver accessibility support
  • DualSense Support: Full PlayStation 5 DualSense controller support

    • Full touchpad support with multi-touch gestures and quadrant remapping
    • Gyroscope aiming and gesture detection
    • Customizable LED colors over USB and Bluetooth
    • Per-layer lightbar colors
    • DualSense built-in microphone support in USB connection mode
    • Microphone mute button mapping
    • Battery notifications at low (20%), critical (10%), and fully charged (100%)
    • Battery-level lightbar with charging animation
  • DualSense Edge (Pro) Support: Full support for Edge-specific controls

    • Function buttons and paddles
    • Edge buttons available as layer activators
  • DualShock 4 (PS4) Support: Full PlayStation 4 DualShock 4 support

    • Touchpad mouse control and gestures (same as DualSense)
    • Lightbar color control over USB and Bluetooth
    • Gyroscope aiming and gesture detection (parsed from raw HID reports)
    • PlayStation-style button labels and icons throughout the UI
    • PS button support via HID monitoring (USB and Bluetooth)
  • Xbox Elite Series 2 Support: Full support for Elite-specific hardware

    • All 4 back paddles (P1–P4) detected and mappable
    • Guide button works over Bluetooth via IOKit HID
    • Correct controller name and UI regardless of firmware version
    • Works with both Classic BT and BLE firmware variants
  • Nintendo Controller Support: Joy-Con and Pro Controller

    • Single Joy-Con, paired Joy-Cons (L+R), and Pro Controller
    • Correct Nintendo button labels (L/R, ZL/ZR, +/−, Capture, Home)
    • Single Joy-Con input via physical input profile enumeration
  • Third-Party Controller Support: ~313 controllers supported via SDL database

    • 8BitDo, Logitech, PowerA, Hori, and more
    • No manual configuration needed
  • Accessibility Zoom Support: Controller input works correctly when macOS Accessibility Zoom is active

    • Cursor, clicks, and scroll positions properly scaled to zoomed coordinates
  • Controller Lock Toggle: Lock/unlock all controller input with haptic feedback

    • Lightbar turns red and menu bar icon shows lock indicator while locked
  • Hide Dock Icon: Option to run as a menu-bar-only app

More Screenshots

Xbox Series X|S

Chord Mappings

Xbox Chord Mappings

Joystick Settings

Xbox Joystick Settings

On Screen Keyboard Widget

On Screen Keyboard Widget

On-Screen Keyboard

Xbox On-Screen Keyboard

DualSense (PS5)

Button Mappings

DualSense Button Mappings

Chord Mappings

DualSense Chord Mappings

Joystick Settings

DualSense Joystick Settings

On Screen Keyboard Widget

DualSense On Screen Keyboard Widget

Touchpad Settings

DualSense Touchpad Settings

Multi-touch Touchpad

DualSense Multi-touch

LED Customization

DualSense LEDs

Microphone Settings

DualSense Microphone Settings

On-Screen Keyboard

DualSense On-Screen Keyboard

Supported Controllers

Brand Controllers
Xbox Series X|S, Xbox One, Xbox 360, Xbox Elite Series 2 (with paddles)
PlayStation DualSense (PS5), DualSense Edge, DualShock 4 v1/v2 (PS4)
Nintendo Switch Pro Controller, Joy-Con (single or paired L+R)
8BitDo Pro 2, SN30 Pro, SN30 Pro+, Ultimate, Lite, Zero 2, and more
Logitech F310, F510, F710
PowerA Enhanced Wired, Fusion Pro
Hori HORIPAD, Fighting Commander, and more
Others ~313 controllers total via SDL gamecontrollerdb

Any controller recognized by macOS's GameController framework works out of the box. Unrecognized controllers fall back to the SDL database for automatic button mapping.

Requirements

  • macOS 14.0 or later
  • A supported controller (see above) connected via Bluetooth or USB
  • Accessibility permissions (for input simulation)
  • Automation permissions (for launching Terminal app with commands)

Installation

Download ControllerKeys - Get the latest signed and notarized build.

  1. Purchase and download the DMG from Gumroad
  2. Open the DMG and drag the app to /Applications
  3. Launch and grant Accessibility permissions when prompted
  4. Automation permissions will be requested when using terminal commands from the on-screen keyboard

The app is signed with an Apple Developer ID certificate and notarized by Apple, so it will run without Gatekeeper warnings.

Trust & Transparency

This app requires Accessibility permissions to simulate keyboard and mouse input. We understand this is a sensitive permission, which is why this project is fully open source.

Why this app is safe:

  • Open Source: The complete source code is available for audit. You can verify exactly what the app does with your input data.

  • No Telemetry or Phoning Home: The app never contacts any server on its own. Network access only occurs when you explicitly configure webhooks, OBS WebSocket commands, or community profile imports.

  • No Data Collection: The app does not log, store, or transmit any input data. Controller inputs are translated to keyboard/mouse events in real-time and immediately discarded.

  • Signed & Notarized: Releases are signed with an Apple Developer ID certificate and notarized by Apple, ensuring the binary matches the source code and hasn't been tampered with.

What the Accessibility permission is used for:

  • Simulating keyboard key presses (when you press controller buttons)
  • Simulating mouse movement (when you move the left joystick)
  • Simulating scroll wheel events (when you move the right joystick)

The app uses Apple's CGEvent API to generate these input events. This is the same API used by accessibility tools, automation software, and other input remapping utilities.

Project Structure

XboxControllerMapper/
├── XboxControllerMapperApp.swift      # App entry point
├── Info.plist                          # App configuration
├── XboxControllerMapper.entitlements   # Sandbox/permissions
│
├── Models/
│   ├── ControllerButton.swift          # Xbox button enum
│   ├── KeyMapping.swift                # Mapping configuration
│   ├── Profile.swift                   # Profile with overrides
│   ├── ChordMapping.swift              # Multi-button chords
│   └── JoystickSettings.swift          # Joystick configuration
│
├── Services/
│   ├── ControllerService.swift         # Controller connection
│   ├── InputSimulator.swift            # Key/mouse simulation
│   ├── ProfileManager.swift            # Profile persistence
│   ├── AppMonitor.swift                # Frontmost app detection
│   └── MappingEngine.swift             # Mapping coordination
│
├── Views/
│   ├── MainWindow/
│   │   ├── ContentView.swift           # Main window
│   │   ├── ControllerVisualView.swift  # Controller visualization
│   │   └── ButtonMappingSheet.swift    # Button configuration
│   ├── MenuBar/
│   │   └── MenuBarView.swift           # Menu bar popover
│   └── Components/
│       └── KeyCaptureField.swift       # Shortcut capture
│
└── Utilities/
    └── KeyCodeMapping.swift            # Key code constants

Default Mappings

Button Default Action
A Return/Enter
B Escape
X Space
Y Tab
LB ⌘ (hold)
RB ⌥ (hold)
LT ⇧ (hold)
RT ⌃ (hold)
D-pad Arrow keys
Menu ⌘ + Tab
View Mission Control
Xbox Launchpad
L-Stick Click Left Click
R-Stick Click Right Click
Left Joystick Mouse
Right Joystick Scroll

Usage

  1. Connect your controller via Bluetooth or USB (System Settings → Bluetooth)
  2. Launch ControllerKeys
  3. Grant Accessibility permissions when prompted
  4. Click any button on the controller visualization to configure its mapping
  5. Use the menu bar icon for quick access to enable/disable and profile switching

Contributing

Contributions are welcome! If you'd like to contribute code:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes
  4. Test thoroughly with both Xbox and DualSense controllers if possible and applicable
  5. Commit your changes (git commit -m 'Add amazing feature')
  6. Push to the branch (git push origin feature/amazing-feature)
  7. Open a Pull Request

Please ensure your code follows the existing style and includes appropriate comments for complex logic.

Community

Join the ControllerKeys Discord to share profiles, get help, and connect with other users.

Feature Requests

Have an idea for a new feature? I'd love to hear it!

  • Open an issue on GitHub with the feature request label
  • Describe the feature and the problem it solves
  • Include any mockups or examples if applicable

Popular requests are more likely to be implemented. Feel free to upvote existing feature requests that you'd find useful.

Issues & Bug Reports

Found a bug? Please help by reporting it:

  1. Check existing issues to avoid duplicates
  2. Open a new issue with:
    • macOS version
    • Controller model (Xbox Series X|S, Xbox One, DualSense, etc.)
    • Connection method (Bluetooth or USB)
    • Steps to reproduce the issue
    • Expected vs actual behavior
    • Screenshots if applicable

The more detail you provide, the easier it is to diagnose and fix the issue.

License

Source Available - See LICENSE for details.

The source code is open for transparency and security auditing. Official binaries are available for purchase on Gumroad.

Star History

Star History Chart