Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix matching of scaled monitors #713

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

Sawy7
Copy link

@Sawy7 Sawy7 commented Jan 11, 2025

Hi, I made an attempt at fixing broken monitor ID matching when using scaling. This works well on my Nix workstation with one 4k and one FHD monitor.

I'll happily make changes in the implementation if it is needed. Please let me know!

Closes #636

@Charging1948
Copy link

Tested it. Works perfectly for my setup.

simonkampe added a commit to simonkampe/HyprPanel that referenced this pull request Jan 14, 2025
@simonkampe
Copy link

Sorry, did not meant to reference your PR in my own fork, I tested yours and it works on my machine. I just wanted to run my own fix until this is merged :)

@Diaoul
Copy link
Contributor

Diaoul commented Jan 18, 2025

@Jas-SinghFSU do you think we can get this merged? Assuming it works as well for single monitors setup we should be good 👍

@Sawy7 Sawy7 force-pushed the monitor-id-workaround branch from 8267ec2 to 03047e2 Compare January 18, 2025 14:36
@simonkampe
Copy link

I tried it both single and multi monitor, seems to work fine.

@Jas-SinghFSU
Copy link
Owner

@Sawy7 Could you please fix the linter issues when you get a chance :)

npm run lint:fix

@uwidev
Copy link

uwidev commented Jan 31, 2025

It seems to not resolve this issue on my end when building from this pull request.
image

I have different sized monitors, but I changed their scaling such that after scaling, they are at the same resolution. One scales up while the other scales down to try to meet in the middle.

monitor=DP-3,2560x1440@144,0x0,1.25,bitdepth,10
monitor=HDMI-A-1,1920x1080,-1152x-896,0.9375,transform,1,bitdepth,10

How it's supposed to look like, is that I have odd numbred workspaces on the left monitor and even numbered workspaces on the right (center) monitor. In other words, Bar0 is right, Bar1 is left (i.e. not working, should be flipped).

@Sawy7 Sawy7 force-pushed the monitor-id-workaround branch from bb8f4fc to ff0cb1c Compare January 31, 2025 20:42
@Sawy7
Copy link
Author

Sawy7 commented Jan 31, 2025

@Sawy7 Could you please fix the linter issues when you get a chance :)

npm run lint:fix

@Jas-SinghFSU Ran the lint command and rebased. Would love to look at @uwidev's issue, but don't have the time right now. If you'd like to postpone this patch, I'd understand.

@wistfulbrick
Copy link

@uwidev I've been looking into this issue and specifically your particular problem with this PR for the last few days. Could you share what version of GDK is running in hyprpanel --inspector? It's the one thing that isn't shown in your screenshot.

