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; }
// === SetAsPanel() === void LXCB::SetAsPanel(WId win){ if(DEBUG){ qDebug() << "XCB: SetAsPanel()"; } if(win==0){ return; } SetDisableWMActions(win); //also need to disable WM actions for this window //Disable Input focus (panel activation ruins task manager window detection routines) // - Disable Input flag in WM_HINTS xcb_icccm_wm_hints_t hints; //qDebug() << " - Disable WM_HINTS input flag"; xcb_get_property_cookie_t cookie = xcb_icccm_get_wm_hints_unchecked(QX11Info::connection(), win); //qDebug() << " -- got cookie"; if(1 == xcb_icccm_get_wm_hints_reply(QX11Info::connection(), cookie, &hints, NULL) ){ //qDebug() << " -- Set no inputs flag"; xcb_icccm_wm_hints_set_input(&hints, false); //set no input focus xcb_icccm_set_wm_hints(QX11Info::connection(), win, &hints); //save hints back to window } // - Remove WM_TAKE_FOCUS from the WM_PROTOCOLS for the window // - - Generate the necessary atoms //qDebug() << " - Generate WM_PROTOCOLS and WM_TAKE_FOCUS atoms"; xcb_atom_t WM_PROTOCOLS, WM_TAKE_FOCUS; //the two atoms needed xcb_intern_atom_reply_t *preply = xcb_intern_atom_reply(QX11Info::connection(), \ xcb_intern_atom(QX11Info::connection(), 0, 12, "WM_PROTOCOLS"), NULL); xcb_intern_atom_reply_t *freply = xcb_intern_atom_reply(QX11Info::connection(), \ xcb_intern_atom(QX11Info::connection(), 0, 13, "WM_TAKE_FOCUS"), NULL); bool gotatoms = false; if(preply && freply){ WM_PROTOCOLS = preply->atom; WM_TAKE_FOCUS = freply->atom; free(preply); free(freply); gotatoms = true; //qDebug() << " -- success"; } // - - Now update the protocols for the window if(gotatoms){ //requires the atoms //qDebug() << " - Get WM_PROTOCOLS"; xcb_icccm_get_wm_protocols_reply_t proto; if( 1 == xcb_icccm_get_wm_protocols_reply(QX11Info::connection(), \ xcb_icccm_get_wm_protocols_unchecked(QX11Info::connection(), win, WM_PROTOCOLS), \ &proto, NULL) ){ //Found the current protocols, see if it has the focus atom set //remove the take focus atom and re-save them bool needremove = false; //Note: This first loop is required so that we can initialize the modified list with a valid size //qDebug() << " -- Check current protocols"; for(unsigned int i=0; i<proto.atoms_len; i++){ if(proto.atoms[i] == WM_TAKE_FOCUS){ needremove = true; break;} } if(needremove){ //qDebug() << " -- Remove WM_TAKE_FOCUS protocol"; xcb_atom_t *protolist = new xcb_atom_t[proto.atoms_len-1]; int num = 0; for(unsigned int i=0; i<proto.atoms_len; i++){ if(proto.atoms[i] != WM_TAKE_FOCUS){ protolist[num] = proto.atoms[i]; num++; } } //qDebug() << " -- Re-save modified protocols"; xcb_icccm_set_wm_protocols(QX11Info::connection(), win, WM_PROTOCOLS, num, protolist); } //qDebug() << " -- Clear protocols reply"; xcb_icccm_get_wm_protocols_reply_wipe(&proto); }//end of get protocols check } //end of gotatoms check //Make sure it has the "dock" window type // - get the current window types (Not necessary, only 1 type of window needed) // - set the adjusted window type(s) //qDebug() << " - Adjust window type"; xcb_atom_t list[1]; list[0] = EWMH._NET_WM_WINDOW_TYPE_DOCK; xcb_ewmh_set_wm_window_type(&EWMH, win, 1, list); //Make sure it is on all workspaces //qDebug() << " - Set window as sticky"; SetAsSticky(win); }