Beispiel #1
0
void Client::close()
{
    WindowManager *wm = WindowManager::instance();
    if (mOwned) {
        EventLoop::eventLoop()->callLater([this, wm] {
                delete this;
                xcb_flush(wm->connection());
            });
    } else {
        if (mProtocols.contains(Atoms::WM_DELETE_WINDOW)) {
            // delete
            xcb_client_message_event_t event;
            memset(&event, '\0', sizeof(event));
            event.response_type = XCB_CLIENT_MESSAGE;
            event.window = mWindow;
            event.format = 32;
            event.type = Atoms::WM_PROTOCOLS;
            event.data.data32[0] = Atoms::WM_DELETE_WINDOW;
            event.data.data32[1] = wm->timestamp();

            xcb_send_event(wm->connection(), false, mWindow, XCB_EVENT_MASK_NO_EVENT,
                           reinterpret_cast<char*>(&event));

        } else {
            xcb_kill_client(wm->connection(), mWindow);
        }
    }
}
Beispiel #2
0
void Client::focus()
{
    const bool takeFocus = mProtocols.count(Atoms::WM_TAKE_FOCUS) > 0;
    if (mNoFocus && !takeFocus)
        return;
    WindowManager *wm = WindowManager::instance();
    if (takeFocus) {
        xcb_client_message_event_t event;
        memset(&event, '\0', sizeof(event));
        event.response_type = XCB_CLIENT_MESSAGE;
        event.window = mWindow;
        event.format = 32;
        event.type = Atoms::WM_PROTOCOLS;
        event.data.data32[0] = Atoms::WM_TAKE_FOCUS;
        event.data.data32[1] = wm->timestamp();

        xcb_send_event(wm->connection(), false, mWindow, XCB_EVENT_MASK_NO_EVENT,
                       reinterpret_cast<char*>(&event));
    }
    xcb_set_input_focus(wm->connection(), XCB_INPUT_FOCUS_PARENT, mWindow, wm->timestamp());
    //error() << "Setting input focus to client" << mWindow << mClass.className;
    xcb_ewmh_set_active_window(wm->ewmhConnection(), mScreenNumber, mWindow);
    wm->setFocusedClient(this);
    if (mWorkspace)
        mWorkspace->updateFocus(this);
}
Beispiel #3
0
Client *Client::create(const Rect& rect, int screenNumber, const String &clazz, const String &instance, bool movable)
{
    WindowManager *wm = WindowManager::instance();
    xcb_connection_t* conn = wm->connection();
    xcb_screen_t* scr = wm->screens().at(screenNumber);

    xcb_window_t window = xcb_generate_id(conn);
    const uint32_t values[] = {
        scr->black_pixel,
        XCB_GRAVITY_NORTH_WEST,
        XCB_GRAVITY_NORTH_WEST,
        1,
        (XCB_EVENT_MASK_STRUCTURE_NOTIFY
         | XCB_EVENT_MASK_ENTER_WINDOW
         | XCB_EVENT_MASK_LEAVE_WINDOW
         | XCB_EVENT_MASK_EXPOSURE
         | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT
         | XCB_EVENT_MASK_POINTER_MOTION
         | XCB_EVENT_MASK_BUTTON_PRESS
         | XCB_EVENT_MASK_BUTTON_RELEASE)
    };
    warning() << "creating client window" << rect;
    xcb_create_window(conn, XCB_COPY_FROM_PARENT, window, scr->root,
                      rect.x, rect.y, rect.width, rect.height, 0,
                      XCB_COPY_FROM_PARENT, XCB_COPY_FROM_PARENT,
                      XCB_CW_BORDER_PIXEL | XCB_CW_BIT_GRAVITY | XCB_CW_WIN_GRAVITY
                      | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK, values);

    xcb_icccm_wm_hints_t wmHints;
    xcb_icccm_wm_hints_set_none(&wmHints);
    xcb_icccm_wm_hints_set_input(&wmHints, 0);
    xcb_icccm_set_wm_hints(conn, window, &wmHints);

    xcb_size_hints_t wmNormalHints;
    memset(&wmNormalHints, 0, sizeof(wmNormalHints));
    xcb_icccm_size_hints_set_position(&wmNormalHints, 1, rect.x, rect.y);
    xcb_icccm_size_hints_set_size(&wmNormalHints, 1, rect.width, rect.height);
    xcb_icccm_set_wm_normal_hints(conn, window, &wmNormalHints);

    String className = clazz + ' ' + instance;
    className[clazz.size()] = '\0';
    xcb_icccm_set_wm_class(conn, window, className.size(), className.constData());
    Client *ptr = new Client(window);
    ptr->mMovable = movable;
    ptr->mRect = rect;
    ptr->mOwned = true;
    ptr->mScreenNumber = screenNumber;
    ptr->init();
    ptr->mNoFocus = true;
    Workspace *ws = wm->activeWorkspace(screenNumber);
    assert(ws);
    ptr->mWorkspace = ws;
    ws->addClient(ptr);

    wm->js().onClient(ptr);
    ptr->complete();

    sClients[window] = ptr;
    return ptr;
}
Beispiel #4
0
void Client::complete()
{
    WindowManager *wm = WindowManager::instance();
    xcb_connection_t* conn = wm->connection();
    xcb_ewmh_connection_t* ewmhConn = wm->ewmhConnection();
    if (mEwmhState.contains(ewmhConn->_NET_WM_STATE_STICKY)) {
        // don't put in layout
#warning support strut windows in layouts (reserved space)
#warning support partial struts
        Rect rect = wm->rect(mScreenNumber);
        if (mStrut.left) {
            if (mRect.width != static_cast<int>(mStrut.left))
                mRect.width = mStrut.left;
            mRect.x = rect.x;
            rect.x += mRect.width;
            rect.width -= mRect.width;
        } else if (mStrut.right) {
            if (mRect.width != static_cast<int>(mStrut.right))
                mRect.width = mStrut.right;
            mRect.x = rect.x + rect.width - mStrut.right;
            rect.width -= mStrut.right;
        } else if (mStrut.top) {
            if (mRect.height != static_cast<int>(mStrut.top))
                mRect.height = mStrut.top;
            mRect.y = rect.y;
            rect.y += mRect.height;
            rect.height -= mRect.height;
        } else if (mStrut.bottom) {
            if (mRect.height != static_cast<int>(mStrut.bottom))
                mRect.height = mStrut.bottom;
            mRect.y = rect.y + rect.height - mStrut.bottom;
            rect.height -= mStrut.bottom;
        }
        wm->setRect(rect, mScreenNumber);
        warning() << "fixed at" << mRect;
    } else {
        if (shouldLayout()) {
            wm->js().onLayout(this);
            warning() << "laid out at" << mRect;
        }
    }
#warning do startup-notification stuff here
    if (!mOwned)
        xcb_change_save_set(conn, XCB_SET_MODE_INSERT, mWindow);
    xcb_screen_t* scr = screen();
    mFrame = xcb_generate_id(conn);
    const uint32_t values[] = {
        scr->black_pixel,
        XCB_GRAVITY_NORTH_WEST,
        XCB_GRAVITY_NORTH_WEST,
        1,
        (XCB_EVENT_MASK_STRUCTURE_NOTIFY
         | XCB_EVENT_MASK_ENTER_WINDOW
         | XCB_EVENT_MASK_LEAVE_WINDOW
         | XCB_EVENT_MASK_EXPOSURE
         | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT
         | XCB_EVENT_MASK_POINTER_MOTION
         | XCB_EVENT_MASK_BUTTON_PRESS
         | XCB_EVENT_MASK_BUTTON_RELEASE)
    };
    warning() << "creating frame window" << mRect;
    xcb_create_window(conn, XCB_COPY_FROM_PARENT, mFrame, scr->root,
                      mRect.x, mRect.y, mRect.width, mRect.height, 0,
                      XCB_COPY_FROM_PARENT, XCB_COPY_FROM_PARENT,
                      XCB_CW_BORDER_PIXEL | XCB_CW_BIT_GRAVITY | XCB_CW_WIN_GRAVITY
                      | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK, values);
    {
        ServerGrabScope grabScope(conn);
        const uint32_t noValue[] = { 0 };
        xcb_change_window_attributes(conn, scr->root, XCB_CW_EVENT_MASK, noValue);
        xcb_reparent_window(conn, mWindow, mFrame, 0, 0);
        const uint32_t rootEvent[] = { Types::RootEventMask };
        xcb_change_window_attributes(conn, scr->root, XCB_CW_EVENT_MASK, rootEvent);
        xcb_grab_button(conn, false, mWindow, XCB_EVENT_MASK_BUTTON_PRESS,
                        XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC, scr->root,
                        XCB_NONE, 1, XCB_BUTTON_MASK_ANY);
        const uint32_t windowEvent[] = { Types::ClientInputMask };
        xcb_change_window_attributes(conn, mWindow, XCB_CW_EVENT_MASK, windowEvent);
    }

    {
        uint16_t windowMask = XCB_CONFIG_WINDOW_WIDTH|XCB_CONFIG_WINDOW_HEIGHT|XCB_CONFIG_WINDOW_BORDER_WIDTH;
        uint32_t windowValues[3];
        int i = 0;
        windowValues[i++] = mRect.width;
        windowValues[i++] = mRect.height;
        windowValues[i++] = 0;
        xcb_configure_window(conn, mWindow, windowMask, windowValues);
    }

#warning do xinerama placement
    const uint32_t stateMode[] = { XCB_ICCCM_WM_STATE_NORMAL, XCB_NONE };
    xcb_change_property(conn, XCB_PROP_MODE_REPLACE, mWindow, Atoms::WM_STATE, Atoms::WM_STATE, 32, 2, stateMode);

    map();
    raise();
    warning() << "created and mapped parent client for frame" << mFrame << "with window" << mWindow;
}