This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

sway: use rumble for notification if available

+139 -1
+29
tools/gpd-rumble/flake-module.nix
··· 1 + { 2 + perSystem = 3 + { pkgs, lib, ... }: 4 + { 5 + packages.gpd-rumble = pkgs.stdenv.mkDerivation { 6 + pname = "gpd-rumble"; 7 + version = "0.1.0"; 8 + 9 + src = ./.; 10 + 11 + buildInputs = [ ]; 12 + 13 + buildPhase = '' 14 + $CC -o gpd-rumble rumble.c 15 + ''; 16 + 17 + installPhase = '' 18 + mkdir -p $out/bin 19 + cp gpd-rumble $out/bin/ 20 + ''; 21 + 22 + meta = { 23 + description = "Trigger vibration motor on GPD Win Mini 2025"; 24 + platforms = lib.platforms.linux; 25 + mainProgram = "gpd-rumble"; 26 + }; 27 + }; 28 + }; 29 + }
+83
tools/gpd-rumble/rumble.c
··· 1 + #include <stdio.h> 2 + #include <stdlib.h> 3 + #include <string.h> 4 + #include <fcntl.h> 5 + #include <unistd.h> 6 + #include <linux/input.h> 7 + #include <sys/ioctl.h> 8 + 9 + int main(int argc, char *argv[]) { 10 + int fd; 11 + struct ff_effect effect; 12 + struct input_event play, stop; 13 + int duration_ms = 500; 14 + int strength = 0xFFFF; 15 + const char *device = "/dev/input/event2"; 16 + 17 + // Parse arguments 18 + if (argc > 1) { 19 + duration_ms = atoi(argv[1]); 20 + } 21 + if (argc > 2) { 22 + strength = (atoi(argv[2]) * 0xFFFF) / 100; 23 + if (strength > 0xFFFF) strength = 0xFFFF; 24 + } 25 + if (argc > 3) { 26 + device = argv[3]; 27 + } 28 + 29 + // Open device 30 + fd = open(device, O_RDWR); 31 + if (fd < 0) { 32 + perror("Failed to open device"); 33 + fprintf(stderr, "Usage: %s [duration_ms] [strength_percent] [device]\n", argv[0]); 34 + return 1; 35 + } 36 + 37 + // Setup rumble effect 38 + memset(&effect, 0, sizeof(effect)); 39 + effect.type = FF_RUMBLE; 40 + effect.id = -1; 41 + effect.u.rumble.strong_magnitude = strength; 42 + effect.u.rumble.weak_magnitude = strength / 2; 43 + effect.replay.length = duration_ms; 44 + effect.replay.delay = 0; 45 + 46 + // Upload effect 47 + if (ioctl(fd, EVIOCSFF, &effect) < 0) { 48 + perror("Failed to upload effect"); 49 + close(fd); 50 + return 1; 51 + } 52 + 53 + // Play effect 54 + memset(&play, 0, sizeof(play)); 55 + play.type = EV_FF; 56 + play.code = effect.id; 57 + play.value = 1; 58 + 59 + if (write(fd, &play, sizeof(play)) < 0) { 60 + perror("Failed to play effect"); 61 + ioctl(fd, EVIOCRMFF, effect.id); 62 + close(fd); 63 + return 1; 64 + } 65 + 66 + printf("Rumble playing for %d ms at %d%% strength\n", duration_ms, (strength * 100) / 0xFFFF); 67 + 68 + // Wait for effect to finish 69 + usleep(duration_ms * 1000); 70 + 71 + // Stop effect 72 + memset(&stop, 0, sizeof(stop)); 73 + stop.type = EV_FF; 74 + stop.code = effect.id; 75 + stop.value = 0; 76 + write(fd, &stop, sizeof(stop)); 77 + 78 + // Cleanup 79 + ioctl(fd, EVIOCRMFF, effect.id); 80 + close(fd); 81 + 82 + return 0; 83 + }
+27 -1
2configs/desktops/sway/default.nix
··· 1 - { pkgs, lib, ... }: 1 + { pkgs, lib, self, ... }: 2 2 let 3 3 4 4 term = "/run/current-system/sw/bin/alacritty"; ··· 167 167 serviceConfig = { 168 168 Type = "simple"; 169 169 ExecStart = "${pkgs.waybar}/bin/waybar -c ${waybarConfig} -s ${waybarStyle}"; 170 + Restart = "on-failure"; 171 + RestartSec = 1; 172 + }; 173 + }; 174 + 175 + systemd.user.services.sway-urgent-rumble = { 176 + description = "Trigger rumble on urgent windows"; 177 + partOf = [ "sway-session.target" ]; 178 + wantedBy = [ "sway-session.target" ]; 179 + unitConfig = { 180 + ConditionPathExists = "/dev/input/event2"; 181 + ConditionPathExists = "/sys/class/input/event2/device/capabilities/ff"; 182 + }; 183 + serviceConfig = { 184 + Type = "simple"; 185 + ExecStart = lib.getExe (pkgs.writeShellApplication { 186 + name = "sway-urgent-rumble"; 187 + runtimeInputs = [ pkgs.sway pkgs.jq self.packages.${pkgs.system}.gpd-rumble ]; 188 + text = '' 189 + swaymsg -t subscribe -m '["window"]' | \ 190 + jq --unbuffered -r 'select(.change == "urgent" and .container.urgent == true) | "urgent"' | \ 191 + while read -r _; do 192 + gpd-rumble 200 100 & 193 + done 194 + ''; 195 + }); 170 196 Restart = "on-failure"; 171 197 RestartSec = 1; 172 198 };