File indexing completed on 2024-12-22 04:31:07
0001 /* 0002 * Copyright (C) 2021 CutefishOS Team. 0003 * 0004 * Author: cutefish <cutefishos@foxmail.com> 0005 * 0006 * This program is free software: you can redistribute it and/or modify 0007 * it under the terms of the GNU General Public License as published by 0008 * the Free Software Foundation, either version 3 of the License, or 0009 * any later version. 0010 * 0011 * This program is distributed in the hope that it will be useful, 0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0014 * GNU General Public License for more details. 0015 * 0016 * You should have received a copy of the GNU General Public License 0017 * along with this program. If not, see <http://www.gnu.org/licenses/>. 0018 */ 0019 0020 #include "windowhelper.h" 0021 0022 #include <QApplication> 0023 #include <QX11Info> 0024 #include <QCursor> 0025 0026 #include <KWindowSystem> 0027 0028 static uint qtEdgesToXcbMoveResizeDirection(Qt::Edges edges) 0029 { 0030 if (edges == (Qt::TopEdge | Qt::LeftEdge)) 0031 return 0; 0032 if (edges == Qt::TopEdge) 0033 return 1; 0034 if (edges == (Qt::TopEdge | Qt::RightEdge)) 0035 return 2; 0036 if (edges == Qt::RightEdge) 0037 return 3; 0038 if (edges == (Qt::RightEdge | Qt::BottomEdge)) 0039 return 4; 0040 if (edges == Qt::BottomEdge) 0041 return 5; 0042 if (edges == (Qt::BottomEdge | Qt::LeftEdge)) 0043 return 6; 0044 if (edges == Qt::LeftEdge) 0045 return 7; 0046 0047 return 0; 0048 } 0049 0050 WindowHelper::WindowHelper(QObject *parent) 0051 : QObject(parent) 0052 , m_moveResizeAtom(0) 0053 , m_compositing(false) 0054 { 0055 // create move-resize atom 0056 // ref: https://github.com/qt/qtbase/blob/9db7cc79a26ced4997277b5c206ca15949133240/src/plugins/platforms/xcb/qxcbwindow.cpp 0057 xcb_connection_t* connection(QX11Info::connection()); 0058 const QString atomName(QStringLiteral("_NET_WM_MOVERESIZE")); 0059 xcb_intern_atom_cookie_t cookie(xcb_intern_atom(connection, false, atomName.size(), qPrintable(atomName))); 0060 QScopedPointer<xcb_intern_atom_reply_t> reply(xcb_intern_atom_reply(connection, cookie, nullptr)); 0061 m_moveResizeAtom = reply ? reply->atom : 0; 0062 0063 onCompositingChanged(KWindowSystem::compositingActive()); 0064 connect(KWindowSystem::self(), &KWindowSystem::compositingChanged, this, &WindowHelper::onCompositingChanged); 0065 } 0066 0067 bool WindowHelper::compositing() const 0068 { 0069 return m_compositing; 0070 } 0071 0072 void WindowHelper::startSystemMove(QWindow *w) 0073 { 0074 doStartSystemMoveResize(w, 16); 0075 } 0076 0077 void WindowHelper::startSystemResize(QWindow *w, Qt::Edges edges) 0078 { 0079 doStartSystemMoveResize(w, edges); 0080 } 0081 0082 void WindowHelper::minimizeWindow(QWindow *w) 0083 { 0084 KWindowSystem::minimizeWindow(w->winId()); 0085 } 0086 0087 void WindowHelper::doStartSystemMoveResize(QWindow *w, int edges) 0088 { 0089 const qreal dpiRatio = qApp->devicePixelRatio(); 0090 0091 xcb_connection_t *connection(QX11Info::connection()); 0092 xcb_client_message_event_t xev; 0093 xev.response_type = XCB_CLIENT_MESSAGE; 0094 xev.type = m_moveResizeAtom; 0095 xev.sequence = 0; 0096 xev.window = w->winId(); 0097 xev.format = 32; 0098 xev.data.data32[0] = QCursor::pos().x() * dpiRatio; 0099 xev.data.data32[1] = QCursor::pos().y() * dpiRatio; 0100 0101 if (edges == 16) 0102 xev.data.data32[2] = 8; // move 0103 else 0104 xev.data.data32[2] = qtEdgesToXcbMoveResizeDirection(Qt::Edges(edges)); 0105 0106 xev.data.data32[3] = XCB_BUTTON_INDEX_1; 0107 xev.data.data32[4] = 0; 0108 xcb_ungrab_pointer(connection, XCB_CURRENT_TIME); 0109 xcb_send_event(connection, false, QX11Info::appRootWindow(), 0110 XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY, 0111 (const char *)&xev); 0112 } 0113 0114 void WindowHelper::onCompositingChanged(bool enabled) 0115 { 0116 if (enabled != m_compositing) { 0117 m_compositing = enabled; 0118 emit compositingChanged(); 0119 } 0120 }