summaryrefslogblamecommitdiffstats
path: root/src/util/clientGUIUtils_X11.cpp
blob: 4b5afe0d2b7989d859c57b8fdfb2cda0723ef7e8 (plain) (tree)







































































































































































                                                                                                                                                                                                  










                                       
#include "clientGUIUtils.h"
#include <X11/Xlib.h>
#include <X11/cursorfont.h>


struct BlankScreen_Sysdep {

    Display *dpy;
    Window win;
    XEvent ev;
    int scr;

    bool locked;


    QString lockMsg;
    int blackColor, whiteColor;
    int offX, offY;
};

BlankScreen::BlankScreen()
{
    _sysdep = new BlankScreen_Sysdep;
    _sysdep->dpy = XOpenDisplay(NULL);
    _sysdep->scr = DefaultScreen(_sysdep->dpy);
    assert(_sysdep->dpy);
    _sysdep->blackColor = BlackPixel(_sysdep->dpy, DefaultScreen(_sysdep->dpy));
    _sysdep->whiteColor = WhitePixel(_sysdep->dpy, DefaultScreen(_sysdep->dpy));
//    win = XCreateSimpleWindow(_sysdep->dpy, DefaultRootWindow(_sysdep->dpy), 0, 0, 200, 100, 0, blackColor, whiteColor);
    _sysdep->win = XCreateSimpleWindow(_sysdep->dpy, RootWindow(_sysdep->dpy, _sysdep->scr), 10, 10, 200, 200, 1, WhitePixel(_sysdep->dpy, _sysdep->scr), BlackPixel(_sysdep->dpy, _sysdep->scr));

    XSelectInput(_sysdep->dpy, _sysdep->win, ExposureMask | KeyPressMask);
    _sysdep->locked = false;
    _sysdep->offX = _sysdep->offY = 0;
}

BlankScreen::~BlankScreen()
{
    delete _sysdep;
}

void BlankScreen::draw(bool force)
{
    if (_sysdep->locked)// no need to draw if we're not showing the window
    {
        XWindowAttributes xwa;
        XGetWindowAttributes(_sysdep->dpy, DefaultRootWindow(_sysdep->dpy), &xwa);
        int hx = (xwa.width)>>2, hy = (xwa.height)>>2;

        if (XCheckTypedEvent(_sysdep->dpy, Expose, &_sysdep->ev) || force )
        {
            hx += _sysdep->offX;
            hy += _sysdep->offY;

            GC gcc = XCreateGC(_sysdep->dpy, _sysdep->win, 0, NULL);
            XSetForeground(_sysdep->dpy, gcc, _sysdep->whiteColor);
//            XClearArea(_sysdep->dpy, _sysdep->win, 0, 0, xwa.width, xwa.height, false);
            if (_sysdep->lockMsg.size() > 0)
            {
                char *msg = const_cast<char*>(_sysdep->lockMsg.toUtf8().data());
                XDrawString(_sysdep->dpy, _sysdep->win, gcc/*DefaultGC(dpy, scr)*/, hx, hy, msg, strlen(msg));
            }
            else
            {
            }
        }
    }
}

bool BlankScreen::lock()
{
#define lock_test

    if (_sysdep->locked)
        return _sysdep->locked;

    // We want to get MapNotify events
    XSelectInput(_sysdep->dpy, _sysdep->win, StructureNotifyMask);

    // "Map" the window (that is, make it appear on the screen)
    XMapWindow(_sysdep->dpy, _sysdep->win);

    // Create a "Graphics Context"
    //GC gc = XCreateGC(dpy, win, 0, NULL);

    XEvent xev;
    Atom wm_state = XInternAtom(_sysdep->dpy, "_NET_WM_STATE", False);
    Atom fullscreen = XInternAtom(_sysdep->dpy, "_NET_WM_STATE_FULLSCREEN", False);
    memset(&xev, 0, sizeof(xev));
    xev.type = ClientMessage;
    xev.xclient.window = _sysdep->win;
    xev.xclient.message_type = wm_state;
    xev.xclient.format = 32;
    xev.xclient.data.l[0] = 1;
    xev.xclient.data.l[1] = fullscreen;
    xev.xclient.data.l[2] = 0;

    XSendEvent(_sysdep->dpy, DefaultRootWindow(_sysdep->dpy), False,
               SubstructureNotifyMask, &xev);




    // Wait for the MapNotify event
    for (;;)
    {
        XEvent e;
        XNextEvent(_sysdep->dpy, &e);
        if (e.type == MapNotify)
            break;
    }
    //Flush it!
    //XFlush(_sysdep->dpy);

#ifndef lock_test
    // load the locked cursor, so people dont think they can click anything
    // TODO: Use some kind of invisible cursor instead of the wait-cursor
    Cursor _sysdep->locked_cur = XCreateFontCursor(_sysdep->dpy, XC_watch);
    XDefineCursor(_sysdep->dpy, DefaultRootWindow(_sysdep->dpy),_sysdep->locked_cur);
#endif

    // grabbing of keyboard and mouse and hide the cursor
    XGrabKeyboard(_sysdep->dpy, DefaultRootWindow(_sysdep->dpy), false, GrabModeAsync, GrabModeAsync, CurrentTime);
    XGrabPointer(_sysdep->dpy, DefaultRootWindow(_sysdep->dpy), false, 0, GrabModeAsync, GrabModeAsync, None, NULL, CurrentTime);

    if (!_sysdep->locked)
        ConsoleLog writeLine(QString("Locked"));

    // see header for more information on this switch
    return _sysdep->locked = true;
}

bool BlankScreen::lock_inputs()
{
    // grabbing of keyboard and mouse and hide the cursor
    XGrabKeyboard(_sysdep->dpy, DefaultRootWindow(_sysdep->dpy), false, GrabModeAsync, GrabModeAsync, CurrentTime);
    XGrabPointer(_sysdep->dpy, DefaultRootWindow(_sysdep->dpy), false, 0, GrabModeAsync, GrabModeAsync, None, NULL, CurrentTime);
    return true;
}

bool BlankScreen::unlock()
{

    if (_sysdep->dpy)
    {

        int retval = -1;

        //reset cursor to arrow (no *real* default here...)
        Cursor normal_cur = XCreateFontCursor(_sysdep->dpy, XC_arrow);
        XDefineCursor(_sysdep->dpy, DefaultRootWindow(_sysdep->dpy), normal_cur);

        // ungrabbing of keyboard and mouse
        XUngrabPointer(_sysdep->dpy, CurrentTime);
        XUngrabKeyboard(_sysdep->dpy, CurrentTime);


        retval = XUnmapWindow(_sysdep->dpy,_sysdep->win);
        if (retval == BadWindow)
            ConsoleLog writeError(QString("Bad window while unmapping. Badwindow: ").append(int2String(retval)));
        XFlush(_sysdep->dpy);
    }
    if (_sysdep->locked)
        ConsoleLog writeLine(QString("Unlocked"));

    _sysdep->lockMsg.clear();
    return !(_sysdep->locked = false);
}

static Display* _dpy = 0;

Display* X11Info::display()
{
	if(!_dpy)
	{
		_dpy = XOpenDisplay(0);
	}
	return _dpy;
}