### Build and Install libmanette Source: https://github.com/gnome/libmanette/blob/main/README.md Use these commands to build and install the libmanette library using Meson. ```bash meson build cd build ninja ninja install ``` -------------------------------- ### Build and Install libmanette Source: https://context7.com/gnome/libmanette/llms.txt Configure, build, and install libmanette using Meson. Optional features like GUdev, demo applications, tests, and introspection can be enabled during configuration. ```sh # Configure, build, and install Meson setup build cd build ninja sudo ninja install # Optional build features Meson setup build \ -Dgudev=enabled \ -Ddemoes=true \ -Dbuild-tests=true \ -Dintrospection=true \ -Dvapi=true ninja -C build ``` -------------------------------- ### ManetteMonitor Example Source: https://context7.com/gnome/libmanette/llms.txt This example demonstrates how to use `ManetteMonitor` to detect connected and disconnected devices, and how to connect to `button-pressed` signals from `ManetteDevice` objects. ```APIDOC ## ManetteMonitor - Device Discovery and Hot-Plug ### Description Monitors for connected gamepads, loads SDL mappings, and emits `device-connected` and `device-disconnected` signals. It also shows how to listen for `button-pressed` events on connected devices. ### Code Example ```c #include #include static void on_button_pressed (ManetteDevice *device, ManetteButton button, gpointer user_data) { g_print ("Button pressed: %d on device '%s'\n", button, manette_device_get_name (device)); } static void on_device_connected (ManetteMonitor *monitor, ManetteDevice *device, gpointer user_data) { g_print ("Device connected: %s (GUID: %s)\n", manette_device_get_name (device), manette_device_get_guid (device)); /* Listen for button events on every newly connected device */ g_signal_connect (device, "button-pressed", G_CALLBACK (on_button_pressed), NULL); } static void on_device_disconnected (ManetteMonitor *monitor, ManetteDevice *device, gpointer user_data) { g_print ("Device disconnected: %s\n", manette_device_get_name (device)); } int main (void) { g_autoptr (ManetteMonitor) monitor = manette_monitor_new (); g_autoptr (GMainLoop) loop = g_main_loop_new (NULL, FALSE); g_signal_connect (monitor, "device-connected", G_CALLBACK (on_device_connected), NULL); g_signal_connect (monitor, "device-disconnected", G_CALLBACK (on_device_disconnected), NULL); g_main_loop_run (loop); /* blocks; signals fired on the GLib main loop */ return 0; } ``` ``` -------------------------------- ### Get libmanette Version Source: https://context7.com/gnome/libmanette/llms.txt This example shows how to retrieve the major, minor, and micro versions of the libmanette library that the application was compiled against. It also includes a compile-time version guard. ```APIDOC ## Get libmanette Version ### Description Retrieve the runtime version of the libmanette library and include a compile-time version check. ### Code Example ```c #include int main (int argc, char *argv[]) { /* Verify the runtime version matches what was compiled against */ g_print ("libmanette %u.%u.%u\n", manette_get_major_version (), manette_get_minor_version (), manette_get_micro_version ()); /* Compile-time version guard */ #if !MANETTE_CHECK_VERSION(0, 2, 0) # error "libmanette >= 0.2.0 required" #endif return 0; } ``` ``` -------------------------------- ### Include libmanette and Check Version Source: https://context7.com/gnome/libmanette/llms.txt Include the main header file `` and verify the runtime and compile-time versions of the library. This example demonstrates how to print the library version and use a compile-time version guard. ```c #include int main (int argc, char *argv[]) { /* Verify the runtime version matches what was compiled against */ g_print ("libmanette %u.%u.%u\n", manette_get_major_version (), manette_get_minor_version (), manette_get_micro_version ()); /* Compile-time version guard */ #if !MANETTE_CHECK_VERSION(0, 2, 0) # error "libmanette >= 0.2.0 required" #endif return 0; } ``` -------------------------------- ### Monitor Gamepad Connections and Events Source: https://context7.com/gnome/libmanette/llms.txt This example demonstrates how to use `ManetteMonitor` to discover connected gamepads, receive notifications for device connections and disconnections, and listen for button press events. ```c #include #include static void on_button_pressed (ManetteDevice *device, ManetteButton button, gpointer user_data) { g_print ("Button pressed: %d on device '%s'\n", button, manette_device_get_name (device)); } static void on_device_connected (ManetteMonitor *monitor, ManetteDevice *device, gpointer user_data) { g_print ("Device connected: %s (GUID: %s)\n", manette_device_get_name (device), manette_device_get_guid (device)); /* Listen for button events on every newly connected device */ g_signal_connect (device, "button-pressed", G_CALLBACK (on_button_pressed), NULL); } static void on_device_disconnected (ManetteMonitor *monitor, ManetteDevice *device, gpointer user_data) { g_print ("Device disconnected: %s\n", manette_device_get_name (device)); } int main (void) { g_autoptr (ManetteMonitor) monitor = manette_monitor_new (); g_autoptr (GMainLoop) loop = g_main_loop_new (NULL, FALSE); g_signal_connect (monitor, "device-connected", G_CALLBACK (on_device_connected), NULL); g_signal_connect (monitor, "device-disconnected", G_CALLBACK (on_device_disconnected), NULL); g_main_loop_run (loop); /* blocks; signals fired on the GLib main loop */ return 0; } ``` -------------------------------- ### manette_monitor_new Source: https://context7.com/gnome/libmanette/llms.txt Creates a new `ManetteMonitor` instance, which starts scanning for gamepads and monitoring for hot-plug events immediately. ```APIDOC ## manette_monitor_new ### Description Creates a new `ManetteMonitor` that begins scanning for connected gamepads and watching for hot-plug events. It uses the file-based backend in Flatpak or GUdev on native desktops if compiled in. ### Method Signature ```c ManetteMonitor * manette_monitor_new (void); ``` ### Return Value A new `ManetteMonitor` object. The caller owns a reference and should release it with `g_object_unref()` or use `g_autoptr`. ``` -------------------------------- ### Create a ManetteMonitor Instance Source: https://context7.com/gnome/libmanette/llms.txt Instantiate a `ManetteMonitor` object. This object starts scanning for gamepads and monitoring hot-plug events immediately upon creation. Use `g_autoptr` or `g_object_unref` to manage its lifecycle. ```c ManetteMonitor *monitor = manette_monitor_new (); /* monitor now owns a reference; release with g_object_unref() or use g_autoptr */ ``` -------------------------------- ### Good Long Commit Explanation Example Source: https://github.com/gnome/libmanette/blob/main/CONTRIBUTING.md Provide detailed explanations in proper prose, using full sentences and punctuation. ```text This gives manette_my_type_my_method() to ManetteMyType to allow… ``` -------------------------------- ### Bad Long Commit Explanation Example Source: https://github.com/gnome/libmanette/blob/main/CONTRIBUTING.md Avoid breaking sentences across lines unnecessarily and ensure proper prose. ```text Give manette_my_type_my_method() to ManetteMyType to allow… ``` -------------------------------- ### Query libmanette Version at Runtime and Compile Time Source: https://context7.com/gnome/libmanette/llms.txt Check the installed library version at runtime using `manette_get_major_version`, `manette_get_minor_version`, and `manette_get_micro_version`. Also shows how to use compile-time constants and `MANETTE_CHECK_VERSION` for version validation. ```c /* Runtime version — the library actually loaded */ guint major = manette_get_major_version (); guint minor = manette_get_minor_version (); guint micro = manette_get_micro_version (); g_print ("Runtime libmanette: %u.%u.%u\n", major, minor, micro); /* Compile-time version constants */ g_print ("Compiled against: %u.%u.%u\n", MANETTE_MAJOR_VERSION, MANETTE_MINOR_VERSION, MANETTE_MICRO_VERSION); /* Compile-time version check — fail if too old */ #if !MANETTE_CHECK_VERSION(0, 2, 9) # error "libmanette 0.2.9+ required for manette_device_get_mapping()" #endif ``` -------------------------------- ### Get Device GUID Source: https://context7.com/gnome/libmanette/llms.txt Obtain the device's SDL-format GUID using `manette_device_get_guid()`. This 32-character hex string is used for looking up mappings in the SDL `gamecontrollerdb` database. ```c ManetteDevice *dev = /* ... */; const char *guid = manette_device_get_guid (dev); g_print ("GUID: %s\n", guid); /* Output: GUID: 030000004c050000cc09000000016800 */ ``` -------------------------------- ### manette_device_get_guid Source: https://context7.com/gnome/libmanette/llms.txt Retrieves the device's SDL-format GUID, a 32-character hex string used for looking up mappings in the SDL gamecontrollerdb database. ```APIDOC ## manette_device_get_guid ### Description Returns the device's SDL-format GUID: a 32-character lowercase hex string derived from bus type, vendor ID, product ID, and version, used to look up mappings in the SDL `gamecontrollerdb` database. ### Method ```c const char *manette_device_get_guid (ManetteDevice *dev); ``` ### Parameters #### Path Parameters - **dev** (ManetteDevice *) - The Manette device to query. ### Request Example ```c ManetteDevice *dev = /* ... */; const char *guid = manette_device_get_guid (dev); g_print ("GUID: %s\n", guid); /* Output: GUID: 030000004c050000cc09000000016800 */ ``` ``` -------------------------------- ### Get Active SDL Mapping String Source: https://context7.com/gnome/libmanette/llms.txt Retrieve the active SDL mapping string for a device using `manette_device_get_mapping()`. This returns the user override if available, otherwise the built-in database entry. The caller owns the returned string and should free it. ```c ManetteDevice *dev = /* ... */; if (manette_device_supports_mapping (dev)) { g_autofree char *mapping = manette_device_get_mapping (dev); if (mapping != NULL) /* Format: ",,,…,platform:Linux" */ g_print ("Mapping: %s\n", mapping); else g_print ("No mapping found for this device\n"); } ``` -------------------------------- ### Get Current Event Time in libmanette Signal Handler Source: https://context7.com/gnome/libmanette/llms.txt Retrieve the kernel timestamp (microseconds since boot) of the event being processed within a signal handler. Use this instead of `g_get_monotonic_time()` to avoid skew from synchronous I/O. ```c static void button_pressed_cb (ManetteDevice *device, ManetteButton button, gpointer user_data) { guint64 event_us = manette_device_get_current_event_time (device); /* Use event_us for timing-sensitive logic, not wall-clock time */ g_print ("Button %d at %" G_GUINT64_FORMAT " µs\n", button, event_us); } ``` -------------------------------- ### Get Human-Readable Device Name Source: https://context7.com/gnome/libmanette/llms.txt Retrieve the human-readable name reported by the kernel driver using `manette_device_get_name()`. The returned pointer is valid for the device's lifetime. Trailing whitespace may be present and can be stripped. ```c ManetteDevice *dev = /* obtained from monitor signal or list_devices */; const char *name = manette_device_get_name (dev); g_autofree char *stripped = g_strstrip (g_strdup (name)); g_print ("Controller: '%s'\n", stripped); /* Output: Controller: 'Sony Interactive Entertainment Wireless Controller' */ ``` -------------------------------- ### Complete GLib Gamepad Application Source: https://context7.com/gnome/libmanette/llms.txt This C code demonstrates a full GLib application that initializes a ManetteMonitor, sets up callbacks for device connections and input events, and runs a main loop to process events. It handles both pre-connected devices and hot-plugging. ```c #include #include static void button_pressed_cb (ManetteDevice *device, ManetteButton button, gpointer user_data) { guint64 t = manette_device_get_current_event_time (device); g_print ("[%%" G_GUINT64_FORMAT "] PRESS button=%%d\n", t, (int) button); } static void button_released_cb (ManetteDevice *device, ManetteButton button, gpointer user_data) { g_print ("RELEASE button=%%d\n", (int) button); } static void axis_changed_cb (ManetteDevice *device, ManetteAxis axis, double value, gpointer user_data) { g_print ("AXIS axis=%%d value=%%.4f\n", (int) axis, value); } static void device_disconnected_cb (ManetteDevice *device, gpointer user_data) { g_print ("DISCONNECTED: %s\n", manette_device_get_name (device)); } static void setup_device (ManetteDevice *device) { g_autofree char *name = g_strstrip (g_strdup (manette_device_get_name (device))); ManetteDeviceType type = manette_device_get_device_type (device); g_print ("CONNECTED: %s GUID=%s type=%s\n", name, manette_device_get_guid (device), type == MANETTE_DEVICE_STEAM_DECK ? "SteamDeck" : "Generic"); g_signal_connect (device, "button-pressed", G_CALLBACK (button_pressed_cb), NULL); g_signal_connect (device, "button-released", G_CALLBACK (button_released_cb), NULL); g_signal_connect (device, "absolute-axis-changed", G_CALLBACK (axis_changed_cb), NULL); g_signal_connect (device, "disconnected", G_CALLBACK (device_disconnected_cb), NULL); /* Rumble test if supported */ if (manette_device_has_rumble (device)) manette_device_rumble (device, 0.5, 0.5, 200); } static void device_connected_cb (ManetteMonitor *monitor, ManetteDevice *device, gpointer user_data) { setup_device (device); } int main (void) { g_autoptr (ManetteMonitor) monitor = manette_monitor_new (); g_autoptr (GMainLoop) loop = g_main_loop_new (NULL, FALSE); g_autofree ManetteDevice **devices = NULL; gsize n_devices, i; /* Handle already-connected devices */ devices = manette_monitor_list_devices (monitor, &n_devices); for (i = 0; i < n_devices; i++) setup_device (devices[i]); /* Handle future hot-plug events */ g_signal_connect (monitor, "device-connected", G_CALLBACK (device_connected_cb), NULL); g_main_loop_run (loop); return 0; } ``` -------------------------------- ### Good Short Commit Explanations Source: https://github.com/gnome/libmanette/blob/main/CONTRIBUTING.md Keep explanations brief, imperative, and without terminal punctuation. Refer to methods and properties concisely. ```text Add HACKING.md gtk: Add ManetteMyType my-type: Add the my_method() method ``` -------------------------------- ### Run libmanette Test Tool Source: https://github.com/gnome/libmanette/blob/main/README.md Execute the manette-test tool from the build directory to display game controller events. ```bash demos/manette-test/manette-test ``` -------------------------------- ### List Connected Gamepad Devices Source: https://context7.com/gnome/libmanette/llms.txt Creates a monitor and retrieves a list of currently connected gamepad devices. Remember to free the returned array after use, but not the devices themselves. ```c g_autoptr (ManetteMonitor) monitor = manette_monitor_new (); gsize n_devices; ManetteDevice **devices = manette_monitor_list_devices (monitor, &n_devices); g_print ("Found %" G_GSIZE_FORMAT " device(s)\n", n_devices); for (gsize i = 0; i < n_devices; i++) { ManetteDevice *dev = devices[i]; g_print (" [%zu] %s GUID=%s\n", i, manette_device_get_name (dev), manette_device_get_guid (dev)); } g_free (devices); /* free the array, not the devices */ ``` -------------------------------- ### Bad Short Commit Explanations Source: https://github.com/gnome/libmanette/blob/main/CONTRIBUTING.md Avoid unnecessary details, punctuation, incorrect casing, and overly verbose phrasing. ```text Add ManetteMyType gtk: Add ManetteMyType. gtk: add ManetteMyType gtk: This adds ManetteMyType my-type: Add manette_my_type_my_method() ``` -------------------------------- ### Static Function Naming Source: https://github.com/gnome/libmanette/blob/main/CONTRIBUTING.md Static functions do not require the class prefix. Virtual methods like init, constructed, finalize, and dispose are exceptions and do take the class prefix. ```c static void button_clicked_cb (GtkButton *button) ``` ```c static void foo_bar_button_clicked_cb (GtkButton *button) ``` -------------------------------- ### Compile libmanette Application Source: https://context7.com/gnome/libmanette/llms.txt This shell command compiles the C application using pkg-config to fetch the necessary compiler and linker flags for libmanette. ```sh gcc $(pkg-config --cflags --libs manette-1) -o gamepad_demo gamepad_demo.c ``` -------------------------------- ### Automatic Resource Cleanup Source: https://github.com/gnome/libmanette/blob/main/CONTRIBUTING.md Use `g_auto()`, `g_autoptr()`, and `g_autofree` for automatic resource cleanup. Ensure there is no space between the attribute and its opening parenthesis. ```c g_autoptr(FooBaz) baz = foo_bar_generate_baz (bar); ``` ```c g_autoptr (FooBaz) baz = foo_bar_generate_baz (bar); ``` ```c FooBaz *baz = foo_bar_generate_baz (bar); … g_object_unref (baz); ``` -------------------------------- ### Check for Supported Buttons and Axes Source: https://context7.com/gnome/libmanette/llms.txt Use `manette_device_has_button()` and `manette_device_has_axis()` to query if a device provides specific inputs after SDL mapping. This is useful for conditionally displaying UI elements or connecting signals. ```c ManetteDevice *dev = /* ... */; if (manette_device_has_button (dev, MANETTE_BUTTON_TOUCHPAD)) g_print ("Touchpad button supported\n"); if (manette_device_has_axis (dev, MANETTE_AXIS_LEFT_TRIGGER)) g_print ("Analog triggers supported\n"); /* Enumerate all buttons and axes present */ for (ManetteButton b = 0; b <= MANETTE_BUTTON_TOUCHPAD; b++) { if (manette_device_has_button (dev, b)) g_print (" Has button %d\n", b); } for (ManetteAxis a = 0; a <= MANETTE_AXIS_RIGHT_TRIGGER; a++) { if (manette_device_has_axis (dev, a)) g_print (" Has axis %d\n", a); } ``` -------------------------------- ### UI Property Naming Convention Source: https://github.com/gnome/libmanette/blob/main/CONTRIBUTING.md Use minus signs instead of underscores in property names within UI files. ```xml 12 ``` ```xml 12 ``` -------------------------------- ### Connect Gamepad Device Signals Source: https://context7.com/gnome/libmanette/llms.txt Connects various GObject signals for a ManetteDevice to handle input events and disconnection. Ensure corresponding callback functions are defined. ```c /* Wire up all the events for a device */ static void connect_device_signals (ManetteDevice *device) { g_signal_connect (device, "button-pressed", G_CALLBACK (on_button_pressed), NULL); g_signal_connect (device, "button-released", G_CALLBACK (on_button_released), NULL); g_signal_connect (device, "absolute-axis-changed", G_CALLBACK (axis_changed_cb), NULL); g_signal_connect (device, "disconnected", G_CALLBACK (on_device_disconnected), NULL); } ``` -------------------------------- ### Version Query Functions Source: https://context7.com/gnome/libmanette/llms.txt Provides functions to query the runtime version of the libmanette library and check against compile-time version constants. ```APIDOC ## Version Query Functions Runtime version inspection functions allow code to adapt behaviour to the installed library version independently of compile-time constants. ```c /* Runtime version — the library actually loaded */ guint major = manette_get_major_version (); guint minor = manette_get_minor_version (); guint micro = manette_get_micro_version (); g_print ("Runtime libmanette: %u.%u.%u\n", major, minor, micro); /* Compile-time version constants */ g_print ("Compiled against: %u.%u.%u\n", MANETTE_MAJOR_VERSION, MANETTE_MINOR_VERSION, MANETTE_MICRO_VERSION); /* Compile-time version check — fail if too old */ #if !MANETTE_CHECK_VERSION(0, 2, 9) # error "libmanette 0.2.9+ required for manette_device_get_mapping()" #endif ``` ``` -------------------------------- ### Control Rumble Effects in libmanette Source: https://context7.com/gnome/libmanette/llms.txt Query if a device supports rumble and activate force-feedback effects. Magnitudes are normalized [0.0, 1.0], and duration is in milliseconds. Returns TRUE on success. ```c ManetteDevice *dev = /* ... */; if (!manette_device_has_rumble (dev)) { g_print ("Rumble not supported\n"); return; } /* Full-power rumble for 500 ms */ gboolean ok = manette_device_rumble (dev, 1.0, 1.0, 500); g_print ("Rumble: %s\n", ok ? "started" : "failed"); /* Gentle, brief pulse — strong motor off, light motor at 30% for 100 ms */ manette_device_rumble (dev, 0.0, 0.3, 100); /* Stop rumble immediately */ manette_device_rumble (dev, 0.0, 0.0, 1); ``` -------------------------------- ### Check if Device Supports SDL Mapping Source: https://context7.com/gnome/libmanette/llms.txt Determine if a device is a generic gamepad (not a Steam Deck) and thus supports SDL mapping strings using `manette_device_supports_mapping()`. This function indicates whether `get_mapping`, `save_user_mapping`, or `remove_user_mapping` can be safely called. ```c ManetteDevice *dev = /* ... */; if (manette_device_supports_mapping (dev)) { g_print ("GUID: %s\n", manette_device_get_guid (dev)); /* Safe to call get_mapping / save_user_mapping / remove_user_mapping */ } else { g_print ("Device uses native driver, no SDL mapping\n"); } ``` -------------------------------- ### manette_device_supports_mapping Source: https://context7.com/gnome/libmanette/llms.txt Determines if a device is a generic gamepad (not a Steam Deck) and thus supports SDL mapping strings and user-defined mappings. ```APIDOC ## manette_device_supports_mapping ### Description Returns `TRUE` when the device is a generic (non-Steam-Deck) device and therefore can have SDL mapping strings applied and user mappings saved. ### Method ```c bool manette_device_supports_mapping (ManetteDevice *dev); ``` ### Parameters #### Path Parameters - **dev** (ManetteDevice *) - The Manette device to query. ### Request Example ```c ManetteDevice *dev = /* ... */; if (manette_device_supports_mapping (dev)) { g_print ("GUID: %s\n", manette_device_get_guid (dev)); /* Safe to call get_mapping / save_user_mapping / remove_user_mapping */ } else { g_print ("Device uses native driver, no SDL mapping\n"); } ``` ``` -------------------------------- ### Function Definition Style Source: https://github.com/gnome/libmanette/blob/main/CONTRIBUTING.md Follow this style for function definitions, ensuring attributes and return types are on a preceding line, and parameters are listed one per line with specific column alignment. ```c static void function (FooBar *bar) ``` ```c static void function (FooBar *bar, char **strings, void *data) ``` ```c static int function (void) ``` ```c static void function () ``` -------------------------------- ### manette_monitor_list_devices Source: https://context7.com/gnome/libmanette/llms.txt Retrieves a snapshot of all currently connected ManetteDevice objects. The returned array is caller-owned and must be freed. ```APIDOC ## manette_monitor_list_devices Returns a snapshot array of all `ManetteDevice` objects currently connected at the time of the call. The returned array is caller-owned (transfer container); the devices themselves are not reffed — they remain owned by the monitor. ```c g_autoptr (ManetteMonitor) monitor = manette_monitor_new (); gsize n_devices; ManetteDevice **devices = manette_monitor_list_devices (monitor, &n_devices); g_print ("Found %" G_GSIZE_FORMAT " device(s)\n", n_devices); for (gsize i = 0; i < n_devices; i++) { ManetteDevice *dev = devices[i]; g_print (" [%zu] %s GUID=%s\n", i, manette_device_get_name (dev), manette_device_get_guid (dev)); } g_free (devices); /* free the array, not the devices */ ``` ``` -------------------------------- ### Structure, Union, and Enumeration Brace Style Source: https://github.com/gnome/libmanette/blob/main/CONTRIBUTING.md The opening curly brace for structures, unions, and enumerations must be on a new line. ```c struct FooBar { ... }; ``` ```c typedef struct { ... } FooBar; ``` ```c struct FooBar { ... }; ``` -------------------------------- ### Valid Commit Tags Source: https://github.com/gnome/libmanette/blob/main/CONTRIBUTING.md Use kebab-case for tags, without file extensions or the 'manette-' prefix. Omit the tag if the change is too global. ```text monitor device meson ci ``` -------------------------------- ### Check for Raw Hardware Input Presence Source: https://context7.com/gnome/libmanette/llms.txt The `manette_device_has_input()` function checks for the presence of raw hardware inputs (Linux `EV_*` type and code), irrespective of SDL mapping. This is valuable for custom mapping tools. ```c #include /* EV_KEY, EV_ABS, BTN_SOUTH, ABS_X, … */ ManetteDevice *dev = /* ... */; /* Check for the "South" face button at the raw evdev level */ if (manette_device_has_input (dev, EV_KEY, BTN_SOUTH)) g_print ("Raw BTN_SOUTH present\n"); /* Check for absolute X axis */ if (manette_device_has_input (dev, EV_ABS, ABS_X)) g_print ("Raw ABS_X present\n"); ``` -------------------------------- ### User Mapping Management Source: https://context7.com/gnome/libmanette/llms.txt Functions to manage per-user mapping overrides for game controllers. These overrides are stored in a configuration file and automatically reloaded. ```APIDOC ## manette_device_has_user_mapping / manette_device_save_user_mapping / manette_device_remove_user_mapping Manage per-user mapping overrides stored in `$XDG_CONFIG_HOME/libmanette/gamecontrollerdb`. Custom mappings persist across sessions and are automatically reloaded by all running `ManetteMonitor` instances when the file changes. ```c ManetteDevice *dev = /* ... */; /* Check if a user override already exists */ if (manette_device_has_user_mapping (dev)) { g_print ("Custom user mapping is active\n"); } else { g_print ("Using built-in mapping\n"); } /* Save a new custom SDL mapping string for this device */ const char *new_mapping = "030000004c050000cc09000000016800,\n" "PS4 Controller,\n" "a:b1,b:b2,x:b0,y:b3,\n" "leftshoulder:b4,rightshoulder:b5,\n" "lefttrigger:a3,righttrigger:a4,\n" "leftx:a0,lefty:a1,rightx:a2,righty:a5,\n" "back:b8,start:b9,guide:b10,\n" "leftstick:b11,rightstick:b12,\n" "dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,\n" "platform:Linux"; manette_device_save_user_mapping (dev, new_mapping); g_print ("Custom mapping saved\n"); /* Remove the user override to fall back to the built-in mapping */ manette_device_remove_user_mapping (dev); g_print ("User mapping removed\n"); ``` ``` -------------------------------- ### Good Issue Reference Format Source: https://github.com/gnome/libmanette/blob/main/CONTRIBUTING.md Reference fixed issues using the 'Fixes $ISSUE_URL' format. ```text Fixes https://gitlab.gnome.org/GNOME/libmanette/-/issues/1 ``` -------------------------------- ### Invalid Commit Tags Source: https://github.com/gnome/libmanette/blob/main/CONTRIBUTING.md Avoid prefixes, file extensions, and inconsistent casing in tags. ```text manette-monitor manette-device Meson.build CI ``` -------------------------------- ### Function Call Spacing Source: https://github.com/gnome/libmanette/blob/main/CONTRIBUTING.md Include a space between the function name and the opening parenthesis for function and macro calls. ```c foo_bar_get_state (FOO_BAR (self->bar)); ``` ```c foo_bar_get_state(FOO_BAR(self->bar)); ``` -------------------------------- ### Manage User Controller Mappings in libmanette Source: https://context7.com/gnome/libmanette/llms.txt Check for, save, and remove custom user mapping overrides for a device. Custom mappings are stored in `$XDG_CONFIG_HOME/libmanette/gamecontrollerdb` and persist across sessions. ```c ManetteDevice *dev = /* ... */; /* Check if a user override already exists */ if (manette_device_has_user_mapping (dev)) { g_print ("Custom user mapping is active\n"); } else { g_print ("Using built-in mapping\n"); } /* Save a new custom SDL mapping string for this device */ const char *new_mapping = "030000004c050000cc09000000016800," "PS4 Controller," "a:b1,b:b2,x:b0,y:b3," "leftshoulder:b4,rightshoulder:b5," "lefttrigger:a3,righttrigger:a4," "leftx:a0,lefty:a1,rightx:a2,righty:a5," "back:b8,start:b9,guide:b10," "leftstick:b11,rightstick:b12," "dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2," "platform:Linux"; manette_device_save_user_mapping (dev, new_mapping); g_print ("Custom mapping saved\n"); /* Remove the user override to fall back to the built-in mapping */ manette_device_remove_user_mapping (dev); g_print ("User mapping removed\n"); ``` -------------------------------- ### Function Body Brace Style Source: https://github.com/gnome/libmanette/blob/main/CONTRIBUTING.md The opening curly brace for function bodies must be on a new line. ```c static void function (...) { ... } ``` ```c static void function (...) { ... } ``` -------------------------------- ### manette_device_get_mapping Source: https://context7.com/gnome/libmanette/llms.txt Retrieves the active SDL mapping string for the device, which can be a user override or a built-in entry. Returns NULL if no mapping is available or supported. ```APIDOC ## manette_device_get_mapping ### Description Returns the active SDL mapping string for the device (user override if one exists, otherwise the built-in database entry). Returns `NULL` if no mapping is available or the device does not support mapping. The caller owns the returned string. ### Method ```c char *manette_device_get_mapping (ManetteDevice *dev); ``` ### Parameters #### Path Parameters - **dev** (ManetteDevice *) - The Manette device to query. ### Request Example ```c ManetteDevice *dev = /* ... */; if (manette_device_supports_mapping (dev)) { g_autofree char *mapping = manette_device_get_mapping (dev); if (mapping != NULL) /* Format: ",,,…,platform:Linux" */ g_print ("Mapping: %s\n", mapping); else g_print ("No mapping found for this device\n"); } ``` ``` -------------------------------- ### Comment Style Source: https://github.com/gnome/libmanette/blob/main/CONTRIBUTING.md Use full sentences with proper capitalization and punctuation in comments. ```c /* Make sure we don't overflow. */ ``` ```c /* overflow check */ ``` -------------------------------- ### Identify Manette Device Type Source: https://context7.com/gnome/libmanette/llms.txt Use `manette_device_get_device_type()` to determine if a device is a standard gamepad or a Steam Deck. This allows for type-specific UI or behavior. ```c ManetteDevice *dev = /* ... */; ManetteDeviceType type = manette_device_get_device_type (dev); switch (type) { case MANETTE_DEVICE_GENERIC: /* Standard SDL-mapped gamepad — supports custom user mappings */ g_print ("Generic gamepad\n"); break; case MANETTE_DEVICE_STEAM_DECK: /* Steam Deck built-in controls — no SDL mapping supported */ g_print ("Steam Deck\n"); break; default: g_assert_not_reached (); } ``` -------------------------------- ### Callback Naming Convention Source: https://github.com/gnome/libmanette/blob/main/CONTRIBUTING.md Callback functions should be suffixed with `_cb` and not have prefixes like `on_`. ```c g_signal_connect (self, "clicked", G_CALLBACK (button_clicked_cb), NULL); ``` ```c g_signal_connect (self, "clicked", G_CALLBACK (on_button_clicked), NULL); ``` ```c g_signal_connect (self, "clicked", G_CALLBACK (on_button_clicked_cb), NULL); ``` ```c g_signal_connect (self, "clicked", G_CALLBACK (handle_button_clicked), NULL); ``` -------------------------------- ### manette_device_has_input Source: https://context7.com/gnome/libmanette/llms.txt Performs a low-level check for the presence of a raw hardware input, identified by Linux EV_* type and input code, irrespective of any mapping. ```APIDOC ## manette_device_has_input ### Description Low-level query that checks whether a raw hardware input of a given Linux `EV_*` type and input code is present, regardless of whether a mapping exists. Useful when implementing a custom mapping configuration tool. ### Method ```c bool manette_device_has_input (ManetteDevice *dev, int type, int code); ``` ### Parameters #### Path Parameters - **dev** (ManetteDevice *) - The Manette device to query. - **type** (int) - The Linux input event type (e.g., `EV_KEY`, `EV_ABS`). - **code** (int) - The Linux input event code (e.g., `BTN_SOUTH`, `ABS_X`). ### Request Example ```c #include /* EV_KEY, EV_ABS, BTN_SOUTH, ABS_X, … */ ManetteDevice *dev = /* ... */; /* Check for the "South" face button at the raw evdev level */ if (manette_device_has_input (dev, EV_KEY, BTN_SOUTH)) g_print ("Raw BTN_SOUTH present\n"); /* Check for absolute X axis */ if (manette_device_has_input (dev, EV_ABS, ABS_X)) g_print ("Raw ABS_X present\n"); ``` ``` -------------------------------- ### Header Inclusion Guard Source: https://github.com/gnome/libmanette/blob/main/CONTRIBUTING.md Use `#pragma once` for header inclusion guards. Internal headers should include a preprocessor directive to prevent direct inclusion. ```c #if !defined(_FOO_INSIDE) && !defined(FOO_COMPILATION) #error "Only can be included directly." #endif ``` -------------------------------- ### Switch Statement Brace Style Source: https://github.com/gnome/libmanette/blob/main/CONTRIBUTING.md The opening curly brace for switch statements must be on the same line as the 'switch' keyword, separated by a space. Case statements should align with the 'switch' keyword, with their blocks indented. ```c switch (...) { ... } ``` ```c switch (...) { case ...: ... } ``` ```c switch (...) { case ...: ... } ``` -------------------------------- ### Commit Message Format Source: https://github.com/gnome/libmanette/blob/main/CONTRIBUTING.md Commit messages should include a tag, a short explanation, a longer explanation, and an issue reference. This structure helps in understanding and tracking changes. ```text tag: Short explanation of the commit Longer explanation explaining exactly what's changed and why, whether any external or private interfaces changed, what bugs were fixed (with bug tracker reference if applicable) and so forth. Be concise but not too brief. Fixes https://gitlab.gnome.org/GNOME/libmanette/-/issues/1 ``` -------------------------------- ### ManetteButton Enum Values Source: https://context7.com/gnome/libmanette/llms.txt Illustrates the assignment of various ManetteButton enum values, corresponding to standard gamepad buttons like D-pad, face buttons, shoulders, and paddles. ```c /* All available ManetteButton values */ ManetteButton btn; btn = MANETTE_BUTTON_DPAD_UP; /* D-pad up */ btn = MANETTE_BUTTON_DPAD_DOWN; /* D-pad down */ btn = MANETTE_BUTTON_DPAD_LEFT; /* D-pad left */ btn = MANETTE_BUTTON_DPAD_RIGHT; /* D-pad right */ btn = MANETTE_BUTTON_NORTH; /* △ / Y */ btn = MANETTE_BUTTON_SOUTH; /* ✕ / A */ btn = MANETTE_BUTTON_WEST; /* □ / X */ btn = MANETTE_BUTTON_EAST; /* ○ / B */ btn = MANETTE_BUTTON_SELECT; /* Select/Back */ btn = MANETTE_BUTTON_START; /* Start */ btn = MANETTE_BUTTON_MODE; /* Guide/Home */ btn = MANETTE_BUTTON_LEFT_SHOULDER; /* L1 */ btn = MANETTE_BUTTON_RIGHT_SHOULDER;/* R1 */ btn = MANETTE_BUTTON_LEFT_STICK; /* L3 */ btn = MANETTE_BUTTON_RIGHT_STICK; /* R3 */ btn = MANETTE_BUTTON_LEFT_PADDLE1; /* Back paddle */ btn = MANETTE_BUTTON_LEFT_PADDLE2; btn = MANETTE_BUTTON_RIGHT_PADDLE1; btn = MANETTE_BUTTON_RIGHT_PADDLE2; btn = MANETTE_BUTTON_MISC1; /* Misc buttons 1–6 */ btn = MANETTE_BUTTON_TOUCHPAD; /* Touchpad click (DualSense etc.) */ ``` -------------------------------- ### ManetteDevice Signals Source: https://context7.com/gnome/libmanette/llms.txt ManetteDevice emits signals to report input events. Mapped signals provide named enum values, while unmapped variants give raw hardware indices. ```APIDOC ## ManetteDevice Signals `ManetteDevice` emits eight GObject signals to report input events. The mapped signals (`button-pressed`, `button-released`, `absolute-axis-changed`) carry named `ManetteButton` / `ManetteAxis` enum values and are the recommended way to handle input. The unmapped variants give raw hardware indices and are useful for custom mapping UIs. | Signal | |---|---| | `disconnected` | Device unplugged | | `button-pressed` | `ManetteButton button` | Mapped button pressed | | `button-released` | `ManetteButton button` | Mapped button released | | `absolute-axis-changed` | `ManetteAxis axis, gdouble value` | Mapped axis moved (−1.0 … +1.0; triggers 0.0 … +1.0) | | `unmapped-button-pressed` | `guint index` | Raw button pressed | | `unmapped-button-released` | `guint index` | Raw button released | | `unmapped-absolute-axis-changed` | `guint index, gdouble value` | Raw absolute axis moved | | `unmapped-hat-axis-changed` | `guint index, gint8 value` | Raw hat axis moved | ```c static void axis_changed_cb ( ManetteDevice *device, ManetteAxis axis, double value, gpointer user_data ) { switch (axis) { case MANETTE_AXIS_LEFT_X: g_print ("Left stick X: %.3f\n", value); break; case MANETTE_AXIS_LEFT_Y: g_print ("Left stick Y: %.3f\n", value); break; case MANETTE_AXIS_LEFT_TRIGGER: /* Triggers report 0.0 (released) … 1.0 (fully pressed) */ g_print ("Left trigger: %.3f\n", value); break; default: break; } } /* Wire up all the events for a device */ static void connect_device_signals (ManetteDevice *device) { g_signal_connect (device, "button-pressed", G_CALLBACK (on_button_pressed), NULL); g_signal_connect (device, "button-released", G_CALLBACK (on_button_released), NULL); g_signal_connect (device, "absolute-axis-changed", G_CALLBACK (axis_changed_cb), NULL); g_signal_connect (device, "disconnected", G_CALLBACK (on_device_disconnected), NULL); } ``` ``` -------------------------------- ### Property Enum Naming Convention Source: https://github.com/gnome/libmanette/blob/main/CONTRIBUTING.md Prefix property enum names with `PROP_*`. The properties count must be named `N_PROPS`. The last element should end with a comma. ```c enum { PROP_0 = 0, PROP_NUMBER, PROP_SHOW_ACTION_BUTTONS, PROP_COLUMN_SPACING, PROP_ROW_SPACING, PROP_RELIEF, N_PROPS, }; ``` -------------------------------- ### Bad Issue Reference Formats Source: https://github.com/gnome/libmanette/blob/main/CONTRIBUTING.md Do not use issue numbers directly or incorrect phrasing for issue references. ```text Fixes #1 Fix https://gitlab.gnome.org/GNOME/libmanette/-/issues/1 Fixes https://gitlab.gnome.org/GNOME/libmanette/-/issues/1. ``` -------------------------------- ### ManetteAxis Enum Source: https://context7.com/gnome/libmanette/llms.txt Enumeration of axes available on a gamepad, matching the W3C Gamepad specification. ```APIDOC ## ManetteAxis Enum Six axes are defined, matching the W3C Gamepad specification. Stick axes range from −1.0 to +1.0; trigger axes range from 0.0 (released) to +1.0 (fully pressed). ```c /* All available ManetteAxis values */ ManetteAxis axis; axis = MANETTE_AXIS_LEFT_X; /* Left stick horizontal (−1=left, +1=right) */ axis = MANETTE_AXIS_LEFT_Y; /* Left stick vertical (−1=up, +1=down) */ axis = MANETTE_AXIS_RIGHT_X; /* Right stick horizontal */ axis = MANETTE_AXIS_RIGHT_Y; /* Right stick vertical */ axis = MANETTE_AXIS_LEFT_TRIGGER; /* L2 / LT (0.0 … 1.0) */ axis = MANETTE_AXIS_RIGHT_TRIGGER; /* R2 / RT (0.0 … 1.0) */ ``` ``` -------------------------------- ### ManetteButton Enum Source: https://context7.com/gnome/libmanette/llms.txt Enumeration of buttons available on a gamepad, following the W3C Gamepad specification layout. ```APIDOC ## ManetteButton Enum Buttons follow the W3C Gamepad specification layout, using position-based names (not label-based) so they are consistent across manufacturers. ```c /* All available ManetteButton values */ ManetteButton btn; btn = MANETTE_BUTTON_DPAD_UP; /* D-pad up */ btn = MANETTE_BUTTON_DPAD_DOWN; /* D-pad down */ btn = MANETTE_BUTTON_DPAD_LEFT; /* D-pad left */ btn = MANETTE_BUTTON_DPAD_RIGHT; /* D-pad right */ btn = MANETTE_BUTTON_NORTH; /* △ / Y */ btn = MANETTE_BUTTON_SOUTH; /* ✕ / A */ btn = MANETTE_BUTTON_WEST; /* □ / X */ btn = MANETTE_BUTTON_EAST; /* ○ / B */ btn = MANETTE_BUTTON_SELECT; /* Select/Back */ btn = MANETTE_BUTTON_START; /* Start */ btn = MANETTE_BUTTON_MODE; /* Guide/Home */ btn = MANETTE_BUTTON_LEFT_SHOULDER; /* L1 */ btn = MANETTE_BUTTON_RIGHT_SHOULDER;/* R1 */ btn = MANETTE_BUTTON_LEFT_STICK; /* L3 */ btn = MANETTE_BUTTON_RIGHT_STICK; /* R3 */ btn = MANETTE_BUTTON_LEFT_PADDLE1; /* Back paddle */ btn = MANETTE_BUTTON_LEFT_PADDLE2; btn = MANETTE_BUTTON_RIGHT_PADDLE1; btn = MANETTE_BUTTON_RIGHT_PADDLE2; btn = MANETTE_BUTTON_MISC1; /* Misc buttons 1–6 */ btn = MANETTE_BUTTON_TOUCHPAD; /* Touchpad click (DualSense etc.) */ ``` ``` -------------------------------- ### Self Argument Naming Source: https://github.com/gnome/libmanette/blob/main/CONTRIBUTING.md The object a method is called on must be named `self`, including in callbacks. It should be the first argument when possible. For methods affecting multiple objects equally, `self` and `other`, or `a` and `b` are acceptable. ```c static gboolean something_happened_cb (FooBar *self) { g_return_val_if_fail (FOO_IS_BAR (self), FALSE); … return FALSE; } ``` ```c FooState * foo_bar_get_state (FooBar *self) { FooBarPrivate *priv; g_return_val_if_fail (FOO_IS_BAR (self), NULL); priv = foo_bar_get_instance_private (self); return priv->state; } ``` -------------------------------- ### Event Time Query Source: https://context7.com/gnome/libmanette/llms.txt Retrieves the kernel timestamp of the event currently being processed within a signal handler. This is useful for accurate timing-sensitive logic. ```APIDOC ## manette_device_get_current_event_time Returns the kernel timestamp (microseconds since boot) of the event currently being processed inside a signal handler. Use this instead of `g_get_monotonic_time()` to avoid skew from synchronous I/O or other blocking operations inside the handler. ```c static void button_pressed_cb (ManetteDevice *device, ManetteButton button, gpointer user_data) { guint64 event_us = manette_device_get_current_event_time (device); /* Use event_us for timing-sensitive logic, not wall-clock time */ g_print ("Button %d at %" G_GUINT64_FORMAT " µs\n", button, event_us); } ``` ```