Tips from a Mac user on customising Hyprland for dev, gaming, MacOS keyboard & Magic Trackpad
Inspired by r/unixporn, I tried out Hyprland on Arch, and have been mainlining it for several months. I still use my Macbook with MacOS and have Mac input peripherals so I’ve aimed to keep things similar enough where it feels mostly seamless switching between the two. I installed it on an Intel Nuc 11 Enthusiast with a mobile RTX 2060.
Contents
- 1. General recommendations, so far.
- 2. Apple Keyboard and familiar MacOS Shortcuts
- 3. Apple Magic Trackpad 2
- 4. Nvidia, Intel and Hyprland
- 5. Steam, Nvidia and Gamescope
- 6. Fixing Systemd Network Stalling
- 7. Things lacking
1. General recommendations, so far
- Use the Arch installer wizard to fast-forward you into a minimum viable system.
- Make things work first, good later, rice latest. Find out potential deal-breakers early. Be wary of customisation addiction / losing sleep making one more thing work.
- When you’re trying to find out what you should do consult things in this order: Hyprland Docs -> Arch Wiki -> -> Man page -> LLM/Search engine.
- Try the default hyprland ecosystem tools first e.g. hypridle - idle state management (sleep), hyprlock - lock screen
- Don’t bother with a greeter just add
[[ $(tty) == "/dev/tty1" ]] && Hyprland
in your zshrc/bashrc to automatically start Hyprland. But maybe set up a nice welcome message. - If you get really stuck on a particular problem, you can always keep a minimal xfce4 (or whatever) on the same OS. Also, you can always bail out with ctrl+alt+f1, f2, f3 etc to switch TTYs
- Use Rofi as an app launcher (default cmd is super+r)
- Bind screen capture utils to shortcuts that make sense for you with
~/.config/hypr/hyprland.conf
2. Apple Keyboard and familiar MacOS Shortcuts
In my experience, Apple has better keyboard shortcuts. I don’t have to contort my hand as much in tab switching & native text editing, I can jump word or to line extents & there’s a left to right notion of heirarchy.
I’m using my Apple keyboard so here is what I’m aiming for:
[global]cmd+c=copycmd+v=pastecmd+left=beginning of linecmd+right=beginning of lineoption+left=previous wordoption+right=next word
[hyprland]Control=meta key
[terminal]ctrl+c=cancel
We can’t go up and down various application stacks to get macos-like text shortcuts, but I’ve found 80% is good enough. The easiest way to get there is to simply swap ctrl+meta keys and then add some custom key-binds per application. You can do this with xremap or with hyrpland.conf.
input { kb_model = apple kb_options = apple:alupckeys,ctrl:swap_lwin_lctl}
Or xremap:
curl -Lo https://github.com/xremap/xremap/releases/download/v0.10.2/xremap-linux-x86_64-hypr.zipunzip xremap-linux-x86_64-hypr.zipchmod +x xremapcp xremap /usr/bin/mkdir ~/.config/xremaptouch ~/.config/xremap/config.yml # and copy contents belowcp xremap.service /etc/systemd/system/xremap.servicesudo systemctl enable xremapsudo systemctl start xremap
Make sure this is copied for xremap to work
modmap: - name: Global remap: Super_L: Ctrl_L Ctrl_L: Super_L Super_R: Ctrl_L
For zed, I created a config that is 98% close to my day-to-day zed profile (I use vi-keys mostly but I like some standard non-modal key jumping too that’s default on MacOS). You can find it as a github gist. Copy and paste it in zed shift+cmd+p->open keymap
.
For ghostty I simply used:
keybind = cmd+c=text:\x03keybind = ctrl+c=copy_to_clipboardkeybind = ctrl+v=paste_from_clipboard
And finally, I want cmd+opt+left/right to jump back and forth between tabs respectively, so I’ve made a gist with 2 files you can copy https://gist.github.com/danielgormly/04f2c24917a2b1e21a2817202f3677e4
.
3. Apple Magic Trackpad 2
I prefer a trackpad to a mouse and three-finger drag & text selection on Mac is the best (you have to enable it in accessibility settings). The Magic Trackpad 2 is by far the best trackpad I’ve ever used. It’s pretty good on Arch but not quite MacOS level - maybe you could get 98% with some extra time spent tuning - but here’s a quick pain-free path.
# You will need paru if you don't have itsudo pacman -S --needed base-develgit clone https://aur.archlinux.org/paru.gitcd parumakepkg -si# https://aur.archlinux.org/packages/libinput-three-finger-drag# Installing AURS can feel sketchy, I recommend that you scan through the PKGBUILD# This should *just work™*sudo paru -S libinput-three-finger-dragreboot
Back in ~/.config/hypr/hyprland.conf
I added.
input { ... touchpad { natural_scroll = true scroll_factor = 0.5 # default scroll was crazy fast clickfinger_behavior = true # enables context click on two finger click (not just tap) }}
But Zed editor starts scrolling way too slow, so I had to double the scroll sensitivity here. In Zed, use cmd+p
->zed: open settings
& add "scroll_sensitivity": 2
to the top level config
Kitty scrolling is really slow too. We can fix that by adding touch_scroll_multiplier 10 >> ~/.config/kitty/kitty.conf
, however Ghostty was good out of the box.
4. Nvidia, Intel and Hyprland
Firstly, Hyprland runs well on my Nvidia RTX2060 Mobile, but there is a guide I followed. If you have an integrated GPU alongside your DGPU, as the Hyprland Multi-GPU guide says, you should definitely consider it to reduce power draw & free up gpu for gpu intensive tasks. I have an Intel NUC 11 Enthusiast with a dedicated Nvidia RTX 2060 GPU & an integrated Intel Iris Xe GPU. Hyprland chose the 2060 by default but I switched to Iris. I did have a couple of very small bugs with Hyprland on Nvidia like my Bluetooth applet not rendering in Waybar.
I am using drivers Nvidia proprietary drivers version 565.77 in this post
Setting up the hardware:
# Install Nvidia driverspacman -Sy nvidia-open nvidia-utils# Install Intel driverspacman -Sy mesa intel-media-driver vulkan-intel# For Intel (Optional): Enable GuC on Intel via kernel parameter, allows low level video decoding/encoding software to use Intel GPU (VAAPI)echo "options i915 enable_guc=2" > /etc/modprobe.d/i915# For Nvidia: Turn on Nvidia DRM, required for Hyprland w Nvidia via kernel parameter, https://en.wikipedia.org/wiki/Direct_Rendering_Manager# This allows Kernel Mode Setting (KMS); allows kernel programmes to set graphics mode (resolution, colour space etc) - Intel already allows this by defaultecho "options nvidia_drm modeset=1" > /etc/modprobe.d/nvidia# Load above kernel parameters into initramsudo mkinitcpio -P
If you want your Intel GPU to drive Hyprland, find your Intel GPU’s file descriptor:
# Find your Intel GPUlspci -nn | grep -iE 'vga|3d'> 0000:00:02.0 VGA compatible controller: Intel Corporation TigerLake-LP GT2 [Iris Xe Graphics] (rev 01)> 0000:01:00.0 VGA compatible controller: NVIDIA Corporation TU106M [GeForce RTX 2060 Mobile] (rev a1)# Now remember the associated identifier `[Domain:]Bus:Device.Function` e.g. "0000:00:02.0"# And confirm its file descriptor is availablels -lha /dev/dri/by-path/> lrwxrwxrwx 1 root root 8 Dec 13 19:59 /dev/dri/by-path/pci-0000:00:02.0-card -> ../card2# We're going to use that /dev/dri/card2 address (as the docs say, don't use the symlink - I tried it & Hyprland won't start with it)
and then to your Hyprland config add:
env = AQ_DRM_DEVICES,/dev/dri/card2
Now reboot everything & hopefully, you have Hyprland running on the Intel GPU. You can confirm this by using intel_gpu_top:
sudo pacman -Sy intel-gpu-toolsintel_gpu_top # and hopefully you can see Hyprland there# Conversely, we can check that it's NOT running on the Nvidia GPU:nvidia-smi
Scaling is a problem though. Many apps don’t have Wayland versions yet and only have Xorg versions. Xorg apps are rendered through Xwayland, and Xwayland doesn’t respect Wayland’s scaling. Xorg itself handles scaling differently. Px value is concrete but apps can consult the X Server’s DPI settings. Blah blah blah, Xwayland just uses the default scaling of 1:1px and this scale is global across all apps as there’s only 1 X Server in its current implementation. This is a problem in Hyprland because Wayland is very HiDPI aware & scale is inherent to its protocol. It is also worth noting that fractional scaling (1.25, 1.5 etc) on Xorg can be problematic in any case.
Popular examples include electron apps like Signal & Bitwarden. They’ll be blurry on your HiDPI screen. But we can fix it by first, prevent scaling. Edit your hyprland.conf
like so:
xwayland { force_zero_scaling = true}
But now all xwayland apps are small. But many apps have their own scaling methods. Most electron apps let you use ctrl +
and ctrl -
because they are web views after all! Some apps might have cli args, internal settings or you might just have to squint!
ctrl +
& ctrl -
on SignalYou can actually try to bypass the Xwayland problem altogether with electron apps specifically, by forcing them to use Wayland e.g. bitwarden-desktop features=UseOzonePlatform --ozone-platform=wayland
, however, my experience with this was very buggy. Sometimes the window would render literally 2min after I typed the command - though it did render well.
5. Steam, Nvidia and Gamescope
Steam is tricky but and ymmv depending on your card. Nvidia cards may present different problems, but the story seems to improving. This is my primary matrix of choices running Steam:
Setup | Card | Steam GPU Accel | Interface performance (subjective) | Verdict |
---|---|---|---|---|
Desktop mode | Intel iGPU | Off | Ok but low responsiveness, FPS | 😵 |
Big Picture Mode | Intel iGPU | Off | Very low FPS | 😵 |
Gamescope | Intel iGPU | Off | Very low FPS | 😵 |
Desktop mode | Intel iGPU | On | Most of the interface is black | 😵 |
Big Picture Mode | Intel iGPU | On | Sets up a pane but no interface | 😵 |
Gamescope | Intel iGPU | On | Runs well* but then some games freeze! | 😵 |
Desktop mode | RTX2060 | Off | Runs pretty well | ✅ |
Big Picture Mode | RTX2060 | Off | Very low FPS | 😵 |
Gamescope | RTX2060 | Off | Very low FPS | 😵 |
Desktop mode | RTX2060 | On | Pretty well | ✅ |
Big Picture Mode | RTX2060 | On | Pretty well | ✅ |
Gamescope | RTX2060 | On | Vulkan error - does not open | 😵 |
Gamescope in theory is amazing with Hyprland as it keeps everything contained and performs well. But you might be victim to the game freeze bug where the game loop continues but the rendering fails.
So based on the above matrix, my preference is running desktop mode on the the RTX2060 with GPU acceleration on. To turn on GPU acceleration:
Steam Settings -> Interface:
- Turn ON Enable GPU accelerated rendering in web views
- Turn ON Enable hardware video decoding, if supported
- Turn OFF Enable smooth scrolling webviews (I found this didn’t mesh well with trackpad, ymmv)
And to run Steam in desktop mode: prime-run steam
or prime-run steam -bigpicture
.
Steam desktop is built for X too, so it has the same scaling problem. So assuming we applied the force_zero_scaling = true
in the previous secion, we can solve it easily by running steam with steam -forcedesktopscaling 1.5
or whatever scale sits well with you.
steam -forcedesktopscaling 10
Lastly, when you switch windows while playing a game without gamescope compositing, consider using these rules. I found that INSIDE would quit when I left its focus without the stayfocused prop, and would not size normally without fullscreen. immediate
renders it without hyprland’s vsync in fullscreen.
windowrulev2 = immediate,class:^(steam_app).*$windowrulev2 = stayfocused,class:^(steam_app).*$windowrulev2 = fullscreen,class:^(steam_app).*$
Not recommended sidequest: Running Gamescope (Please skip)
Gamescope doesn’t play nice with Nvidia so I wouldn’t bother but I did make some attempts and thought I’d record them. By default Gamescope will run on the same device as the compositor is, so for me that’s Intel. I can also specify a device using lspci
(referenced earlier) e.g. for the Nvidia
QT_QPA_PLATFORM=wayland gamescope -W 2560 -H 1440 --force-grab-cursor --prefer-vk-device $(lspci -nn | grep -iE "vga|3d" | tr -d "][" | tr " " "\n" | grep 10de) -e -- steam -tenfoot
But that will give me a crash! See gamescope/issues/497.
I can run gamescope --prefer-vk-device $(lspci -nn | grep -iE "vga|3d" | tr -d "][" | tr " " "\n" | grep 10de) -e --backend sdl -- steam
and it boots but the FPS is not great & the colours are off:
gamescope --backend sdl
with my RTX2060 mobile. Fried colour space.prime-run gamescope -- steam
seems to be the way to go.
Now everything works great and I can open up games (rendered with the RTX2060) and they all work great but we’re on Linux on Nvidia so it’s not going to work - gamescope/issues/1592. This was a difficult issue to track down. I was only trying two games - INSIDE & Dark Souls Remastered. Both games would freeze on a frame and stop accepting input but continue playing sound. Interestingly, gamescope is unaffected & I can hit controller hotkey to open up Steam - but the game won’t die without a dirty killall -9 /usr/bin/gamescope && killall -9 /usr/bin/gamescopereaper
. Running the same setup on the iGPU directly from a TTY (no Hyprland). I tried to recompile Proton with a suggested patch related to Vulkan but no noticeable improvements.
As it seemed like a framebuffer issue which led me to try various fixes including turning off vsync in game. That actually works for Dark Souls Remastered and I got no freezes, but for INSIDE there’s no VSYNC option. I tried disabling VK_KHR_present_wait
for gamescope with env VKD3D_DISABLE_EXTENSIONS=VK_KHR_present_id,VK_KHR_present_wait
which is a Vulkan extension that helps with frame timing, pacing etc but no dice. Running gamescope through Intel but via Nvidia could put me in a weird spot.
A brief description of the command:
- -W 2560 -H 1440: 2k gaming is good enough for my RTX2060
- —force-grab-cursor: This steals the cursor away from Wayland. It’s not a perfect experience because the sensitivity is slightly off, but without it, gamescope will just close when you leave a game.
- —prefer-vk-device $(lspci -nn | grep -iE ‘vga|3d’ | tr -d ’][’ | tr ’ ’ $‘\n’ | grep 8086): This spits out the vendor id : device id (in my case 8086:9a49) of the Intel card - you might want to confirm that. I found Steam works perfectly running under the Intel GPU with mesa & like absolute shit (especially Big Picture mode) on my Nvidia card. Don’t worry, your games will still boot up on your DGPU.
- -e: This is a flag to tell gamescope you’re running steam and makes it friendly with child processes launched from it.
- -f: Optional (gamescope option); but this will let you start in fullscreen.
- -tenfoot: kicks you off into Big Picture mode - when I didn’t do this I would sometimes lose the game in gamescope.
Summing it up:
So yeah Gamescope + Nvidia = not yet, so let’s solidify our normal approach with a Desktop shortcut your app launcher (i.e. ctrl+r) will pick up.
[Desktop Entry]Name=Steam Hyprland Big PictureExec=sh -c 'prime-run steam -bigpicture'Type=ApplicationCategories=Game;Icon=steamTerminal=falseComment=Launch Steam in Big Picture Mode with Gamescope
Copy this to ~/.local/share/applications/steam-hyprland-big-picture.desktop
and it will appear in your app launchers.
6. Fixing systemd network stalling
I will note that xremap wouldn’t launch for the first 2 minutes after launching Hyprland at first because its default service file waits for multi-user.target to complete, but my ethernet port wasn’t connecting (because I don’t use it), so multi-user’s dependency systemd-networkd-wait-online
would time out first as it waits for ALL interfaces! If you come across the same headache, here’s the fix:
This will wait for --any
(including lo interface I believe) to come online - basically I am establishing my computer as a local computer rather than inherently networked. Add this override with sudo -E systemctl edit systemd-networkd-wait-online.service
. Note the -E
will export your local environment vars so will save you from dealing with nano
.
[Service]Type=oneshotExecStart=ExecStart=/usr/lib/systemd/systemd-networkd-wait-online --anyRemainAfterExit=yes
YES you need the first blank ExecStart! This clears the existing ExecStart. Actually, I suppose you could just disable the systemd-networkd-wait-online altogether.
7. Things lacking
- I can’t use Sketch, Photomator & Final Cut Pro. Mac still has a monopoly on the best creative tools. I might try PenPot. I’ve tried the photo tools in the past they’re not great.
- Airplay is proprietary, Google Cast or whatever is proprietary. No convenient solution for wireless casting from Linux.
- Magic Trackpad is the best - but Apple isn’t very friendly with the BT implementation to outside devices so I have to repair from scratch if I want to use it on my Macbook.