void TitleWidget::mouseMoveEvent(QGraphicsSceneMouseEvent* event) { Plasma::IconWidget::mouseMoveEvent(event); if (m_drag && (event->buttons() & Qt::LeftButton)) { WId wid = KWindowSystem::activeWindow(); if (wid) { XUngrabPointer(QX11Info::display(), QX11Info::appTime()); NETRootInfo rootInfo(QX11Info::display(), NET::WMMoveResize); KWindowInfo info = KWindowSystem::windowInfo(wid, NET::WMGeometry); int x; int y; QPointF p = event->screenPos(); if (p.x() > info.geometry().x() && p.x() < info.geometry().x() + info.geometry().width()) x = p.x(); else x = info.geometry().x(); if (p.y() > info.geometry().y() && p.y() < info.geometry().y() + info.geometry().height()) y = p.y(); else y = info.geometry().y(); rootInfo.moveResizeRequest( wid, x, y, NET::Move); } } }
void WindowManager::startDrag(QWidget *widget, const QPoint& position) { if (!(enabled() && widget)) { return; } if (QWidget::mouseGrabber()) { return; } // ungrab pointer if (useWMMoveResize()) { #if defined Q_WS_X11 && QT_VERSION < 0x050000 #ifndef ENABLE_KDE_SUPPORT static const Atom constNetMoveResize = XInternAtom(QX11Info::display(), "_NET_WM_MOVERESIZE", False); //...Taken from bespin... // stolen... errr "adapted!" from QSizeGrip QX11Info info; XEvent xev; xev.xclient.type = ClientMessage; xev.xclient.message_type = constNetMoveResize; xev.xclient.display = QX11Info::display(); xev.xclient.window = widget->window()->winId(); xev.xclient.format = 32; xev.xclient.data.l[0] = position.x(); xev.xclient.data.l[1] = position.y(); xev.xclient.data.l[2] = 8; // NET::Move xev.xclient.data.l[3] = Button1; xev.xclient.data.l[4] = 0; XUngrabPointer(QX11Info::display(), QX11Info::appTime()); XSendEvent(QX11Info::display(), QX11Info::appRootWindow(info.screen()), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); #else XUngrabPointer(QX11Info::display(), QX11Info::appTime()); NETRootInfo rootInfo(QX11Info::display(), NET::WMMoveResize); rootInfo.moveResizeRequest(widget->window()->winId(), position.x(), position.y(), NET::Move); #endif // !ENABLE_KDE_SUPPORT #endif } if (!useWMMoveResize() && !_cursorOverride) { qApp->setOverrideCursor(Qt::DragMoveCursor); _cursorOverride = true; } _dragInProgress = true; return; }
/*! Propagates the managed clients to the world. Called ONLY from updateStackingOrder(). */ void Workspace::propagateClients(bool propagate_new_clients) { // restack the windows according to the stacking order // supportWindow > electric borders > clients > hidden clients QVector<xcb_window_t> newWindowStack; // Stack all windows under the support window. The support window is // not used for anything (besides the NETWM property), and it's not shown, // but it was lowered after kwin startup. Stacking all clients below // it ensures that no client will be ever shown above override-redirect // windows (e.g. popups). newWindowStack << rootInfo()->supportWindow(); newWindowStack << ScreenEdges::self()->windows(); newWindowStack.reserve(newWindowStack.size() + 2*stacking_order.size()); // *2 for inputWindow for (int i = stacking_order.size() - 1; i >= 0; --i) { Client *client = qobject_cast<Client*>(stacking_order.at(i)); if (!client || client->hiddenPreview()) { continue; } if (client->inputId()) // Stack the input window above the frame newWindowStack << client->inputId(); newWindowStack << client->frameId(); } // when having hidden previews, stack hidden windows below everything else // (as far as pure X stacking order is concerned), in order to avoid having // these windows that should be unmapped to interfere with other windows for (int i = stacking_order.size() - 1; i >= 0; --i) { Client *client = qobject_cast<Client*>(stacking_order.at(i)); if (!client || !client->hiddenPreview()) continue; newWindowStack << client->frameId(); } // TODO isn't it too inefficient to restack always all clients? // TODO don't restack not visible windows? assert(newWindowStack.at(0) == rootInfo()->supportWindow()); Xcb::restackWindows(newWindowStack); int pos = 0; xcb_window_t *cl(nullptr); if (propagate_new_clients) { cl = new xcb_window_t[ desktops.count() + clients.count()]; // TODO this is still not completely in the map order for (ClientList::ConstIterator it = desktops.constBegin(); it != desktops.constEnd(); ++it) cl[pos++] = (*it)->window(); for (ClientList::ConstIterator it = clients.constBegin(); it != clients.constEnd(); ++it) cl[pos++] = (*it)->window(); rootInfo()->setClientList(cl, pos); delete [] cl; } cl = new xcb_window_t[ stacking_order.count()]; pos = 0; for (ToplevelList::ConstIterator it = stacking_order.constBegin(); it != stacking_order.constEnd(); ++it) { if ((*it)->isClient()) cl[pos++] = (*it)->window(); } rootInfo()->setClientListStacking(cl, pos); delete [] cl; // Make the cached stacking order invalid here, in case we need the new stacking order before we get // the matching event, due to X being asynchronous. x_stacking_dirty = true; }