I suspect that somehow your hyprpanel is running with GDK4 because for GDK geometry values are fractionally scaled. E.g. for your Ankor monitor, the GDK geometry width is 2048 = 1920/0.9375 (your monitor height, as you're rotating it, and your hyprland scale for that monitor).

Hyprpanel uses GDK3, which doesn't support fractional scaling. For myself and everyone else in 636 the GDK geometry is scaled by the GDK scaleFactor, which is the wayland fractional scaling rounded up to the nearest integer (e.g. 0.9735 -> 1, 1.25 -> 2). The scale factor still exists in GDK4 and in inspector is indicated by the little "@ 2" on the Geometry section for your Dell monitor. However your geometry values are the true fractional scaled height/widths, which indicates GDK4.

I have no idea how this could happen. Do you use other/your own AGS components that perhaps use a more recent version of AGS (no idea if later AGS versions upgraded to GDK4 or not). Perhaps if you have Nix you've set HyprPanel to follow an AGS flake that pulls a GDK4 version?

@wistfulbrick
Copy link

@Sawy7 First of all thank you for your PR, it helped me get up to speed on this issue much more quickly. I think instead of omitting the scale entirely from the key, we can use the gdk scaleFactor instead of the fractional hyprland scale. That way if there are two monitors of the same brand with the same resolutions, Hyprpanel could tell the difference between monitors with different scaleFactors but not their fractional scale.

E.g. on the GDK key creation side:

...
        const model = curMonitor.get_model() || '';
        const geometry = curMonitor.get_geometry();
        const scaleFactor = curMonitor.get_scale_factor();

        /**
         * The gdk geometry dimensions have already been scaled by the gdk scaleFactor.
         * The gdk scaleFactor is the hyprland scale rounded up to an integer.
         * E.g. geometry.width = hyprmon.width / ceil(hypr_scale)
         * We convert it back to the original values to match with Hyprlands values.
         * Converting on gdk side instead means we use multiplication instead of a division
         * on the hyprland side.
         **/
        const unscaled_width = geometry.width * scaleFactor;
        const unscaled_height = geometry.height * scaleFactor;

        /**
         * We use the gdk scaleFactor in the key, which is the hyprland scale rounded up to
         * an integer (e.g. 1, 2, etc).
         * It is not possible to obtain the original floating "scale" value in GDK3, though it
         * does seem to be possible in GDK4.
         * This does mean there's more likely to be monitor conflicts (see below) but is still
         * better than omitting scale from the key completely.
         **/
        const key = `${model}_${unscaled_width}x${unscaled_height}_${scaleFactor}`;
        gdkMonitors[i] = { key, model, used: false };
...

And on the hyprland key matching side:

...
    // First pass: Strict matching including the monitor index (i.e., hypMon.id === monitor + resolution+scale criteria)
    const directMatch = hyprlandService.get_monitors().find((hypMon) => {
        const isVertical = hypMon?.transform !== undefined ? hypMon.transform % 2 !== 0 : false;

        const width = isVertical ? hypMon.height : hypMon.width;
        const height = isVertical ? hypMon.width : hypMon.height;

        const gdkScaleFactor = Math.ceil(hypMon.scale);

        const hyprlandKey = `${hypMon.model}_${width}x${height}_${gdkScaleFactor}`;
        return gdkMonitor.key === hyprlandKey && !usedHyprlandMonitors.has(hypMon.id) && hypMon.id === monitor;
    });
...

And of course the same for the second pass.

I've tested the above changes in my own local flake of HyprPanel and seems to work well, I just have no idea what eslint version you folks are using because I'm in NixOS land and can't dnf install it.

@wistfulbrick
Copy link

I may well be wrong in some of my above statements, I've only been looking through this project and GDK for the last few days. If I am wrong please feel free to correct me, the clarifications would benefit us all :)

@uwidev
Copy link

uwidev commented Feb 7, 2025

As per request from @wistfulbrick

Could you share what version of GDK is running in hyprpanel --inspector?

*Image removed because it was not correct.

Do you use other/your own AGS components that perhaps use a more recent version of AGS (no idea if later AGS versions upgraded to GDK4 or not).

This is the out-of-box experience with no modifications.

Also... did something get pushed that fixes which bar goes to which monitor? They're appearing on the correct monitor now for me. I DID perform a system since the my last post...

@wistfulbrick
Copy link

wistfulbrick commented Feb 7, 2025

This is the out-of-box experience with no modifications.

Also... did something get pushed that fixes which bar goes to which monitor? They're appearing on the correct monitor now for me. I DID perform a system since the my last post...

Bizarre, perhaps someone more knowledgeable with GDK might be able to figure it out. The GDK geometry on your Dell monitor makes even less sense now, unless the monitor resolution/scale in hyprland has also changed since.

@uwidev
Copy link

uwidev commented Feb 7, 2025

This is the out-of-box experience with no modifications.
Also... did something get pushed that fixes which bar goes to which monitor? They're appearing on the correct monitor now for me. I DID perform a system since the my last post...

Bizarre, perhaps someone more knowledgeable with GDK might be able to figure it out. The GDK geometry on your Dell monitor makes even less sense now, unless the monitor resolution/scale in hyprland has also changed since.

You reminded me, I forgot about it, but since my very first post, I have also changed the scaling of my monitors, so that screenshot is actually inaccurate. My apologies. Here are the actual settings when changing back to the resolution where the issue occurred.

image

@wistfulbrick
Copy link

@Sawy7 I've tried to reproduce @uwidev 's issue in every way I could with my hardware but can't get my machine to replicate that fractional GDK geometry they were getting.

That's definitely their issue though, their GDK geometry height/width GDK was fractionally scaled but your code (and mine) assumes that it will be scaled with the non-fractional scaleFactor. Your code applies the scaleFactor to the hyprland monitor height/width to match it in the key (and mine unscales the gdk geometry with it). Either way, the two keys won't match.

I think @uwidev 's issue is some other bug basically, unless someone else can reproduce it. I don't think it should prevent you or @Jas-SinghFSU from considering merging this.

@tixwho
Copy link

tixwho commented Feb 8, 2025

Hello there, luckily enough I also have a Dell monitor involved in my dual-monitor setup, and the build has not fixed the issue (workspace bar still on the wrong monitor). The two monitors are on the same scaling and of the same size, scaling set to 1.5.

Here are the logs:

monitor setup in hyprland.conf:

$MONITOR_L = desc:LG Electronics LG ULTRAGEAR+ 310NTXRBV490 #landscape
$MONITOR_R = desc:Dell Inc. DELL U2723QE 6K155P3 #portrait

monitor = $MONITOR_L, 3840x2160@144, 0x0, 1.5
# position use scaled one, so 3840/1.5=2560
monitor = $MONITOR_R, preferred, 2560x-406, 1.5, transform, 3 
monitor = , preferred, auto, 1

xrandr --listmonitors

0: +DP-2 2160/600x3840/340+0+0  DP-2
1: +DP-3 3840/600x2160/340+2160+0  DP-3

hyprctl monitors

Monitor DP-2 (ID 0):
	[email protected] at 2560x-406
	description: Dell Inc. DELL U2723QE 6K155P3
	make: Dell Inc.
	model: DELL U2723QE
	serial: 6K155P3
	active workspace: 9 (9)
	special workspace: 0 ()
	reserved: 0 51 0 0
	scale: 1.50
	transform: 3
	focused: no
	dpmsStatus: 1
	vrr: false
	solitary: 0
	activelyTearing: false
	directScanoutTo: 0
	disabled: false
	currentFormat: XRGB8888
	mirrorOf: none
	availableModes: [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] 

Monitor DP-3 (ID 1):
	[email protected] at 0x0
	description: LG Electronics LG ULTRAGEAR+ 310NTXRBV490
	make: LG Electronics
	model: LG ULTRAGEAR+
	serial: 310NTXRBV490
	active workspace: 1 (1)
	special workspace: 0 ()
	reserved: 0 51 0 0
	scale: 1.50
	transform: 0
	focused: yes
	dpmsStatus: 1
	vrr: true
	solitary: 0
	activelyTearing: false
	directScanoutTo: 0
	disabled: false
	currentFormat: XRGB8888
	mirrorOf: none
	availableModes: [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected]

GTK debug:
1ed83796dc224fa45a6f7fef986345a3

@wistfulbrick
Copy link

@tixwho Interesting, thank you for replicating it! Again the Geometry height width has also been fractionally scaled, which is what is causing the keys to not match. Your output is actually super useful for narrowing down possible culprits.

So considering that both monitors in your GDK output are fractionally scaled, and whilst you have a similar dell monitor, uwidev's second monitor was an Ankor and your second monitor is an LG. I think we can rule out anything specific to monitor brands. Additionally, uwidev's issue had both hdmi and DP outputs and you're replicating the issue with two DP monitors, so we can probably rule out handling of different display connector types.

I think I know what the issue is here, I'm just collecting my evidence to present my theory. Are you and @uwidev running any gtk4 applications? If you're on Arch I'm pretty sure that both astal3 and astal4 and related gdk3/4 libraries get installed with the ags-hyprpanel-git. Can you let me know if you have both gtk-launch and gtk4-launch in your PATH and what versions?

@wistfulbrick
Copy link

wistfulbrick commented Feb 9, 2025

So I'm absolutely not a GTK/GDK expert, I've just been reviewing the source code for GDK3 and GDK4 and how they handle scaling and setting geometry. Please take what I'm about to say with a grain of salt.

In both versions the monitor scaling and geometry is handled by the apply_monitor_change function:

- In GDK4 this is in [gdkdisplay-wayland.c](https://gitlab.gnome.org/GNOME/gtk/-/blob/gtk-4-6/gdk/wayland/gdkdisplay-wayland.c#L2314) Edit: Incorrect GDK4 version, will update again.

How the two versions handle scaling is quite different.

In GDK3 it scales the gdkmonitor geometry (its position and size) by the scale factor (the wayland fractional scale rounded up to nearest integer). Then the gdkscreen and surfaces within(?) render the gui components within that pre scaled monitor geometry space.

In GDK4 the gdkmonitor geometry is not scaled at all, it is set to the original resolution height/width of the wayland display. The scaling happens in a function [update_scale](https://gitlab.gnome.org/GNOME/gtk/-/blob/gtk-4-6/gdk/wayland/gdkdisplay-wayland.c#L2248) which (I think) goes through all the surface/display components and applies the respective scale factor for the monitor that the surface outputs to. Edit: Incorrect, I was looking at an older GDK4 version. Will update again What this means is that GDK3/4 will set the monitor gdkgeometry values differently: - GDK3 geometry = wayland_resolution / scaleFactor - GDK4 geometry = wayland_resolution

I know that GDK supports having multiple GDK major versions on the same system. In my case I'm on NixOS and it looks like my setup seems tightly limited to GDK3 only, my GDK prefix in inspector is /nix/store/22krgnw10vrhdfhrfkgr1zp8kwlh1xfv-gtk+3-3.24.43. But on arch installs I believe both astal3/4 and gdk3/4 are installed (in your case to /opt).

I think what's happening is that somehow when there are both GDK3 and GDK4 applications running, their GDKMonitor geometry will be in conflict with each other? Or one wins out over the other somehow? So we can run a HyprPanel, a GDK3 application but the gdkmonitor geometry may well be set by a GDK4 application elsewhere on the system.

@uwidev
Copy link

uwidev commented Feb 9, 2025

@wistfulbrick correct, I am on Arch. I don't recall specifically installing any gtk4. Regardless, here's what I tried to gather (wasn't too sure, had to ask LLMs for help).

> which gtk-launch; gtk-launch --version
/usr/bin/gtk-launch
3.24.48
> which gtk4-launch; gtk4-launch --version
/usr/bin/gtk4-launch
4.16.12

Installed packages related to gtk4.

> pacman -Qs gtk4
local/appmenu-glib-translator-git 24.05.r6.g218bb4a-1
    GLib-based library for translating DBusMenu-exported menus into GMenuModels. Used
    for vala-panel's system tray and all variants of vala-panel-appmenu. Can be used
    with GTK3 or GTK4.
local/gtk4 1:4.16.12-1
    GObject-based multi-platform GUI toolkit
local/gtk4-layer-shell 1.0.4-1
    Library to create panels and other desktop components for Wayland
local/libastal-4-git r736.32348e7-1 (libastal)
    Building blocks for building desktop shells using gtk4.
local/libportal-gtk4 0.9.0-1
    GIO-style async APIs for most Flatpak portals - GTK 4 backend

Any processes potentially utilizing gtk4

> grep -Rl 'libgtk-4' /proc/*/maps 2>/dev/null
/proc/290752/maps

Which corresponds to easyeffects.

An ldd for executable linked to libgtk-4.

> ldd /usr/bin/* 2>/dev/null | grep libgtk-4
	libgtk-4.so.1 => /usr/lib/libgtk-4.so.1 (0x00007a00e9800000)
	libgtk-4.so.1 => /usr/lib/libgtk-4.so.1 (0x0000767315800000)
	libgtk-4.so.1 => /usr/lib/libgtk-4.so.1 (0x0000790e05c00000)
	libgtk-4.so.1 => /usr/lib/libgtk-4.so.1 (0x0000711482c00000)
	libgtk-4.so.1 => /usr/lib/libgtk-4.so.1 (0x00007413ba600000)
	libgtk-4.so.1 => /usr/lib/libgtk-4.so.1 (0x00007fb397600000)
	libgtk-4.so.1 => /usr/lib/libgtk-4.so.1 (0x0000784864200000)
	libgtk-4.so.1 => /usr/lib/libgtk-4.so.1 (0x000075dbc2600000)
	libgtk-4.so.1 => /usr/lib/libgtk-4.so.1 (0x000078349ba00000)
	libgtk-4.so.1 => /usr/lib/libgtk-4.so.1 (0x00007d37f5c00000)
	libgtk-4.so.1 => /usr/lib/libgtk-4.so.1 (0x00007e1717000000)
	libgtk-4.so.1 => /usr/lib/libgtk-4.so.1 (0x00007852d5a00000)
	libgtk-4.so.1 => /usr/lib/libgtk-4.so.1 (0x0000701f9b600000)

I tested without easyeffects runing, no changes.

Not too sure if this is relevant or helpful, but with hyprpanel open, changing the resolution configs does not result in any changes to where the bars are placed.

Here are is my working resolution configs

# Scale down 1440p to 1080p, resulting in lower DPI
monitor=DP-3,2560x1440@144,0x0,1.3333,bitdepth,10
monitor=HDMI-A-1,1920x1080,-1080x-840,1,transform,1,bitdepth,10

And not working resolution configs

# Scale up and down to meet in the middle, moderate DPI
monitor=DP-3,2560x1440@144,0x0,1.25,bitdepth,10
monitor=HDMI-A-1,1920x1080,-1152x-896,0.9375,transform,1,bitdepth,10

@wistfulbrick
Copy link

wistfulbrick commented Feb 9, 2025

@uwidev nice digging! Though I'm not 100% sure whether uninstalling all GTK4 apps would prevent the behavior if you still have the libraries (I still don't understand why this behavior is happening).

Not too sure if this is relevant or helpful, but with hyprpanel open, changing the resolution configs does not result in any changes to where the bars are placed.

Yeah I found this as well with my testing, you have to restart the hyprland session for it to take effect (in my case I just did a full reboot after changing hyprland resolution). Could you set your non-working resolution configs and restart hyprland or reboot and test it again with easyeffects removed? It would be good to eliminate it as a possibility.

Edit:
When you do this, whether hyprpanel works or not when you do this doesn't matter so much. What I'm interested in is your GDK geometry values in hyprpanel --inspector.

@uwidev
Copy link

uwidev commented Feb 9, 2025

@wistfulbrick
image

Easyeffects uninstalled pacman -Rns easyeffects.

@wistfulbrick
Copy link

@uwidev Thank you, it doesn't seem to have effected it. I'm also realizing I was looking at an older GDK4 version 😓 a lot of what I previously said on GDK4 regarding geometry doesn't apply, sorry!

I do still think this issue has something along these lines.. I'm probably way out of my depth here but I'll keep reading through the codebases and see if I can figure it out.

@ppenguin
Copy link

ppenguin commented Feb 9, 2025

For me this branch fixes the issue too (in my case two identical monitors scaled at 1.5)

@wistfulbrick
Copy link

Aha! I think this is probably the lead we're looking for on this https://gitlab.gnome.org/GNOME/gtk/-/issues/3066

The problem is that gdk_monitor_get_geometry() will return different results depending whether the Wayland compositor scales the framebuffer (e.g. for fractional scaling) or not.

gdk_monitor_get_geometry() is what returns the gdkmonitor geometry both in this code, but also the inspector windows.

As quoted from: https://gitlab.freedesktop.org/wayland/wayland-protocols/-/blob/master/unstable/xdg-output/xdg-output-unstable-v1.xml#L115

	For example, for a wl_output mode 3840×2160 and a scale factor 2:

	- A compositor not scaling the surface buffers will advertise a
	  logical size of 3840×2160,

	- A compositor automatically scaling the surface buffers will
	  advertise a logical size of 1920×1080,

	- A compositor using a fractional scale of 1.5 will advertise a
	  logical size to 2560×1620.

GDK will only scale the logical geometry size by the gdk scaleFactor if it finds the geometry for xdg_output and wl_output aren't the same gdk4-ref.

This is a far more likely explanation than my misunderstanding of GDK3/4 😁

The Arch docs have some info around this https://wiki.archlinux.org/title/HiDPI I'm curious whether you folks have this set up:

gsettings set org.gnome.mutter experimental-features "['scale-monitor-framebuffer']"

@wistfulbrick
Copy link

Another strange thing I found was that if I nix-shell -p gtk4 and then run gtk4-demo-application I can run a GTK4 inspector session by pressing CTRL+SHIFT+D.

In this GTK4 inspector window, my gdkmonitor geometries are fractionally scaled correctly (and the positions are correct too). So this might just be an issue with GDK3?

@tixwho
Copy link

tixwho commented Feb 9, 2025

@wistfulbrick Thanks for the follow up! No, I only have KDE and hyprland installed so I never checked the gnome section.

Running the gsettings set org.gnome.mutter experimental-features "['scale-monitor-framebuffer']" returned No such schema “org.gnome.mutter”. Rightfully so , because mutter wasn't installed at all!
So I attempted to use the permanent dconf configuration method described in Archwiki HiDPI 2.1.1.1, that didn't work. A mutter installation after reboot wasn't helpful as well.

A follow up here, here is a side-by-side inspector comparison between a GTK-4 application of mine (trayscale) and GTK-3 based hyprpanel. The GTK4 application is on the left side.

2025-02-09-154901_hyprshot

@ppenguin
Copy link

ppenguin commented Feb 9, 2025

I fail to understand why scaling should be relevant to the monitor selection algorithm anyway as seems to be the case, but I admit I haven't looked into any details at all...

I haven't done any additional gsettings stuff, just some theming with home-manager and stylix.

As an additional data point: GTK inspector on the demo app seems to identify the same as hyprctl, so I don't understand why in such case the unpatched hyprpanel swapped the workspaces in the first place?

image

image

@wistfulbrick
Copy link

I fail to understand why scaling should be relevant to the monitor selection algorithm anyway as seems to be the case, but I admit I haven't looked into any details at all...

It's not a hyprland workspace issue, it's an issue with how GDK tracks monitor ids, to know which bars (and thus which workspace numbers) to render to the correct monitor.

The context you're looking for is here.

Hyprpanel has to a decent amount of work to attempt to pair gdk monitor ids with hyprland monitor ids. It matches them by a key that's based on monitor model, height/width and scale. Unfortunately the gdk height/width is proving to be equally as slippery!

@wistfulbrick
Copy link

Thank you folks for testing out the mutter setting, I really am just throwing things out here at the moment. I think there's some setting/config option either in hyprland or gdk that's being applied (or not) that's causing the variation in behavior. As soon as you have found a setting that changes whether the GDK3 inspector geometry scales with fractional scale or scale factor, please post here.

There's two things we could possibly try code wise, we could try and anticipate and match keys against both a fractionally scaled geometry and a scale factor scaled geometry. Or we could try updating Hyprpanel to use astal4/gdk4 (which may break a few other things) as it seems GDK4 is more reliable in fetching accurate monitor information.

@ppenguin
Copy link

@wistfulbrick

The context you're looking for is here.

Thanks! I noted that in my case the monitor description field is different for two identical monitors (it appears to have (part of) a serial code?) as can be seen in the screenshots, and it is consistent between GDK and hyprland BUT this is only available in GTK4

Or we could try updating Hyprpanel to use astal4/gdk4 (which may break a few other things) as it seems GDK4 is more reliable in fetching accurate monitor information.

I came to the same conclusion, would be interesting to try and see whether it's feasible effort-wise. Maybe just start changing imports to astal/gtk4 etc., and see where the build fails? There might be some difficulty with things like systray and such that might be different?

@wistfulbrick
Copy link

Hahaha, I just spent the afternoon trying to hack HyprPanel to work with gdk4 to no success. Really should have expected tbh, it's a huge amount of work and I'm not remotely qualified to do it!

There's a ton of changes to make, some of the old GTK3 widgets HyprPanel used like Gtk.Menu have been deprecated and require work to convert to alternatives, it looks like you have to declare external GTK4 widgets in a new/different way, there's a good few gdk functions that have been deprecated needing sometimes additional logic or testing. It's not a complete rewrite but it's substantial. Probably not a fair ask on the maintainers!

@wistfulbrick
Copy link

Instead I think we can a workaround for this behavior that tries to match against both outcomes:

  • Where the GDK key height/width are scaled by the scaleFactor
  • Where the GDK key height/width are scaled by the scale (fractional)

I've tested this on my local flake of HyprPanel and it works for me, which isn't conclusive of course. Obviously the real test will be whether it works for others with fractional geometry:

gdk key setup same as master
...
// First pass: Strict matching including the monitor index (i.e., hypMon.id === monitor + resolution+scale criteria)
    const directMatch = hyprlandService.get_monitors().find((hypMon) => {
        const isVertical = hypMon?.transform !== undefined ? hypMon.transform % 2 !== 0 : false;

        const gdkScaleFactor = Math.ceil(hypMon.scale);

        const width = isVertical ? hypMon.height : hypMon.width;
        const height = isVertical ? hypMon.width : hypMon.height;

        const scaleFactorWidth = Math.trunc(width / gdkScaleFactor);
        const scaleFactorHeight = Math.trunc(height / gdkScaleFactor);
        const scaleFactorKey = `${hypMon.model}_${scaleFactorWidth}x${scaleFactorHeight}_${gdkScaleFactor}`;

        const scaleWidth = Math.trunc(width / hypMon.scale);
        const scaleHeight = Math.trunc(height / hypMon.scale);
        const scaleKey = `${hypMon.model}_${scaleWidth}x${scaleHeight}_${gdkScaleFactor}`;

        const keyMatch = (gdkMonitor.key === scaleFactorKey || gdkMonitor.key === scaleKey);

        return keyMatch && !usedHyprlandMonitors.has(hypMon.id) && hypMon.id === monitor;
    });

... and similar for the second pass

Only issue is we're now matching against two keys so there's maybe the potential for more key conflicts, currently doing the mental gymnastics to figure out in what additional circumstances this would occur.

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.

Bar is Displayed on wrong monitors (Dual Monitor)
9 participants