/*************************************************************************** * Based on Licq * * Copyright (C) 2006-2009 Licq developers * * Copyright (C) 2011 Ilya Kotov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "windowsystem.h" #include #ifdef Q_WS_X11 #include #include #include #include #include #endif #ifdef Q_WS_X11 void WindowSystem::ghostWindow(WId win) { Display* dsp = QX11Info::display(); Window root = DefaultRootWindow(dsp); Atom win_state = XInternAtom(dsp, "_NET_WM_STATE", False); Atom win_state_add = XInternAtom(dsp, "_NET_WM_STATE_ADD", False); Atom win_state_settings[] = { XInternAtom(dsp, "_NET_WM_STATE_SKIP_TASKBAR", False), XInternAtom(dsp, "_NET_WM_STATE_SKIP_PAGER", False) }; XChangeProperty(dsp, win, win_state, XA_ATOM, 32, PropModeReplace, reinterpret_cast(&win_state_settings), 2); XEvent xev; xev.type = ClientMessage; xev.xclient.type = ClientMessage; xev.xclient.display = dsp; xev.xclient.window = win; xev.xclient.message_type = win_state; xev.xclient.format = 32; xev.xclient.data.l[0] = win_state_add; xev.xclient.data.l[1] = win_state_settings[0]; xev.xclient.data.l[2] = win_state_settings[1]; XSendEvent(dsp, root, false, SubstructureRedirectMask | SubstructureNotifyMask, &xev); } QString WindowSystem::netWindowManagerName() { Display* dsp = QX11Info::display(); WId root = DefaultRootWindow(dsp); unsigned char* retValue1 = NULL; unsigned char* retValue2 = NULL; retValue1 = getWindowProperty(root, "_NET_SUPPORTING_WM_CHECK"); if (retValue1 == NULL) return QString(); WId win = *(reinterpret_cast(retValue1)); retValue2 = getWindowProperty(win, "_NET_SUPPORTING_WM_CHECK"); if (retValue2 == NULL) { XFree(retValue1); return QString(); } if (win != *(reinterpret_cast(retValue2))) { XFree(retValue1); XFree(retValue2); return QString(); } XFree(retValue2); retValue2 = NULL; retValue2 = getWindowProperty(win, "_NET_WM_NAME"); XFree(retValue1); if (retValue2 == NULL) return QString(); QString name = QString((char *)retValue2); XFree(retValue2); return name; } void WindowSystem::changeWinSticky(WId win, bool stick) { qDebug("WindowSystem: setting sticky state of window 0x%lx to %s.", static_cast(win), stick ? "true" : "false"); Display* dsp = QX11Info::display(); Window root = DefaultRootWindow(dsp); unsigned long desktop = ~(0UL); if (!stick) { unsigned char* tmp = getWindowProperty(root, "_NET_CURRENT_DESKTOP"); if (tmp == NULL) qWarning("WindowSystem: error reading current desktop property."); else { desktop = *(reinterpret_cast(tmp)); XFree(tmp); } } XEvent xev; xev.type = ClientMessage; xev.xclient.type = ClientMessage; xev.xclient.display = dsp; xev.xclient.window = win; xev.xclient.message_type = XInternAtom(dsp, "_NET_WM_DESKTOP", False); xev.xclient.format = 32; xev.xclient.data.l[0] = desktop; XSendEvent(dsp, root, False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); } void WindowSystem::setWinHint(WId win, const char *res_name, const char *res_class) { Display* dsp = QX11Info::display(); XClassHint hint; hint.res_name = strdup(res_name); hint.res_class = strdup(res_class); XSetClassHint(dsp, win, &hint); free(hint.res_name); free(hint.res_class); } unsigned char* WindowSystem::getWindowProperty(WId win, const char* prop) { Display* dsp = QX11Info::display(); // We inhibit new Atom creation since if you request for it // then such Atom most probably exists already. // Otherwise, no surprise we return NULL here. Atom reqAtom = XInternAtom(dsp, prop, True); if (reqAtom == None) return NULL; int retCheck = None; Atom retType = None; int retFormat = 0; unsigned long retItems = 0UL; unsigned long retMoreBytes = 0UL; unsigned char* retValue = NULL; // Check if the property exists and calculate its length. retCheck = XGetWindowProperty(dsp, win, reqAtom, 0L, 0L, False, AnyPropertyType, &retType, &retFormat, &retItems, &retMoreBytes, &retValue); // The value is most probably empty, since we requested to read // only 0L length, thus, it's just useless... if (retValue != NULL) { XFree(retValue); retValue = NULL; } if (retCheck != Success || retType == None || retMoreBytes == 0) return NULL; // These are not needed for now. retCheck = None; retFormat = 0; retItems = 0UL; // Convert the byte length into 32bit multiples. if (retMoreBytes % 4 != 0) retMoreBytes += 4 - retMoreBytes % 4; retMoreBytes /= 4; // Now request the actual property value with correct length and type. retCheck = XGetWindowProperty(dsp, win, reqAtom, 0L, retMoreBytes, False, retType, &retType, &retFormat, &retItems, &retMoreBytes, &retValue); if (retCheck != Success || retMoreBytes != 0) { if (retValue != NULL) XFree(retValue); return NULL; } return retValue; } #endif