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

Reference Monitor IDs by Hyprland ID, not GDK ID #363

Open
cpinflux opened this issue Mar 21, 2024 · 5 comments · May be fixed by #400
Open

Reference Monitor IDs by Hyprland ID, not GDK ID #363

cpinflux opened this issue Mar 21, 2024 · 5 comments · May be fixed by #400

Comments

@cpinflux
Copy link

cpinflux commented Mar 21, 2024

The AGS Window widget should accept a Hyprland Monitor ID instead of a GDK monitor number.

I noticed that the gdkmonitor parameter as added, and especially given this, I think the "monitor" value of the window should be updated to actually relate the the Hyprland monitor ID.

There doesn't appear to be an ideally simple way to translate, however it's possible to get a correct translation by going via get_monitor_at_point().

I have got this working through a simple enough update to a copy of your dotfiles:

utils.js:

export function GdkMonitorFromHyprID(id) {
    const monitors = JSON.parse(Utils.exec('hyprctl -j monitors'));
    const monitor = Gdk.Display.get_default()?.get_monitor_at_point(monitors[id].x, monitors[id].y) || 1;
    return monitor;
}

TopBar.js:

export default monitor => Widget.Window({
    name: `bar${monitor}`,
    class_name: 'transparent',
    exclusivity: 'exclusive',
    gdkmonitor: GdkMonitorFromHyprID(monitor),
    [...]
    }),
});

But it shouldn't be necessary to reference GDK in AGS config. Instead, I presume something like this should work:

    get monitor(): number { return this._get('monitor'); }
    set monitor(monitor: number) {
        if (monitor < 0)
            return;

        const monitors = JSON.parse(Utils.exec('hyprctl -j monitors'));
        const m = Gdk.Display.get_default()?.get_monitor_at_point(monitors[monitor].x, monitors[monitor].y);
        if (m) {
            this.gdkmonitor = m;
            this._set('monitor', monitor);
            return;
        }

        console.error(`Could not find monitor with id: ${monitor}`);
    }

Notes:

  1. A this point in loading, Hyprland.monitors is still undefined, ideally this could be resolved as an issue in it's own write, but as a known workaround, we have the hyprctl call itself. Not great.

  2. An alternative approach could be to implement an equivalent "monitor_at_point" parameter and pass the x,y found by the user but I fail to see any reason this half way solution need be the stopping point.

  3. By default GDK monitor numbers do match the Hyprland ones, so no disruption is likely. The issues arise for me when my laptop is undocked and reconnected, or I disable the built in monitor in Hyprland. These cahnges cause the ID's to become unaligned.

@kotontrion
Copy link
Contributor

kotontrion commented Mar 21, 2024

The windows monitor property should stay as gdk monitor id so this is compositor independent. Otherwise you would get problems with the upcoming sway service. There could however be methods to map hyprland (or sway) monitor ids to gdk ids in utils or their respective services.
Maybe even add the gdk monitor id as an additional property to the monitor object?

@cpinflux
Copy link
Author

Oh, I was unaware of any work for Sway, interesting. I suppose that could be a motivation for a "monitor_at_point" parameter in point 2? That would technically count as a solution in my book if a more complete integration is not feasible. :)

There could be a reserve solution I guess, add something to the Hyprland service to deduce the GDK ID - get the correct monitor and then iterate through all GDK monitors to find the match then return the array index. But as elsewhere, the GDK display number is a pretty meaningless thing, it's just the position in an array, not a formally classified value, so is pretty... wishy washy, and still something that AGS users shouldn't ideally have to be exposed directly to.

@Aylur
Copy link
Owner

Aylur commented Mar 21, 2024

We are not tying AGS to Hyprland, its supposed to be compositor independent.
I agree that it would be better to not expose the user to gdk and the cleanest solution here is to add a getGdkMonitor(id: number): Gdk.Monitor to the Hyprland and Sway service

@Kondor777200
Copy link

Why not use a port name or monitor description for more consistency?

@shezdy shezdy linked a pull request Apr 29, 2024 that will close this issue
@wagyourtail
Copy link

wagyourtail commented May 3, 2024

Why not use a port name or monitor description for more consistency?

something like

export function monitorIdFromName(name) {
  const monitors = JSON.parse(Utils.exec('wlr-randr --json'));
  const m = monitors.find(m => m.name === name);
  if (!m) return 0;
  const mode = m.modes.find(m => m.current);
  const position = m.position;
  const gmonitors = range(Gdk.Display.get_default()?.get_n_monitors() ?? 0, 0).map(i => Gdk.Display.get_default()?.get_monitor(i));
  return gmonitors.findIndex(gmonitor => gmonitor?.geometry.x === position.x && gmonitor?.geometry.y === position.y && gmonitor?.geometry.width === mode.width && gmonitor?.geometry.height === mode.height);
}

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 a pull request may close this issue.

5 participants