Xinerama opt in at runtime (no need for dev packages)


#1

This way we don’t need to link the Xinerama package, it will be only used if the user have it.

//==============================================================================
void juce_updateMultiMonitorInfo (Array <Rectangle>& monitorCoords, const bool /*clipToWorkArea*/) throw()
{
#if JUCE_USE_XINERAMA
    int major_opcode, first_event, first_error;

    if (XQueryExtension (display, "XINERAMA", &major_opcode, &first_event, &first_error))
    {
        typedef struct {
           int   screen_number;
           short x_org;
           short y_org;
           short width;
           short height;
        } XineramaScreenInfo;

        typedef Bool (*tXineramaIsActive) (Display*);
        typedef XineramaScreenInfo* (*tXineramaQueryScreens) (Display*, int*);

        static tXineramaIsActive xXineramaIsActive = 0;
        static tXineramaQueryScreens xXineramaQueryScreens = 0;

        if (xXineramaIsActive == 0 || xXineramaQueryScreens == 0)
        {
            void* h = dlopen ("libXinerama.so", RTLD_GLOBAL | RTLD_NOW);

            if (h != 0)
            {
                xXineramaIsActive = (tXineramaIsActive) dlsym (h, "XineramaIsActive");
                xXineramaQueryScreens = (tXineramaQueryScreens) dlsym (h, "XineramaQueryScreens");
            }
        }

        if (xXineramaIsActive != 0 
            && xXineramaQueryScreens != 0
            && xXineramaIsActive (display))
        {
            int numMonitors = 0;
            XineramaScreenInfo* const screens = xXineramaQueryScreens (display, &numMonitors);

            if (screens != 0)
            {
                for (int i = numMonitors; --i >= 0;)
                {
                    int index = screens[i].screen_number;

                    if (index >= 0)
                    {
                        while (monitorCoords.size() < index)
                            monitorCoords.add (Rectangle (0, 0, 0, 0));

                        monitorCoords.set (index, Rectangle (screens[i].x_org,
                                                             screens[i].y_org,
                                                             screens[i].width,
                                                             screens[i].height));
                    }
                }

                XFree (screens);
            }
        }
    }

    if (monitorCoords.size() == 0)
#endif
    {
        Atom hints = XInternAtom (display, "_NET_WORKAREA", True);

        if (hints != None)
        {
            const int numMonitors = ScreenCount (display);

            for (int i = 0; i < numMonitors; ++i)
            {
                Window root = RootWindow (display, i);

                unsigned long nitems, bytesLeft;
                Atom actualType;
                int actualFormat;
                unsigned char* data = 0;

                if (XGetWindowProperty (display, root, hints, 0, 4, False,
                                        XA_CARDINAL, &actualType, &actualFormat, &nitems, &bytesLeft,
                                        &data) == Success)
                {
                    const long* const position = (const long*) data;

                    if (actualType == XA_CARDINAL && actualFormat == 32 && nitems == 4)
                        monitorCoords.add (Rectangle (position[0], position[1],
                                                      position[2], position[3]));

                    XFree (data);
                }
            }
        }

        if (monitorCoords.size() == 0)
        {
            monitorCoords.add (Rectangle (0, 0,
                                          DisplayWidth (display, DefaultScreen (display)),
                                          DisplayHeight (display, DefaultScreen (display))));
        }
    }
}

and you can get rid of any #include <Xinerama.h>

Hope it will be included in the main tip!


#2

Cool - thanks very much! I guess I could also just remove the JUCE_USE_XINERAMA setting altogether. (Or is there a reason why you might want to disable it?)


#3

yes, eventually we can add the same for the Xshm extension. so if it is not present it will fall back.


#4