a-ba / squint

Duplicate an X11 monitor into a window
GNU General Public License v3.0
16 stars 2 forks source link

[Feature Request] Mirroring disconnected monitors #2

Open Salama opened 2 years ago

Salama commented 2 years ago

Mirroring disconnected monitors would be useful for online presentations

a-ba commented 2 years ago

This is feasible with virtual monitors, though i don't know if this hack works with any xorg driver.

see: https://unix.stackexchange.com/questions/626451/displaying-an-x11-virtual-screen-in-a-window#631697

Salama commented 2 years ago

I used that before, but I changed from intel driver to modesetting due to performance improvements and I haven't found a working virtual display setup that doesn't include fake disconnected monitors that are still there. Discord can somehow screenshare a disconnected monitor, so it should be possible.

a-ba commented 2 years ago

perhaps you can use ltrace or wireshark to trace the calls to the xrandr API and see how it achieves that

Salama commented 2 years ago

Looks like it can be achieved by removing

#ifdef HAVE_XRANDR
    if (xrandr_event_base)
    {
        if (ev->type == xrandr_event_base + RRScreenChangeNotify) {
            squint_disable();
        }
    }
#endif

and somehow finding the monitor dimensions even though it's disconnected (maybe another library?). I was able to get it to work by hardcoding src_rect and dst_rect.

Salama commented 2 years ago

Here is an example code that can get the monitor dimensions with their names even if they're disconnected.

#include <X11/extensions/Xrandr.h>
#include <stdio.h>

int main() {
    Display *display;
    display = XOpenDisplay(0);
    int nmonitors = 0;
    XRRMonitorInfo *monitors;
    monitors = XRRGetMonitors(display, DefaultRootWindow(display), 1, &nmonitors);
    XRRScreenResources *screen_res = XRRGetScreenResources(display, DefaultRootWindow(display));
    for(unsigned i = 0; i < nmonitors; i++) {
        XRRCrtcInfo *screen_info = XRRGetCrtcInfo(display, screen_res, screen_res->crtcs[i]);
        XRROutputInfo *output_info = XRRGetOutputInfo(display, screen_res, screen_res->outputs[i]);

        fprintf(stdout, "%s %d %d %d %d\n", output_info->name, screen_info->x, screen_info->y, screen_info->width, screen_info->height);
    }
}
Salama commented 2 years ago

Should I implement this and make a pull request or will you? If I make it, should libxrandr be kept as an optional dependency for a chance of having it merged?

a-ba commented 2 years ago

That would be fine.

I've had a look at the sources of gdk3 and i have several points to add:

My thoughts for the merge request:

Salama commented 2 years ago

Should connected source monitors have priority over disconnected ones in auto selection unless there is only one connected monitor?

a-ba commented 2 years ago

I have not really thought about it. I am only concerned about the destination: we must avoid auto-selecting a disconnected monitor for destination so as not to undermine the user experience (because nothing would appear on any monitor).

I do not have any clear idea for the source. At first sight I would rather give priority to the disconnected monitors (assuming that the user wants to see the undisplayed parts of the screen), but that's just a guts feeling.