Aylur / ags

A customizable and extensible shell
GNU General Public License v3.0
2.02k stars 105 forks source link

hyprland.getGdkMonitor(i) returns dublicate monitor [Bug] #534

Open Not-a-true-statement opened 1 month ago

Not-a-true-statement commented 1 month ago

Seems like when getting the gtk monitor using the util function (which was merged with #400) does not retrieve the correct monitor. Currently it retrieves 2 correct monitors and 1 duplicate. I have checked the location of each monitor placement and none of them is overlapping since the code looks for XY, presumably top left.

How i am trying to use it

const hyprland = await Service.import("hyprland");
let currentBars = [];
App.config({
    style: "./src/stylesheets/stylesheet.css",

    // windows: hyprland.bind("monitors").as((v)=>{
    //         return [];
    //     }),

    windows: () => {
        let bars = [];
        let monitors = hyprland.monitors;

        for (let monitorIndex = 0; monitorIndex < monitors.length; monitorIndex++) {
            const monitor = monitors[monitorIndex];
            let { id } = monitor;
            let gdkMonitor = hyprland.getGdkMonitor(id);

            if (!gdkMonitor)
                continue;
            console.log(`GDK:${gdkMonitor} Desc: ${monitor.description}`);

            bars.push(Bar(gdkMonitor, id))
        }
        return bars;
    }
})

Checking for info

let monitors = hyprland.monitors;
for (let monitorIndex = 0; monitorIndex < monitors.length; monitorIndex++) {
    const monitor = monitors[monitorIndex];
    let { id } = monitor;
    let gdkMonitor = hyprland.getGdkMonitor(id);
    if (!gdkMonitor)
        continue;
    console.log(`GDK:${gdkMonitor} Desc: ${monitor.description}`);
}

Output:

Gjs-Console-Message: 16:46:16.866: GDK:[object instance wrapper GType:GdkWaylandMonitor jsobj@0x3c64c42996c8 native@0x186dfb0] Desc: AOC 2460G5 0x00021280
Gjs-Console-Message: 16:46:16.866: GDK:[object instance wrapper GType:GdkWaylandMonitor jsobj@0x3c64c42996c8 native@0x186dfb0] Desc: Dell Inc. DELL P2219H B6GM443
Gjs-Console-Message: 16:46:16.866: GDK:[object instance wrapper GType:GdkWaylandMonitor jsobj@0x3c64c429e4e8 native@0x1881590] Desc: Microstep MSI G273Q CA8A641600625

When i look for monitors that are detected

try {
    let gdkDefault = Gdk.Display.get_default();
    const monitorCount = gdkDefault?.get_n_monitors();
    for (let index = 0; index < (monitorCount ?? 1); index++) {
        const str = JSON.stringify(gdkDefault?.get_monitor(index), null, 4);
        console.log(str);
    }

} catch (error) {
    console.log(error);
}

Output:

Gjs-Console-Message: 17:03:23.895: {
    "display": {},
    "manufacturer": "AOC",
    "model": "2460G5",
    "scale-factor": 1,
    "geometry": {},
    "workarea": {},
    "width-mm": 530,
    "height-mm": 300,
    "refresh-rate": 74986,
    "subpixel-layout": 0
}
Gjs-Console-Message: 17:03:23.895: {
    "display": {},
    "manufacturer": "Dell Inc.",
    "model": "DELL P2219H",
    "scale-factor": 1,
    "geometry": {},
    "workarea": {},
    "width-mm": 270,
    "height-mm": 480,
    "refresh-rate": 60000,
    "subpixel-layout": 0
}
Gjs-Console-Message: 17:03:23.895: {
    "display": {},
    "manufacturer": "Microstep",
    "model": "MSI G273Q",
    "scale-factor": 1,
    "geometry": {},
    "workarea": {},
    "width-mm": 600,
    "height-mm": 340,
    "refresh-rate": 143854,
    "subpixel-layout": 0
}

Output for hyprctl monitors -j

hyprctl monitors -j
[{
    "id": 0,
    "name": "DP-1",
    "description": "AOC 2460G5 0x00021280",
    "make": "AOC",
    "model": "2460G5",
    "serial": "0x00021280",
    "width": 1920,
    "height": 1080,
    "refreshRate": 74.98600,
    "x": 1080,
    "y": 0,
    "activeWorkspace": {
        "id": 1,
        "name": "1"
    },
    "specialWorkspace": {
        "id": 0,
        "name": ""
    },
    "reserved": [0, 98, 0, 0],
    "scale": 1.00,
    "transform": 2,
    "focused": false,
    "dpmsStatus": true,
    "vrr": false,
    "activelyTearing": false,
    "disabled": false,
    "currentFormat": "XRGB8888",
    "availableModes": ["1920x1080@60.00Hz","1920x1080@74.99Hz","1920x1080@72.03Hz","1920x1080@60.02Hz","1920x1080@60.00Hz","1920x1080@59.94Hz","1920x1080@50.01Hz","1920x1080@50.00Hz","1920x1080@48.00Hz","1680x1050@59.95Hz","1280x1024@75.03Hz","1280x1024@60.02Hz","1440x900@59.89Hz","1280x960@60.00Hz","1280x800@60.00Hz","1280x720@60.00Hz","1280x720@60.00Hz","1280x720@59.94Hz","1280x720@50.00Hz","1024x768@75.03Hz","1024x768@70.07Hz","1024x768@60.00Hz","832x624@74.55Hz","800x600@75.00Hz","800x600@72.19Hz","800x600@60.32Hz","800x600@56.25Hz","720x576@50.00Hz","720x576@50.00Hz","720x576@50.00Hz","720x480@60.00Hz","720x480@60.00Hz","720x480@59.94Hz","720x480@59.94Hz","720x480@59.94Hz","640x480@75.00Hz","640x480@72.81Hz","640x480@66.67Hz","640x480@60.00Hz","640x480@59.94Hz","640x480@59.94Hz","720x400@70.08Hz"]
},{
    "id": 1,
    "name": "DP-2",
    "description": "Dell Inc. DELL P2219H B6GM443",
    "make": "Dell Inc.",
    "model": "DELL P2219H",
    "serial": "B6GM443",
    "width": 1920,
    "height": 1080,
    "refreshRate": 60.00000,
    "x": 0,
    "y": 0,
    "activeWorkspace": {
        "id": 2,
        "name": "2"
    },
    "specialWorkspace": {
        "id": 0,
        "name": ""
    },
    "reserved": [0, 0, 0, 0],
    "scale": 1.00,
    "transform": 3,
    "focused": false,
    "dpmsStatus": true,
    "vrr": false,
    "activelyTearing": false,
    "disabled": false,
    "currentFormat": "XRGB8888",
    "availableModes": ["1920x1080@60.00Hz","1680x1050@60.00Hz","1600x900@60.00Hz","1280x1024@75.03Hz","1280x1024@60.02Hz","1440x900@60.00Hz","1280x800@60.00Hz","1152x864@75.00Hz","1280x720@60.00Hz","1024x768@75.03Hz","1024x768@60.00Hz","800x600@75.00Hz","800x600@60.32Hz","640x480@75.00Hz","640x480@59.94Hz","720x400@70.08Hz"]
},{
    "id": 2,
    "name": "HDMI-A-1",
    "description": "Microstep MSI G273Q CA8A641600625",
    "make": "Microstep",
    "model": "MSI G273Q",
    "serial": "CA8A641600625",
    "width": 2560,
    "height": 1440,
    "refreshRate": 143.85500,
    "x": 1080,
    "y": 1080,
    "activeWorkspace": {
        "id": 3,
        "name": "3"
    },
    "specialWorkspace": {
        "id": 0,
        "name": ""
    },
    "reserved": [0, 49, 0, 0],
    "scale": 1.00,
    "transform": 0,
    "focused": true,
    "dpmsStatus": true,
    "vrr": false,
    "activelyTearing": false,
    "disabled": false,
    "currentFormat": "XRGB8888",
    "availableModes": ["2560x1440@59.95Hz","3840x2160@60.00Hz","3840x2160@59.94Hz","3840x2160@30.00Hz","3840x2160@29.97Hz","2560x1440@143.85Hz","2560x1440@120.00Hz","1920x1200@59.95Hz","1920x1080@164.84Hz","1920x1080@120.00Hz","1920x1080@119.88Hz","1920x1080@100.00Hz","1920x1080@60.00Hz","1920x1080@60.00Hz","1920x1080@59.94Hz","1920x1080@50.00Hz","1600x1200@59.95Hz","1680x1050@59.88Hz","1280x1024@75.03Hz","1280x1024@60.02Hz","1440x900@59.90Hz","1280x800@59.95Hz","1280x720@120.00Hz","1280x720@119.88Hz","1280x720@100.00Hz","1280x720@60.00Hz","1280x720@59.94Hz","1280x720@50.00Hz","1024x768@75.03Hz","1024x768@70.07Hz","1024x768@60.00Hz","800x600@75.00Hz","800x600@72.19Hz","800x600@60.32Hz","800x600@56.25Hz","720x576@50.00Hz","720x576@50.00Hz","720x480@60.00Hz","720x480@60.00Hz","720x480@59.94Hz","720x480@59.94Hz","640x480@75.00Hz","640x480@72.81Hz","640x480@66.67Hz","640x480@60.00Hz","640x480@59.94Hz"]
}]
kotontrion commented 1 month ago

Looking at the x, y, width, height properties of the monitors in the hyprctl monitors -j output, the monitors do overlap.

Monitor 1 is positioned at 0,0 with a width of 1920, monitor 0 is positioned at 1080,0, so they do overlap according to those numbers.

Sadly there is no good way to map hyprland monitors to gdkmonitors in gtk3. You either have to try to map them using coordinates, which ags does, but this breaks when the monitors overlap, or map them using the display name, which is more robust, but uses functions which have been deprecated for long a long now. I have a function, which gets the display name from an gdkmknitor here in my dots , this can be easily modified to get the gdkmonitor from its name.

Not-a-true-statement commented 1 month ago

Looking at the x, y, width, height properties of the monitors in the hyprctl monitors -j output, the monitors do overlap.

Monitor 1 is positioned at 0,0 with a width of 1920, monitor 0 is positioned at 1080,0, so they do overlap according to those numbers.

If you look at the rotations (transform in the output) you will see that monitor 1 is rotated sideways and monitor 0 is upside down. This means that monitor height is the actual width therefore they do not overlap.

I will look into your implementation of determining the correct monitor.

Not-a-true-statement commented 1 month ago

I have rewritten my code and implemented the solution by @kotontrion . The following code works well for now.

// UTIL.JS file (slightly rewritten)
export function getMonitorName(gdkmonitor) {
    const screen = display?.get_default_screen();
    const screenCount = display?.get_n_monitors() ?? 1; 

    for(let i = 0; i < screenCount; ++i) {
        if(gdkmonitor === display?.get_monitor(i))
            return screen?.get_monitor_plug_name(i) ?? null;
    }
    return null;
}

// config.js
App.config({
    style: "./src/stylesheets/stylesheet.css",

    windows: () => {
        let bars = [];
        let monitors = hyprland.monitors;

        for (let monitorIndex = 0; monitorIndex < monitors.length; monitorIndex++) {
            const monitor = monitors[monitorIndex];
            let { id, name } = monitor;

            console.log(monitor);

            // Find correct GTK monitor for hyperland monitor
            const monitorCount = display?.get_n_monitors();
            for (let index = 0; index < (monitorCount ?? 1); index++) {
                let monitor = display?.get_monitor(index);
                if(getMonitorName(monitor) === name)
                    bars.push(Bar(monitor, id))     
            }
        }

        return bars;
    }
})