x11: Merge Unmanaged into X11Window
Currently, managed and override-redirect windows are split in two types: X11Window and Unmanaged. While looking at it strictly from type perspective, this is great. But it creates other problems, e.g. we need to put shared X11-specific code in the base Window class or mess with "base" classes. As an alternative solution, this change merges the Unmanaged class into the X11Window class and disables some functionality based on the value of isUnmanaged(). X11Window::manage() is used to create a managed Window. X11Window::track() is used to create an unmanaged Window.
This commit is contained in:
parent
062f092f38
commit
dbbcf31d0d
23 changed files with 433 additions and 555 deletions
|
@ -11,7 +11,6 @@
|
|||
#include "core/outputbackend.h"
|
||||
#include "main.h"
|
||||
#include "scene/workspacescene.h"
|
||||
#include "unmanaged.h"
|
||||
#include "wayland_server.h"
|
||||
#include "workspace.h"
|
||||
#include "x11window.h"
|
||||
|
@ -36,7 +35,6 @@ private Q_SLOTS:
|
|||
|
||||
void XwaylandServerCrashTest::initTestCase()
|
||||
{
|
||||
qRegisterMetaType<Unmanaged *>();
|
||||
qRegisterMetaType<X11Window *>();
|
||||
QSignalSpy applicationStartedSpy(kwinApp(), &Application::started);
|
||||
QVERIFY(waylandServer()->init(s_socketName));
|
||||
|
@ -99,7 +97,7 @@ void XwaylandServerCrashTest::testCrash()
|
|||
|
||||
QSignalSpy unmanagedAddedSpy(workspace(), &Workspace::windowAdded);
|
||||
QVERIFY(unmanagedAddedSpy.wait());
|
||||
QPointer<Unmanaged> unmanaged = unmanagedAddedSpy.last().first().value<Unmanaged *>();
|
||||
QPointer<X11Window> unmanaged = unmanagedAddedSpy.last().first().value<X11Window *>();
|
||||
QVERIFY(unmanaged);
|
||||
|
||||
// Let's pretend that the Xwayland process has crashed.
|
||||
|
|
|
@ -163,7 +163,6 @@ target_sources(kwin PRIVATE
|
|||
tiles/tile.cpp
|
||||
tiles/tilemanager.cpp
|
||||
touch_input.cpp
|
||||
unmanaged.cpp
|
||||
useractions.cpp
|
||||
virtualdesktops.cpp
|
||||
virtualdesktopsdbustypes.cpp
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
*/
|
||||
#include "x11_standalone_windowselector.h"
|
||||
#include "cursor.h"
|
||||
#include "unmanaged.h"
|
||||
#include "utils/xcbutils.h"
|
||||
#include "workspace.h"
|
||||
#include "x11window.h"
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
#include "scene/workspacescene_opengl.h"
|
||||
#include "scene/workspacescene_qpainter.h"
|
||||
#include "shadow.h"
|
||||
#include "unmanaged.h"
|
||||
#include "useractions.h"
|
||||
#include "utils/common.h"
|
||||
#include "utils/xcbutils.h"
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include "main.h"
|
||||
#include "placement.h"
|
||||
#include "pluginmanager.h"
|
||||
#include "unmanaged.h"
|
||||
#include "virtualdesktops.h"
|
||||
#include "window.h"
|
||||
#include "workspace.h"
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
#include "libkwineffects/kwinglutils.h"
|
||||
#include "main.h"
|
||||
#include "platformsupport/scenes/opengl/openglbackend.h"
|
||||
#include "unmanaged.h"
|
||||
#include "utils/filedescriptor.h"
|
||||
#include "utils/subsurfacemonitor.h"
|
||||
#include "wayland/abstract_data_source.h"
|
||||
|
@ -926,7 +925,11 @@ DebugConsoleModel::DebugConsoleModel(QObject *parent)
|
|||
void DebugConsoleModel::handleWindowAdded(Window *window)
|
||||
{
|
||||
if (auto x11 = qobject_cast<X11Window *>(window)) {
|
||||
add(s_x11WindowId - 1, m_x11Windows, x11);
|
||||
if (x11->isUnmanaged()) {
|
||||
add(s_x11UnmanagedId - 1, m_unmanageds, x11);
|
||||
} else {
|
||||
add(s_x11WindowId - 1, m_x11Windows, x11);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -939,17 +942,16 @@ void DebugConsoleModel::handleWindowAdded(Window *window)
|
|||
add(s_workspaceInternalId - 1, m_internalWindows, internal);
|
||||
return;
|
||||
}
|
||||
|
||||
if (auto unmanaged = qobject_cast<Unmanaged *>(window)) {
|
||||
add(s_x11UnmanagedId - 1, m_unmanageds, unmanaged);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void DebugConsoleModel::handleWindowRemoved(Window *window)
|
||||
{
|
||||
if (auto x11 = qobject_cast<X11Window *>(window)) {
|
||||
remove(s_x11WindowId - 1, m_x11Windows, x11);
|
||||
if (x11->isUnmanaged()) {
|
||||
remove(s_x11UnmanagedId - 1, m_unmanageds, x11);
|
||||
} else {
|
||||
remove(s_x11WindowId - 1, m_x11Windows, x11);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -962,11 +964,6 @@ void DebugConsoleModel::handleWindowRemoved(Window *window)
|
|||
remove(s_workspaceInternalId - 1, m_internalWindows, internal);
|
||||
return;
|
||||
}
|
||||
|
||||
if (auto unmanaged = qobject_cast<Unmanaged *>(window)) {
|
||||
remove(s_x11UnmanagedId - 1, m_unmanageds, unmanaged);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
DebugConsoleModel::~DebugConsoleModel() = default;
|
||||
|
@ -1230,7 +1227,7 @@ QVariant DebugConsoleModel::data(const QModelIndex &index, int role) const
|
|||
return propertyData(w, index, role);
|
||||
} else if (X11Window *w = x11Window(index)) {
|
||||
return propertyData(w, index, role);
|
||||
} else if (Unmanaged *u = unmanaged(index)) {
|
||||
} else if (X11Window *u = unmanaged(index)) {
|
||||
return propertyData(u, index, role);
|
||||
}
|
||||
} else {
|
||||
|
@ -1293,7 +1290,7 @@ X11Window *DebugConsoleModel::x11Window(const QModelIndex &index) const
|
|||
return windowForIndex(index, m_x11Windows, s_x11WindowId);
|
||||
}
|
||||
|
||||
Unmanaged *DebugConsoleModel::unmanaged(const QModelIndex &index) const
|
||||
X11Window *DebugConsoleModel::unmanaged(const QModelIndex &index) const
|
||||
{
|
||||
return windowForIndex(index, m_unmanageds, s_x11UnmanagedId);
|
||||
}
|
||||
|
|
|
@ -37,7 +37,6 @@ namespace KWin
|
|||
class Window;
|
||||
class X11Window;
|
||||
class InternalWindow;
|
||||
class Unmanaged;
|
||||
class DebugConsoleFilter;
|
||||
class WaylandWindow;
|
||||
|
||||
|
@ -75,13 +74,13 @@ private:
|
|||
WaylandWindow *waylandWindow(const QModelIndex &index) const;
|
||||
InternalWindow *internalWindow(const QModelIndex &index) const;
|
||||
X11Window *x11Window(const QModelIndex &index) const;
|
||||
Unmanaged *unmanaged(const QModelIndex &index) const;
|
||||
X11Window *unmanaged(const QModelIndex &index) const;
|
||||
int topLevelRowCount() const;
|
||||
|
||||
QVector<WaylandWindow *> m_waylandWindows;
|
||||
QVector<InternalWindow *> m_internalWindows;
|
||||
QVector<X11Window *> m_x11Windows;
|
||||
QVector<Unmanaged *> m_unmanageds;
|
||||
QVector<X11Window *> m_unmanageds;
|
||||
};
|
||||
|
||||
class DebugConsoleDelegate : public QStyledItemDelegate
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
#include "pointer_input.h"
|
||||
#include "scene/itemrenderer.h"
|
||||
#include "scripting/scripting.h"
|
||||
#include "unmanaged.h"
|
||||
#include "x11window.h"
|
||||
#if KWIN_BUILD_TABBOX
|
||||
#include "tabbox/tabbox.h"
|
||||
|
@ -996,7 +995,7 @@ EffectWindow *EffectsHandlerImpl::findWindow(WId id) const
|
|||
if (X11Window *w = Workspace::self()->findClient(Predicate::WindowMatch, id)) {
|
||||
return w->effectWindow();
|
||||
}
|
||||
if (Unmanaged *w = Workspace::self()->findUnmanaged(id)) {
|
||||
if (X11Window *w = Workspace::self()->findUnmanaged(id)) {
|
||||
return w->effectWindow();
|
||||
}
|
||||
return nullptr;
|
||||
|
@ -1855,7 +1854,7 @@ EffectWindowImpl::EffectWindowImpl(Window *window)
|
|||
managed = window->isClient();
|
||||
|
||||
m_waylandWindow = qobject_cast<KWin::WaylandWindow *>(window) != nullptr;
|
||||
m_x11Window = qobject_cast<KWin::X11Window *>(window) != nullptr || qobject_cast<KWin::Unmanaged *>(window) != nullptr;
|
||||
m_x11Window = qobject_cast<KWin::X11Window *>(window) != nullptr;
|
||||
}
|
||||
|
||||
EffectWindowImpl::~EffectWindowImpl()
|
||||
|
|
188
src/events.cpp
188
src/events.cpp
|
@ -27,7 +27,6 @@
|
|||
#include "group.h"
|
||||
#include "rules.h"
|
||||
#include "screenedge.h"
|
||||
#include "unmanaged.h"
|
||||
#include "useractions.h"
|
||||
#include "utils/xcbutils.h"
|
||||
#include "wayland/surface_interface.h"
|
||||
|
@ -168,7 +167,7 @@ bool Workspace::workspaceEvent(xcb_generic_event_t *e)
|
|||
if (window->windowEvent(e)) {
|
||||
return true;
|
||||
}
|
||||
} else if (Unmanaged *window = findUnmanaged(eventWindow)) {
|
||||
} else if (X11Window *window = findUnmanaged(eventWindow)) {
|
||||
if (window->windowEvent(e)) {
|
||||
return true;
|
||||
}
|
||||
|
@ -223,7 +222,7 @@ bool Workspace::workspaceEvent(xcb_generic_event_t *e)
|
|||
case XCB_MAP_NOTIFY: {
|
||||
const auto *event = reinterpret_cast<xcb_map_notify_event_t *>(e);
|
||||
if (event->override_redirect) {
|
||||
Unmanaged *window = findUnmanaged(event->window);
|
||||
X11Window *window = findUnmanaged(event->window);
|
||||
if (window == nullptr) {
|
||||
window = createUnmanaged(event->window);
|
||||
}
|
||||
|
@ -232,7 +231,7 @@ bool Workspace::workspaceEvent(xcb_generic_event_t *e)
|
|||
// since release is scheduled after map notify, this old Unmanaged will get released
|
||||
// before KWIN has chance to remanage it again. so release it right now.
|
||||
if (window->hasScheduledRelease()) {
|
||||
window->release();
|
||||
window->releaseWindow();
|
||||
window = createUnmanaged(event->window);
|
||||
}
|
||||
if (window) {
|
||||
|
@ -317,6 +316,73 @@ bool Workspace::workspaceEvent(xcb_generic_event_t *e)
|
|||
*/
|
||||
bool X11Window::windowEvent(xcb_generic_event_t *e)
|
||||
{
|
||||
if (isUnmanaged()) {
|
||||
NET::Properties dirtyProperties;
|
||||
NET::Properties2 dirtyProperties2;
|
||||
info->event(e, &dirtyProperties, &dirtyProperties2); // pass through the NET stuff
|
||||
if (dirtyProperties2 & NET::WM2Opacity) {
|
||||
if (Compositor::compositing()) {
|
||||
setOpacity(info->opacityF());
|
||||
}
|
||||
}
|
||||
if (dirtyProperties2 & NET::WM2OpaqueRegion) {
|
||||
getWmOpaqueRegion();
|
||||
}
|
||||
if (dirtyProperties2.testFlag(NET::WM2WindowRole)) {
|
||||
Q_EMIT windowRoleChanged();
|
||||
}
|
||||
if (dirtyProperties2.testFlag(NET::WM2WindowClass)) {
|
||||
getResourceClass();
|
||||
}
|
||||
const uint8_t eventType = e->response_type & ~0x80;
|
||||
switch (eventType) {
|
||||
case XCB_DESTROY_NOTIFY:
|
||||
destroyWindow();
|
||||
break;
|
||||
case XCB_UNMAP_NOTIFY: {
|
||||
workspace()->updateFocusMousePosition(Cursors::self()->mouse()->pos()); // may cause leave event
|
||||
|
||||
// unmap notify might have been emitted due to a destroy notify
|
||||
// but unmap notify gets emitted before the destroy notify, nevertheless at this
|
||||
// point the window is already destroyed. This means any XCB request with the window
|
||||
// will cause an error.
|
||||
// To not run into these errors we try to wait for the destroy notify. For this we
|
||||
// generate a round trip to the X server and wait a very short time span before
|
||||
// handling the release.
|
||||
kwinApp()->updateXTime();
|
||||
// using 1 msec to not just move it at the end of the event loop but add an very short
|
||||
// timespan to cover cases like unmap() followed by destroy(). The only other way to
|
||||
// ensure that the window is not destroyed when we do the release handling is to grab
|
||||
// the XServer which we do not want to do for an Unmanaged. The timespan of 1 msec is
|
||||
// short enough to not cause problems in the close window animations.
|
||||
// It's of course still possible that we miss the destroy in which case non-fatal
|
||||
// X errors are reported to the event loop and logged by Qt.
|
||||
m_releaseTimer.start(1);
|
||||
break;
|
||||
}
|
||||
case XCB_CONFIGURE_NOTIFY:
|
||||
configureNotifyEvent(reinterpret_cast<xcb_configure_notify_event_t *>(e));
|
||||
break;
|
||||
case XCB_PROPERTY_NOTIFY:
|
||||
propertyNotifyEvent(reinterpret_cast<xcb_property_notify_event_t *>(e));
|
||||
break;
|
||||
case XCB_CLIENT_MESSAGE:
|
||||
clientMessageEvent(reinterpret_cast<xcb_client_message_event_t *>(e));
|
||||
break;
|
||||
default: {
|
||||
if (eventType == Xcb::Extensions::self()->shapeNotifyEvent()) {
|
||||
detectShape(window());
|
||||
Q_EMIT geometryShapeChanged(frameGeometry());
|
||||
}
|
||||
if (eventType == Xcb::Extensions::self()->damageNotifyEvent()) {
|
||||
damageNotifyEvent();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false; // don't eat events, even our own unmanaged widgets are tracked
|
||||
}
|
||||
|
||||
if (findEventWindow(e) == window()) { // avoid doing stuff on frame or wrapper
|
||||
NET::Properties dirtyProperties;
|
||||
NET::Properties2 dirtyProperties2;
|
||||
|
@ -596,6 +662,27 @@ void X11Window::clientMessageEvent(xcb_client_message_event_t *e)
|
|||
}
|
||||
}
|
||||
|
||||
void X11Window::configureNotifyEvent(xcb_configure_notify_event_t *e)
|
||||
{
|
||||
if (effects) {
|
||||
static_cast<EffectsHandlerImpl *>(effects)->checkInputWindowStacking(); // keep them on top
|
||||
}
|
||||
QRectF newgeom(Xcb::fromXNative(e->x), Xcb::fromXNative(e->y), Xcb::fromXNative(e->width), Xcb::fromXNative(e->height));
|
||||
if (newgeom != m_frameGeometry) {
|
||||
Q_EMIT frameGeometryAboutToChange();
|
||||
|
||||
QRectF old = m_frameGeometry;
|
||||
m_clientGeometry = newgeom;
|
||||
m_frameGeometry = newgeom;
|
||||
m_bufferGeometry = newgeom;
|
||||
checkOutput();
|
||||
Q_EMIT bufferGeometryChanged(old);
|
||||
Q_EMIT clientGeometryChanged(old);
|
||||
Q_EMIT frameGeometryChanged(old);
|
||||
Q_EMIT geometryShapeChanged(old);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles configure requests of the client window
|
||||
*/
|
||||
|
@ -1210,99 +1297,6 @@ void X11Window::keyPressEvent(uint key_code, xcb_timestamp_t time)
|
|||
Window::keyPressEvent(key_code);
|
||||
}
|
||||
|
||||
// ****************************************
|
||||
// Unmanaged
|
||||
// ****************************************
|
||||
|
||||
bool Unmanaged::windowEvent(xcb_generic_event_t *e)
|
||||
{
|
||||
NET::Properties dirtyProperties;
|
||||
NET::Properties2 dirtyProperties2;
|
||||
info->event(e, &dirtyProperties, &dirtyProperties2); // pass through the NET stuff
|
||||
if (dirtyProperties2 & NET::WM2Opacity) {
|
||||
if (Compositor::compositing()) {
|
||||
setOpacity(info->opacityF());
|
||||
}
|
||||
}
|
||||
if (dirtyProperties2 & NET::WM2OpaqueRegion) {
|
||||
getWmOpaqueRegion();
|
||||
}
|
||||
if (dirtyProperties2.testFlag(NET::WM2WindowRole)) {
|
||||
Q_EMIT windowRoleChanged();
|
||||
}
|
||||
if (dirtyProperties2.testFlag(NET::WM2WindowClass)) {
|
||||
getResourceClass();
|
||||
}
|
||||
const uint8_t eventType = e->response_type & ~0x80;
|
||||
switch (eventType) {
|
||||
case XCB_DESTROY_NOTIFY:
|
||||
release(ReleaseReason::Destroyed);
|
||||
break;
|
||||
case XCB_UNMAP_NOTIFY: {
|
||||
workspace()->updateFocusMousePosition(Cursors::self()->mouse()->pos()); // may cause leave event
|
||||
|
||||
// unmap notify might have been emitted due to a destroy notify
|
||||
// but unmap notify gets emitted before the destroy notify, nevertheless at this
|
||||
// point the window is already destroyed. This means any XCB request with the window
|
||||
// will cause an error.
|
||||
// To not run into these errors we try to wait for the destroy notify. For this we
|
||||
// generate a round trip to the X server and wait a very short time span before
|
||||
// handling the release.
|
||||
kwinApp()->updateXTime();
|
||||
// using 1 msec to not just move it at the end of the event loop but add an very short
|
||||
// timespan to cover cases like unmap() followed by destroy(). The only other way to
|
||||
// ensure that the window is not destroyed when we do the release handling is to grab
|
||||
// the XServer which we do not want to do for an Unmanaged. The timespan of 1 msec is
|
||||
// short enough to not cause problems in the close window animations.
|
||||
// It's of course still possible that we miss the destroy in which case non-fatal
|
||||
// X errors are reported to the event loop and logged by Qt.
|
||||
m_releaseTimer.start(1);
|
||||
break;
|
||||
}
|
||||
case XCB_CONFIGURE_NOTIFY:
|
||||
configureNotifyEvent(reinterpret_cast<xcb_configure_notify_event_t *>(e));
|
||||
break;
|
||||
case XCB_PROPERTY_NOTIFY:
|
||||
propertyNotifyEvent(reinterpret_cast<xcb_property_notify_event_t *>(e));
|
||||
break;
|
||||
case XCB_CLIENT_MESSAGE:
|
||||
clientMessageEvent(reinterpret_cast<xcb_client_message_event_t *>(e));
|
||||
break;
|
||||
default: {
|
||||
if (eventType == Xcb::Extensions::self()->shapeNotifyEvent()) {
|
||||
detectShape(window());
|
||||
Q_EMIT geometryShapeChanged(frameGeometry());
|
||||
}
|
||||
if (eventType == Xcb::Extensions::self()->damageNotifyEvent()) {
|
||||
damageNotifyEvent();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false; // don't eat events, even our own unmanaged widgets are tracked
|
||||
}
|
||||
|
||||
void Unmanaged::configureNotifyEvent(xcb_configure_notify_event_t *e)
|
||||
{
|
||||
if (effects) {
|
||||
static_cast<EffectsHandlerImpl *>(effects)->checkInputWindowStacking(); // keep them on top
|
||||
}
|
||||
QRectF newgeom(Xcb::fromXNative(e->x), Xcb::fromXNative(e->y), Xcb::fromXNative(e->width), Xcb::fromXNative(e->height));
|
||||
if (newgeom != m_frameGeometry) {
|
||||
Q_EMIT frameGeometryAboutToChange();
|
||||
|
||||
QRectF old = m_frameGeometry;
|
||||
m_clientGeometry = newgeom;
|
||||
m_frameGeometry = newgeom;
|
||||
m_bufferGeometry = newgeom;
|
||||
checkOutput();
|
||||
Q_EMIT bufferGeometryChanged(old);
|
||||
Q_EMIT clientGeometryChanged(old);
|
||||
Q_EMIT frameGeometryChanged(old);
|
||||
Q_EMIT geometryShapeChanged(old);
|
||||
}
|
||||
}
|
||||
|
||||
// ****************************************
|
||||
// Window
|
||||
// ****************************************
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
#include "internalwindow.h"
|
||||
#include "popup_input_filter.h"
|
||||
#include "screenedge.h"
|
||||
#include "unmanaged.h"
|
||||
#include "virtualdesktops.h"
|
||||
#include "wayland/display.h"
|
||||
#include "wayland/inputmethod_v1_interface.h"
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
#include "killwindow.h"
|
||||
#include "main.h"
|
||||
#include "osd.h"
|
||||
#include "unmanaged.h"
|
||||
#include "window.h"
|
||||
|
||||
#include <KLocalizedString>
|
||||
|
|
|
@ -73,7 +73,6 @@
|
|||
#include "rules.h"
|
||||
#include "screenedge.h"
|
||||
#include "tabbox/tabbox.h"
|
||||
#include "unmanaged.h"
|
||||
#include "utils/common.h"
|
||||
#include "virtualdesktops.h"
|
||||
#include "wayland_server.h"
|
||||
|
@ -162,7 +161,7 @@ void Workspace::propagateWindows(bool propagate_new_windows)
|
|||
|
||||
for (int i = stacking_order.size() - 1; i >= 0; --i) {
|
||||
X11Window *window = qobject_cast<X11Window *>(stacking_order.at(i));
|
||||
if (!window || window->hiddenPreview()) {
|
||||
if (!window || window->isUnmanaged() || window->hiddenPreview()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -179,7 +178,7 @@ void Workspace::propagateWindows(bool propagate_new_windows)
|
|||
// these windows that should be unmapped to interfere with other windows
|
||||
for (int i = stacking_order.size() - 1; i >= 0; --i) {
|
||||
X11Window *window = qobject_cast<X11Window *>(stacking_order.at(i));
|
||||
if (!window || !window->hiddenPreview()) {
|
||||
if (!window || window->isUnmanaged() || !window->hiddenPreview()) {
|
||||
continue;
|
||||
}
|
||||
newWindowStack << window->frameId();
|
||||
|
@ -197,7 +196,7 @@ void Workspace::propagateWindows(bool propagate_new_windows)
|
|||
}
|
||||
for (Window *window : std::as_const(m_windows)) {
|
||||
X11Window *x11Window = qobject_cast<X11Window *>(window);
|
||||
if (x11Window) {
|
||||
if (x11Window && !x11Window->isUnmanaged()) {
|
||||
cl.push_back(x11Window->window());
|
||||
}
|
||||
}
|
||||
|
@ -207,7 +206,7 @@ void Workspace::propagateWindows(bool propagate_new_windows)
|
|||
cl.clear();
|
||||
for (auto it = stacking_order.constBegin(); it != stacking_order.constEnd(); ++it) {
|
||||
X11Window *window = qobject_cast<X11Window *>(*it);
|
||||
if (window) {
|
||||
if (window && !window->isUnmanaged()) {
|
||||
cl.push_back(window->window());
|
||||
}
|
||||
}
|
||||
|
@ -467,7 +466,7 @@ void Workspace::restoreSessionStackingOrder(X11Window *window)
|
|||
unconstrained_stacking_order.removeAll(window);
|
||||
for (auto it = unconstrained_stacking_order.begin(); it != unconstrained_stacking_order.end(); ++it) {
|
||||
X11Window *current = qobject_cast<X11Window *>(*it);
|
||||
if (!current) {
|
||||
if (!current || current->isUnmanaged()) {
|
||||
continue;
|
||||
}
|
||||
if (current->sessionStackingOrder() > window->sessionStackingOrder()) {
|
||||
|
|
|
@ -66,7 +66,6 @@
|
|||
#include "scene/surfaceitem.h"
|
||||
#include "scene/windowitem.h"
|
||||
#include "shadow.h"
|
||||
#include "unmanaged.h"
|
||||
#include "wayland/seat_interface.h"
|
||||
#include "wayland/surface_interface.h"
|
||||
#include "wayland_server.h"
|
||||
|
|
|
@ -91,7 +91,7 @@ void SessionManager::storeSession(const QString &sessionName, SMSavePhase phase)
|
|||
const QList<Window *> windows = workspace()->windows();
|
||||
for (auto it = windows.begin(); it != windows.end(); ++it) {
|
||||
X11Window *c = qobject_cast<X11Window *>(*it);
|
||||
if (!c) {
|
||||
if (!c || c->isUnmanaged()) {
|
||||
continue;
|
||||
}
|
||||
if (c->windowType() > NET::Splash) {
|
||||
|
@ -180,7 +180,7 @@ void SessionManager::storeSubSession(const QString &name, QSet<QByteArray> sessi
|
|||
|
||||
for (auto it = windows.begin(); it != windows.end(); ++it) {
|
||||
X11Window *c = qobject_cast<X11Window *>(*it);
|
||||
if (!c) {
|
||||
if (!c || c->isUnmanaged()) {
|
||||
continue;
|
||||
}
|
||||
if (c->windowType() > NET::Splash) {
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
#include "keyboard_input.h"
|
||||
#include "pointer_input.h"
|
||||
#include "screenedge.h"
|
||||
#include "unmanaged.h"
|
||||
#include "utils/xcbutils.h"
|
||||
#include "virtualdesktops.h"
|
||||
#include "workspace.h"
|
||||
|
|
|
@ -1,226 +0,0 @@
|
|||
/*
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
SPDX-FileCopyrightText: 2006 Lubos Lunak <l.lunak@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "unmanaged.h"
|
||||
|
||||
#include "effects.h"
|
||||
#include "scene/surfaceitem_x11.h"
|
||||
#include "scene/windowitem.h"
|
||||
#include "utils/common.h"
|
||||
#include "wayland/surface_interface.h"
|
||||
#include "workspace.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QTimer>
|
||||
#include <QWindow>
|
||||
|
||||
#include <xcb/shape.h>
|
||||
|
||||
using namespace KWaylandServer;
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
// window types that are supported as unmanaged (mainly for compositing)
|
||||
const NET::WindowTypes SUPPORTED_UNMANAGED_WINDOW_TYPES_MASK = NET::NormalMask
|
||||
| NET::DesktopMask
|
||||
| NET::DockMask
|
||||
| NET::ToolbarMask
|
||||
| NET::MenuMask
|
||||
| NET::DialogMask
|
||||
/*| NET::OverrideMask*/
|
||||
| NET::TopMenuMask
|
||||
| NET::UtilityMask
|
||||
| NET::SplashMask
|
||||
| NET::DropdownMenuMask
|
||||
| NET::PopupMenuMask
|
||||
| NET::TooltipMask
|
||||
| NET::NotificationMask
|
||||
| NET::ComboBoxMask
|
||||
| NET::DNDIconMask
|
||||
| NET::OnScreenDisplayMask
|
||||
| NET::CriticalNotificationMask;
|
||||
|
||||
Unmanaged::Unmanaged()
|
||||
: Window()
|
||||
{
|
||||
m_releaseTimer.setSingleShot(true);
|
||||
connect(&m_releaseTimer, &QTimer::timeout, this, [this]() {
|
||||
release();
|
||||
});
|
||||
|
||||
switch (kwinApp()->operationMode()) {
|
||||
case Application::OperationModeXwayland:
|
||||
// The wayland surface is associated with the override-redirect window asynchronously.
|
||||
connect(this, &Window::surfaceChanged, this, &Unmanaged::associate);
|
||||
break;
|
||||
case Application::OperationModeX11:
|
||||
// We have no way knowing whether the override-redirect window can be painted. Mark it
|
||||
// as ready for painting after synthetic 50ms delay.
|
||||
QTimer::singleShot(50, this, &Unmanaged::initialize);
|
||||
break;
|
||||
case Application::OperationModeWaylandOnly:
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
Unmanaged::~Unmanaged()
|
||||
{
|
||||
}
|
||||
|
||||
std::unique_ptr<WindowItem> Unmanaged::createItem(Scene *scene)
|
||||
{
|
||||
return std::make_unique<WindowItemX11>(this, scene);
|
||||
}
|
||||
|
||||
void Unmanaged::associate()
|
||||
{
|
||||
if (surface()->isMapped()) {
|
||||
initialize();
|
||||
} else {
|
||||
// Queued connection because we want to mark the window ready for painting after
|
||||
// the associated surface item has processed the new surface state.
|
||||
connect(surface(), &SurfaceInterface::mapped, this, &Unmanaged::initialize, Qt::QueuedConnection);
|
||||
}
|
||||
}
|
||||
|
||||
void Unmanaged::initialize()
|
||||
{
|
||||
setReadyForPainting();
|
||||
}
|
||||
|
||||
bool Unmanaged::track(xcb_window_t w)
|
||||
{
|
||||
XServerGrabber xserverGrabber;
|
||||
Xcb::WindowAttributes attr(w);
|
||||
Xcb::WindowGeometry geo(w);
|
||||
if (attr.isNull() || attr->map_state != XCB_MAP_STATE_VIEWABLE) {
|
||||
return false;
|
||||
}
|
||||
if (attr->_class == XCB_WINDOW_CLASS_INPUT_ONLY) {
|
||||
return false;
|
||||
}
|
||||
if (geo.isNull()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
setWindowHandles(w); // the window is also the frame
|
||||
Xcb::selectInput(w, attr->your_event_mask | XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_PROPERTY_CHANGE);
|
||||
m_bufferGeometry = geo.rect();
|
||||
m_frameGeometry = geo.rect();
|
||||
m_clientGeometry = geo.rect();
|
||||
checkOutput();
|
||||
m_visual = attr->visual;
|
||||
bit_depth = geo->depth;
|
||||
info = new NETWinInfo(kwinApp()->x11Connection(), w, kwinApp()->x11RootWindow(),
|
||||
NET::WMWindowType | NET::WMPid,
|
||||
NET::WM2Opacity | NET::WM2WindowRole | NET::WM2WindowClass | NET::WM2OpaqueRegion);
|
||||
setOpacity(info->opacityF());
|
||||
getResourceClass();
|
||||
getWmClientLeader();
|
||||
getWmClientMachine();
|
||||
if (Xcb::Extensions::self()->isShapeAvailable()) {
|
||||
xcb_shape_select_input(kwinApp()->x11Connection(), w, true);
|
||||
}
|
||||
detectShape(w);
|
||||
getWmOpaqueRegion();
|
||||
getSkipCloseAnimation();
|
||||
setupCompositing();
|
||||
if (QWindow *internalWindow = findInternalWindow()) {
|
||||
m_outline = internalWindow->property("__kwin_outline").toBool();
|
||||
}
|
||||
if (effects) {
|
||||
static_cast<EffectsHandlerImpl *>(effects)->checkInputWindowStacking();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Unmanaged::release(ReleaseReason releaseReason)
|
||||
{
|
||||
if (SurfaceItemX11 *item = qobject_cast<SurfaceItemX11 *>(surfaceItem())) {
|
||||
if (releaseReason == ReleaseReason::Destroyed) {
|
||||
item->forgetDamage();
|
||||
} else {
|
||||
item->destroyDamage();
|
||||
}
|
||||
}
|
||||
markAsDeleted();
|
||||
m_releaseTimer.stop();
|
||||
Q_EMIT closed();
|
||||
if (releaseReason != ReleaseReason::Destroyed && !findInternalWindow()) { // don't affect our own windows
|
||||
if (Xcb::Extensions::self()->isShapeAvailable()) {
|
||||
xcb_shape_select_input(kwinApp()->x11Connection(), window(), false);
|
||||
}
|
||||
Xcb::selectInput(window(), XCB_EVENT_MASK_NO_EVENT);
|
||||
}
|
||||
workspace()->removeUnmanaged(this);
|
||||
unref();
|
||||
}
|
||||
|
||||
void Unmanaged::deleteUnmanaged(Unmanaged *c)
|
||||
{
|
||||
delete c;
|
||||
}
|
||||
|
||||
bool Unmanaged::hasScheduledRelease() const
|
||||
{
|
||||
return m_releaseTimer.isActive();
|
||||
}
|
||||
|
||||
QStringList Unmanaged::activities() const
|
||||
{
|
||||
return QStringList();
|
||||
}
|
||||
|
||||
NET::WindowType Unmanaged::windowType(bool direct) const
|
||||
{
|
||||
return info->windowType(SUPPORTED_UNMANAGED_WINDOW_TYPES_MASK);
|
||||
}
|
||||
|
||||
bool Unmanaged::isOutline() const
|
||||
{
|
||||
return m_outline;
|
||||
}
|
||||
|
||||
bool Unmanaged::isUnmanaged() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
QWindow *Unmanaged::findInternalWindow() const
|
||||
{
|
||||
const QWindowList windows = kwinApp()->topLevelWindows();
|
||||
for (QWindow *w : windows) {
|
||||
if (w->handle() && w->winId() == window()) {
|
||||
return w;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Unmanaged::checkOutput()
|
||||
{
|
||||
setOutput(workspace()->outputAt(frameGeometry().center()));
|
||||
}
|
||||
|
||||
void Unmanaged::damageNotifyEvent()
|
||||
{
|
||||
Q_ASSERT(kwinApp()->operationMode() == Application::OperationModeX11);
|
||||
SurfaceItemX11 *item = static_cast<SurfaceItemX11 *>(surfaceItem());
|
||||
if (item) {
|
||||
item->processDamage();
|
||||
}
|
||||
}
|
||||
|
||||
void Unmanaged::killWindow()
|
||||
{
|
||||
xcb_kill_client(kwinApp()->x11Connection(), window());
|
||||
}
|
||||
|
||||
} // namespace
|
|
@ -1,79 +0,0 @@
|
|||
/*
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
SPDX-FileCopyrightText: 2006 Lubos Lunak <l.lunak@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <netwm.h>
|
||||
|
||||
#include "window.h"
|
||||
|
||||
#include <QTimer>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
class KWIN_EXPORT Unmanaged : public Window
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit Unmanaged();
|
||||
bool windowEvent(xcb_generic_event_t *e);
|
||||
bool track(xcb_window_t w);
|
||||
bool hasScheduledRelease() const;
|
||||
static void deleteUnmanaged(Unmanaged *c);
|
||||
QStringList activities() const override;
|
||||
NET::WindowType windowType(bool direct = false) const override;
|
||||
bool isOutline() const override;
|
||||
bool isUnmanaged() const override;
|
||||
|
||||
QString captionNormal() const override { return {}; }
|
||||
QString captionSuffix() const override { return {}; }
|
||||
bool isCloseable() const override { return false; }
|
||||
bool isShown() const override { return false; }
|
||||
bool isHiddenInternal() const override { return false; }
|
||||
void hideClient() override { /* nothing to do */ }
|
||||
void showClient() override { /* nothing to do */ }
|
||||
Window *findModal(bool /*allow_itself*/) override { return nullptr; }
|
||||
bool isResizable() const override { return false; }
|
||||
bool isMovable() const override { return false; }
|
||||
bool isMovableAcrossScreens() const override { return false; }
|
||||
bool takeFocus() override { return false; }
|
||||
bool wantsInput() const override { return false; }
|
||||
void killWindow() override;
|
||||
void destroyWindow() override { /* nothing to do */ }
|
||||
void closeWindow() override { /* nothing to do */ }
|
||||
bool acceptsFocus() const override { return false; }
|
||||
bool belongsToSameApplication(const Window *other, SameApplicationChecks /*checks*/) const override { return other == this; }
|
||||
void moveResizeInternal(const QRectF & /*rect*/, KWin::Window::MoveResizeMode /*mode*/) override
|
||||
{ /* nothing to do */
|
||||
}
|
||||
void updateCaption() override { /* nothing to do */ }
|
||||
QRectF resizeWithChecks(const QRectF &geometry, const QSizeF &) override
|
||||
{ /* nothing to do */
|
||||
return geometry;
|
||||
}
|
||||
std::unique_ptr<WindowItem> createItem(Scene *scene) override;
|
||||
|
||||
public Q_SLOTS:
|
||||
void release(ReleaseReason releaseReason = ReleaseReason::Release);
|
||||
|
||||
private:
|
||||
~Unmanaged() override; // use release()
|
||||
// handlers for X11 events
|
||||
void configureNotifyEvent(xcb_configure_notify_event_t *e);
|
||||
void damageNotifyEvent();
|
||||
QWindow *findInternalWindow() const;
|
||||
void checkOutput();
|
||||
void associate();
|
||||
void initialize();
|
||||
bool m_outline = false;
|
||||
QTimer m_releaseTimer;
|
||||
};
|
||||
|
||||
} // namespace
|
|
@ -20,7 +20,6 @@
|
|||
#include "layershellv1integration.h"
|
||||
#include "main.h"
|
||||
#include "scene/workspacescene.h"
|
||||
#include "unmanaged.h"
|
||||
#include "utils/serviceutils.h"
|
||||
#include "virtualdesktops.h"
|
||||
#include "wayland/appmenu_interface.h"
|
||||
|
@ -357,7 +356,7 @@ bool WaylandServer::init(InitializationFlags flags)
|
|||
return;
|
||||
}
|
||||
|
||||
Unmanaged *unmanaged = ws->findUnmanaged([surface](const Unmanaged *unmanaged) {
|
||||
X11Window *unmanaged = ws->findUnmanaged([surface](const X11Window *unmanaged) {
|
||||
return unmanaged->pendingSurfaceId() == surface->id();
|
||||
});
|
||||
if (unmanaged) {
|
||||
|
@ -378,7 +377,7 @@ bool WaylandServer::init(InitializationFlags flags)
|
|||
return;
|
||||
}
|
||||
|
||||
Unmanaged *unmanaged = workspace()->findUnmanaged([&surface](const Unmanaged *window) {
|
||||
X11Window *unmanaged = workspace()->findUnmanaged([&surface](const X11Window *window) {
|
||||
return window->surfaceSerial() == surface->serial();
|
||||
});
|
||||
if (unmanaged) {
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
*/
|
||||
#include "window_property_notify_x11_filter.h"
|
||||
#include "effects.h"
|
||||
#include "unmanaged.h"
|
||||
#include "workspace.h"
|
||||
#include "x11window.h"
|
||||
|
||||
|
|
|
@ -52,7 +52,6 @@
|
|||
#include "placeholderoutput.h"
|
||||
#include "placementtracker.h"
|
||||
#include "tiles/tilemanager.h"
|
||||
#include "unmanaged.h"
|
||||
#include "useractions.h"
|
||||
#include "utils/xcbutils.h"
|
||||
#include "virtualdesktops.h"
|
||||
|
@ -440,12 +439,8 @@ void Workspace::cleanupX11()
|
|||
for (Window *window : stack) {
|
||||
if (auto x11 = qobject_cast<X11Window *>(window)) {
|
||||
x11->releaseWindow(true);
|
||||
} else if (auto unmanaged = qobject_cast<Unmanaged *>(window)) {
|
||||
unmanaged->release(ReleaseReason::KWinShutsDown);
|
||||
} else {
|
||||
continue;
|
||||
removeFromStack(window);
|
||||
}
|
||||
removeFromStack(window);
|
||||
}
|
||||
|
||||
manual_overlays.clear();
|
||||
|
@ -677,16 +672,16 @@ X11Window *Workspace::createX11Window(xcb_window_t windowId, bool is_mapped)
|
|||
return window;
|
||||
}
|
||||
|
||||
Unmanaged *Workspace::createUnmanaged(xcb_window_t windowId)
|
||||
X11Window *Workspace::createUnmanaged(xcb_window_t windowId)
|
||||
{
|
||||
if (X11Compositor *compositor = X11Compositor::self()) {
|
||||
if (compositor->checkForOverlayWindow(windowId)) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
Unmanaged *window = new Unmanaged();
|
||||
X11Window *window = new X11Window();
|
||||
if (!window->track(windowId)) {
|
||||
Unmanaged::deleteUnmanaged(window);
|
||||
X11Window::deleteClient(window);
|
||||
return nullptr;
|
||||
}
|
||||
addUnmanaged(window);
|
||||
|
@ -727,7 +722,7 @@ void Workspace::addX11Window(X11Window *window)
|
|||
updateTabbox();
|
||||
}
|
||||
|
||||
void Workspace::addUnmanaged(Unmanaged *window)
|
||||
void Workspace::addUnmanaged(X11Window *window)
|
||||
{
|
||||
m_windows.append(window);
|
||||
addToStack(window);
|
||||
|
@ -748,7 +743,7 @@ void Workspace::removeX11Window(X11Window *window)
|
|||
removeWindow(window);
|
||||
}
|
||||
|
||||
void Workspace::removeUnmanaged(Unmanaged *window)
|
||||
void Workspace::removeUnmanaged(X11Window *window)
|
||||
{
|
||||
Q_ASSERT(m_windows.contains(window));
|
||||
m_windows.removeOne(window);
|
||||
|
@ -1894,7 +1889,7 @@ void Workspace::forEachClient(std::function<void(X11Window *)> func)
|
|||
{
|
||||
for (Window *window : std::as_const(m_windows)) {
|
||||
X11Window *x11Window = qobject_cast<X11Window *>(window);
|
||||
if (x11Window) {
|
||||
if (x11Window && !x11Window->isUnmanaged()) {
|
||||
func(x11Window);
|
||||
}
|
||||
}
|
||||
|
@ -1904,27 +1899,27 @@ X11Window *Workspace::findClient(std::function<bool(const X11Window *)> func) co
|
|||
{
|
||||
for (Window *window : std::as_const(m_windows)) {
|
||||
X11Window *x11Window = qobject_cast<X11Window *>(window);
|
||||
if (x11Window && func(x11Window)) {
|
||||
if (x11Window && !x11Window->isUnmanaged() && func(x11Window)) {
|
||||
return x11Window;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Unmanaged *Workspace::findUnmanaged(std::function<bool(const Unmanaged *)> func) const
|
||||
X11Window *Workspace::findUnmanaged(std::function<bool(const X11Window *)> func) const
|
||||
{
|
||||
for (Window *window : m_windows) {
|
||||
Unmanaged *unmanaged = qobject_cast<Unmanaged *>(window);
|
||||
if (unmanaged && func(unmanaged)) {
|
||||
return unmanaged;
|
||||
X11Window *x11Window = qobject_cast<X11Window *>(window);
|
||||
if (x11Window && x11Window->isUnmanaged() && func(x11Window)) {
|
||||
return x11Window;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Unmanaged *Workspace::findUnmanaged(xcb_window_t w) const
|
||||
X11Window *Workspace::findUnmanaged(xcb_window_t w) const
|
||||
{
|
||||
return findUnmanaged([w](const Unmanaged *u) {
|
||||
return findUnmanaged([w](const X11Window *u) {
|
||||
return u->window() == w;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -58,7 +58,6 @@ class Group;
|
|||
class InternalWindow;
|
||||
class KillWindow;
|
||||
class ShortcutDialog;
|
||||
class Unmanaged;
|
||||
class UserActionsMenu;
|
||||
class VirtualDesktop;
|
||||
class X11Window;
|
||||
|
@ -135,14 +134,14 @@ public:
|
|||
*/
|
||||
X11Window *findClient(Predicate predicate, xcb_window_t w) const;
|
||||
void forEachClient(std::function<void(X11Window *)> func);
|
||||
Unmanaged *findUnmanaged(std::function<bool(const Unmanaged *)> func) const;
|
||||
X11Window *findUnmanaged(std::function<bool(const X11Window *)> func) const;
|
||||
/**
|
||||
* @brief Finds the Unmanaged with the given window id.
|
||||
*
|
||||
* @param w The window id to search for
|
||||
* @return KWin::Unmanaged* Found Unmanaged or @c null if there is no Unmanaged with given Id.
|
||||
*/
|
||||
Unmanaged *findUnmanaged(xcb_window_t w) const;
|
||||
X11Window *findUnmanaged(xcb_window_t w) const;
|
||||
|
||||
Window *findWindow(const QUuid &internalId) const;
|
||||
Window *findWindow(std::function<bool(const Window *)> func) const;
|
||||
|
@ -353,7 +352,7 @@ public:
|
|||
Group *findClientLeaderGroup(const X11Window *c) const;
|
||||
int unconstainedStackingOrderIndex(const X11Window *c) const;
|
||||
|
||||
void removeUnmanaged(Unmanaged *); // Only called from Unmanaged::release()
|
||||
void removeUnmanaged(X11Window *);
|
||||
void removeDeleted(Window *);
|
||||
void addDeleted(Window *);
|
||||
|
||||
|
@ -592,8 +591,8 @@ private:
|
|||
X11Window *createX11Window(xcb_window_t windowId, bool is_mapped);
|
||||
void addX11Window(X11Window *c);
|
||||
void setupWindowConnections(Window *window);
|
||||
Unmanaged *createUnmanaged(xcb_window_t windowId);
|
||||
void addUnmanaged(Unmanaged *c);
|
||||
X11Window *createUnmanaged(xcb_window_t windowId);
|
||||
void addUnmanaged(X11Window *c);
|
||||
|
||||
void addWaylandWindow(Window *window);
|
||||
void removeWaylandWindow(Window *window);
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "screenedge.h"
|
||||
#include "shadow.h"
|
||||
#include "virtualdesktops.h"
|
||||
#include "wayland/surface_interface.h"
|
||||
#include "wayland_server.h"
|
||||
#include "workspace.h"
|
||||
#include <KDecoration2/DecoratedClient>
|
||||
|
@ -143,6 +144,26 @@ const NET::WindowTypes SUPPORTED_MANAGED_WINDOW_TYPES_MASK = NET::NormalMask
|
|||
| NET::CriticalNotificationMask
|
||||
| NET::AppletPopupMask;
|
||||
|
||||
// window types that are supported as unmanaged (mainly for compositing)
|
||||
const NET::WindowTypes SUPPORTED_UNMANAGED_WINDOW_TYPES_MASK = NET::NormalMask
|
||||
| NET::DesktopMask
|
||||
| NET::DockMask
|
||||
| NET::ToolbarMask
|
||||
| NET::MenuMask
|
||||
| NET::DialogMask
|
||||
/*| NET::OverrideMask*/
|
||||
| NET::TopMenuMask
|
||||
| NET::UtilityMask
|
||||
| NET::SplashMask
|
||||
| NET::DropdownMenuMask
|
||||
| NET::PopupMenuMask
|
||||
| NET::TooltipMask
|
||||
| NET::NotificationMask
|
||||
| NET::ComboBoxMask
|
||||
| NET::DNDIconMask
|
||||
| NET::OnScreenDisplayMask
|
||||
| NET::CriticalNotificationMask;
|
||||
|
||||
X11DecorationRenderer::X11DecorationRenderer(Decoration::DecoratedClientImpl *client)
|
||||
: DecorationRenderer(client)
|
||||
, m_scheduleTimer(new QTimer(this))
|
||||
|
@ -319,6 +340,11 @@ X11Window::X11Window()
|
|||
});
|
||||
}
|
||||
|
||||
m_releaseTimer.setSingleShot(true);
|
||||
connect(&m_releaseTimer, &QTimer::timeout, this, [this]() {
|
||||
releaseWindow();
|
||||
});
|
||||
|
||||
// SELI TODO: Initialize xsizehints??
|
||||
}
|
||||
|
||||
|
@ -335,9 +361,6 @@ X11Window::~X11Window()
|
|||
xcb_sync_destroy_alarm(kwinApp()->x11Connection(), m_syncRequest.alarm);
|
||||
}
|
||||
Q_ASSERT(!isInteractiveMoveResize());
|
||||
Q_ASSERT(m_client == XCB_WINDOW_NONE);
|
||||
Q_ASSERT(m_wrapper == XCB_WINDOW_NONE);
|
||||
Q_ASSERT(m_frame == XCB_WINDOW_NONE);
|
||||
Q_ASSERT(!check_active_modal);
|
||||
}
|
||||
|
||||
|
@ -352,6 +375,11 @@ void X11Window::deleteClient(X11Window *c)
|
|||
delete c;
|
||||
}
|
||||
|
||||
bool X11Window::hasScheduledRelease() const
|
||||
{
|
||||
return m_releaseTimer.isActive();
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases the window. The client has done its job and the window is still existing.
|
||||
*/
|
||||
|
@ -361,61 +389,75 @@ void X11Window::releaseWindow(bool on_shutdown)
|
|||
if (SurfaceItemX11 *item = qobject_cast<SurfaceItemX11 *>(surfaceItem())) {
|
||||
item->destroyDamage();
|
||||
}
|
||||
|
||||
markAsDeleted();
|
||||
cleanTabBox();
|
||||
if (isInteractiveMoveResize()) {
|
||||
Q_EMIT interactiveMoveResizeFinished();
|
||||
}
|
||||
Q_EMIT closed();
|
||||
workspace()->rulebook()->discardUsed(this, true); // Remove ForceTemporarily rules
|
||||
StackingUpdatesBlocker blocker(workspace());
|
||||
if (isInteractiveMoveResize()) {
|
||||
leaveInteractiveMoveResize();
|
||||
|
||||
if (isUnmanaged()) {
|
||||
m_releaseTimer.stop();
|
||||
if (!findInternalWindow()) { // don't affect our own windows
|
||||
if (Xcb::Extensions::self()->isShapeAvailable()) {
|
||||
xcb_shape_select_input(kwinApp()->x11Connection(), window(), false);
|
||||
}
|
||||
Xcb::selectInput(window(), XCB_EVENT_MASK_NO_EVENT);
|
||||
}
|
||||
workspace()->removeUnmanaged(this);
|
||||
} else {
|
||||
cleanTabBox();
|
||||
if (isInteractiveMoveResize()) {
|
||||
Q_EMIT interactiveMoveResizeFinished();
|
||||
}
|
||||
workspace()->rulebook()->discardUsed(this, true); // Remove ForceTemporarily rules
|
||||
StackingUpdatesBlocker blocker(workspace());
|
||||
if (isInteractiveMoveResize()) {
|
||||
leaveInteractiveMoveResize();
|
||||
}
|
||||
finishWindowRules();
|
||||
blockGeometryUpdates();
|
||||
// Grab X during the release to make removing of properties, setting to withdrawn state
|
||||
// and repareting to root an atomic operation (https://lists.kde.org/?l=kde-devel&m=116448102901184&w=2)
|
||||
grabXServer();
|
||||
exportMappingState(XCB_ICCCM_WM_STATE_WITHDRAWN);
|
||||
setModal(false); // Otherwise its mainwindow wouldn't get focus
|
||||
hidden = true; // So that it's not considered visible anymore (can't use hideClient(), it would set flags)
|
||||
if (!on_shutdown) {
|
||||
workspace()->windowHidden(this);
|
||||
}
|
||||
m_frame.unmap(); // Destroying decoration would cause ugly visual effect
|
||||
cleanGrouping();
|
||||
workspace()->removeX11Window(this);
|
||||
if (!on_shutdown) {
|
||||
// Only when the window is being unmapped, not when closing down KWin (NETWM sections 5.5,5.7)
|
||||
info->setDesktop(0);
|
||||
info->setState(NET::States(), info->state()); // Reset all state flags
|
||||
}
|
||||
if (WinInfo *cinfo = dynamic_cast<WinInfo *>(info)) {
|
||||
cinfo->disable();
|
||||
}
|
||||
xcb_connection_t *c = kwinApp()->x11Connection();
|
||||
m_client.deleteProperty(atoms->kde_net_wm_user_creation_time);
|
||||
m_client.deleteProperty(atoms->net_frame_extents);
|
||||
m_client.deleteProperty(atoms->kde_net_wm_frame_strut);
|
||||
const QPointF grav = calculateGravitation(true);
|
||||
m_client.reparent(kwinApp()->x11RootWindow(), grav.x(), grav.y());
|
||||
xcb_change_save_set(c, XCB_SET_MODE_DELETE, m_client);
|
||||
m_client.selectInput(XCB_EVENT_MASK_NO_EVENT);
|
||||
if (on_shutdown) {
|
||||
// Map the window, so it can be found after another WM is started
|
||||
m_client.map();
|
||||
// TODO: Preserve minimized, shaded etc. state?
|
||||
} else { // Make sure it's not mapped if the app unmapped it (#65279). The app
|
||||
// may do map+unmap before we initially map the window by calling rawShow() from manage().
|
||||
m_client.unmap();
|
||||
}
|
||||
m_client.reset();
|
||||
m_wrapper.reset();
|
||||
m_frame.reset();
|
||||
unblockGeometryUpdates(); // Don't use GeometryUpdatesBlocker, it would now set the geometry
|
||||
ungrabXServer();
|
||||
}
|
||||
finishWindowRules();
|
||||
blockGeometryUpdates();
|
||||
// Grab X during the release to make removing of properties, setting to withdrawn state
|
||||
// and repareting to root an atomic operation (https://lists.kde.org/?l=kde-devel&m=116448102901184&w=2)
|
||||
grabXServer();
|
||||
exportMappingState(XCB_ICCCM_WM_STATE_WITHDRAWN);
|
||||
setModal(false); // Otherwise its mainwindow wouldn't get focus
|
||||
hidden = true; // So that it's not considered visible anymore (can't use hideClient(), it would set flags)
|
||||
if (!on_shutdown) {
|
||||
workspace()->windowHidden(this);
|
||||
}
|
||||
m_frame.unmap(); // Destroying decoration would cause ugly visual effect
|
||||
cleanGrouping();
|
||||
workspace()->removeX11Window(this);
|
||||
if (!on_shutdown) {
|
||||
// Only when the window is being unmapped, not when closing down KWin (NETWM sections 5.5,5.7)
|
||||
info->setDesktop(0);
|
||||
info->setState(NET::States(), info->state()); // Reset all state flags
|
||||
}
|
||||
if (WinInfo *cinfo = dynamic_cast<WinInfo *>(info)) {
|
||||
cinfo->disable();
|
||||
}
|
||||
xcb_connection_t *c = kwinApp()->x11Connection();
|
||||
m_client.deleteProperty(atoms->kde_net_wm_user_creation_time);
|
||||
m_client.deleteProperty(atoms->net_frame_extents);
|
||||
m_client.deleteProperty(atoms->kde_net_wm_frame_strut);
|
||||
const QPointF grav = calculateGravitation(true);
|
||||
m_client.reparent(kwinApp()->x11RootWindow(), grav.x(), grav.y());
|
||||
xcb_change_save_set(c, XCB_SET_MODE_DELETE, m_client);
|
||||
m_client.selectInput(XCB_EVENT_MASK_NO_EVENT);
|
||||
if (on_shutdown) {
|
||||
// Map the window, so it can be found after another WM is started
|
||||
m_client.map();
|
||||
// TODO: Preserve minimized, shaded etc. state?
|
||||
} else { // Make sure it's not mapped if the app unmapped it (#65279). The app
|
||||
// may do map+unmap before we initially map the window by calling rawShow() from manage().
|
||||
m_client.unmap();
|
||||
}
|
||||
m_client.reset();
|
||||
m_wrapper.reset();
|
||||
m_frame.reset();
|
||||
unblockGeometryUpdates(); // Don't use GeometryUpdatesBlocker, it would now set the geometry
|
||||
|
||||
unref();
|
||||
ungrabXServer();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -428,34 +470,113 @@ void X11Window::destroyWindow()
|
|||
if (SurfaceItemX11 *item = qobject_cast<SurfaceItemX11 *>(surfaceItem())) {
|
||||
item->forgetDamage();
|
||||
}
|
||||
|
||||
markAsDeleted();
|
||||
cleanTabBox();
|
||||
if (isInteractiveMoveResize()) {
|
||||
Q_EMIT interactiveMoveResizeFinished();
|
||||
}
|
||||
Q_EMIT closed();
|
||||
workspace()->rulebook()->discardUsed(this, true); // Remove ForceTemporarily rules
|
||||
StackingUpdatesBlocker blocker(workspace());
|
||||
if (isInteractiveMoveResize()) {
|
||||
leaveInteractiveMoveResize();
|
||||
|
||||
if (isUnmanaged()) {
|
||||
m_releaseTimer.stop();
|
||||
workspace()->removeUnmanaged(this);
|
||||
} else {
|
||||
cleanTabBox();
|
||||
if (isInteractiveMoveResize()) {
|
||||
Q_EMIT interactiveMoveResizeFinished();
|
||||
}
|
||||
workspace()->rulebook()->discardUsed(this, true); // Remove ForceTemporarily rules
|
||||
StackingUpdatesBlocker blocker(workspace());
|
||||
if (isInteractiveMoveResize()) {
|
||||
leaveInteractiveMoveResize();
|
||||
}
|
||||
finishWindowRules();
|
||||
blockGeometryUpdates();
|
||||
setModal(false);
|
||||
hidden = true; // So that it's not considered visible anymore
|
||||
workspace()->windowHidden(this);
|
||||
cleanGrouping();
|
||||
workspace()->removeX11Window(this);
|
||||
if (WinInfo *cinfo = dynamic_cast<WinInfo *>(info)) {
|
||||
cinfo->disable();
|
||||
}
|
||||
m_client.reset(); // invalidate
|
||||
m_wrapper.reset();
|
||||
m_frame.reset();
|
||||
unblockGeometryUpdates(); // Don't use GeometryUpdatesBlocker, it would now set the geometry
|
||||
}
|
||||
finishWindowRules();
|
||||
blockGeometryUpdates();
|
||||
setModal(false);
|
||||
hidden = true; // So that it's not considered visible anymore
|
||||
workspace()->windowHidden(this);
|
||||
cleanGrouping();
|
||||
workspace()->removeX11Window(this);
|
||||
if (WinInfo *cinfo = dynamic_cast<WinInfo *>(info)) {
|
||||
cinfo->disable();
|
||||
}
|
||||
m_client.reset(); // invalidate
|
||||
m_wrapper.reset();
|
||||
m_frame.reset();
|
||||
unblockGeometryUpdates(); // Don't use GeometryUpdatesBlocker, it would now set the geometry
|
||||
|
||||
unref();
|
||||
}
|
||||
|
||||
bool X11Window::track(xcb_window_t w)
|
||||
{
|
||||
XServerGrabber xserverGrabber;
|
||||
Xcb::WindowAttributes attr(w);
|
||||
Xcb::WindowGeometry geo(w);
|
||||
if (attr.isNull() || attr->map_state != XCB_MAP_STATE_VIEWABLE) {
|
||||
return false;
|
||||
}
|
||||
if (attr->_class == XCB_WINDOW_CLASS_INPUT_ONLY) {
|
||||
return false;
|
||||
}
|
||||
if (geo.isNull()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_unmanaged = true;
|
||||
|
||||
setWindowHandles(w);
|
||||
m_frame.reset(w, false);
|
||||
m_wrapper.reset(w, false);
|
||||
m_client.reset(w, false);
|
||||
|
||||
Xcb::selectInput(w, attr->your_event_mask | XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_PROPERTY_CHANGE);
|
||||
m_bufferGeometry = geo.rect();
|
||||
m_frameGeometry = geo.rect();
|
||||
m_clientGeometry = geo.rect();
|
||||
checkOutput();
|
||||
m_visual = attr->visual;
|
||||
bit_depth = geo->depth;
|
||||
info = new NETWinInfo(kwinApp()->x11Connection(), w, kwinApp()->x11RootWindow(),
|
||||
NET::WMWindowType | NET::WMPid,
|
||||
NET::WM2Opacity | NET::WM2WindowRole | NET::WM2WindowClass | NET::WM2OpaqueRegion);
|
||||
setOpacity(info->opacityF());
|
||||
getResourceClass();
|
||||
getWmClientLeader();
|
||||
getWmClientMachine();
|
||||
if (Xcb::Extensions::self()->isShapeAvailable()) {
|
||||
xcb_shape_select_input(kwinApp()->x11Connection(), w, true);
|
||||
}
|
||||
detectShape(w);
|
||||
getWmOpaqueRegion();
|
||||
getSkipCloseAnimation();
|
||||
setupCompositing();
|
||||
if (QWindow *internalWindow = findInternalWindow()) {
|
||||
m_outline = internalWindow->property("__kwin_outline").toBool();
|
||||
}
|
||||
if (effects) {
|
||||
static_cast<EffectsHandlerImpl *>(effects)->checkInputWindowStacking();
|
||||
}
|
||||
|
||||
switch (kwinApp()->operationMode()) {
|
||||
case Application::OperationModeXwayland:
|
||||
// The wayland surface is associated with the override-redirect window asynchronously.
|
||||
if (surface()) {
|
||||
associate();
|
||||
} else {
|
||||
connect(this, &Window::surfaceChanged, this, &X11Window::associate);
|
||||
}
|
||||
break;
|
||||
case Application::OperationModeX11:
|
||||
// We have no way knowing whether the override-redirect window can be painted. Mark it
|
||||
// as ready for painting after synthetic 50ms delay.
|
||||
QTimer::singleShot(50, this, &X11Window::setReadyForPainting);
|
||||
break;
|
||||
case Application::OperationModeWaylandOnly:
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Manages the clients. This means handling the very first maprequest:
|
||||
* reparenting, initial geometry, initial state, placement, etc.
|
||||
|
@ -1333,6 +1454,9 @@ bool X11Window::userNoBorder() const
|
|||
|
||||
bool X11Window::isFullScreenable() const
|
||||
{
|
||||
if (isUnmanaged()) {
|
||||
return false;
|
||||
}
|
||||
if (!rules()->checkFullScreen(true)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1355,6 +1479,10 @@ bool X11Window::noBorder() const
|
|||
|
||||
bool X11Window::userCanSetNoBorder() const
|
||||
{
|
||||
if (isUnmanaged()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Client-side decorations and server-side decorations are mutually exclusive.
|
||||
if (isClientSideDecorated()) {
|
||||
return false;
|
||||
|
@ -1657,7 +1785,7 @@ void X11Window::doSetShade(ShadeMode previousShadeMode)
|
|||
|
||||
void X11Window::updateVisibility()
|
||||
{
|
||||
if (isDeleted()) {
|
||||
if (isUnmanaged() || isDeleted()) {
|
||||
return;
|
||||
}
|
||||
if (hidden) {
|
||||
|
@ -1872,7 +2000,7 @@ void X11Window::sendClientMessage(xcb_window_t w, xcb_atom_t a, xcb_atom_t proto
|
|||
*/
|
||||
bool X11Window::isCloseable() const
|
||||
{
|
||||
return rules()->checkCloseable(m_motif.close() && !isSpecialWindow());
|
||||
return !isUnmanaged() && rules()->checkCloseable(m_motif.close() && !isSpecialWindow());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1901,10 +2029,14 @@ void X11Window::closeWindow()
|
|||
*/
|
||||
void X11Window::killWindow()
|
||||
{
|
||||
qCDebug(KWIN_CORE) << "X11Window::killWindow():" << caption();
|
||||
killProcess(false);
|
||||
m_client.kill(); // Always kill this client at the server
|
||||
destroyWindow();
|
||||
qCDebug(KWIN_CORE) << "X11Window::killWindow():" << window();
|
||||
if (isUnmanaged()) {
|
||||
xcb_kill_client(kwinApp()->x11Connection(), window());
|
||||
} else {
|
||||
killProcess(false);
|
||||
m_client.kill(); // Always kill this client at the server
|
||||
destroyWindow();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2580,11 +2712,25 @@ QString X11Window::preferredColorScheme() const
|
|||
|
||||
bool X11Window::isClient() const
|
||||
{
|
||||
return true;
|
||||
return !m_unmanaged;
|
||||
}
|
||||
|
||||
bool X11Window::isUnmanaged() const
|
||||
{
|
||||
return m_unmanaged;
|
||||
}
|
||||
|
||||
bool X11Window::isOutline() const
|
||||
{
|
||||
return m_outline;
|
||||
}
|
||||
|
||||
NET::WindowType X11Window::windowType(bool direct) const
|
||||
{
|
||||
if (m_unmanaged) {
|
||||
return info->windowType(SUPPORTED_UNMANAGED_WINDOW_TYPES_MASK);
|
||||
}
|
||||
|
||||
NET::WindowType wt = info->windowType(SUPPORTED_MANAGED_WINDOW_TYPES_MASK);
|
||||
if (direct) {
|
||||
return wt;
|
||||
|
@ -4030,6 +4176,9 @@ void X11Window::GTKShowWindowMenu(qreal x_root, qreal y_root)
|
|||
|
||||
bool X11Window::isMovable() const
|
||||
{
|
||||
if (isUnmanaged()) {
|
||||
return false;
|
||||
}
|
||||
if (!hasNETSupport() && !m_motif.move()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -4047,6 +4196,9 @@ bool X11Window::isMovable() const
|
|||
|
||||
bool X11Window::isMovableAcrossScreens() const
|
||||
{
|
||||
if (isUnmanaged()) {
|
||||
return false;
|
||||
}
|
||||
if (!hasNETSupport() && !m_motif.move()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -4061,6 +4213,9 @@ bool X11Window::isMovableAcrossScreens() const
|
|||
|
||||
bool X11Window::isResizable() const
|
||||
{
|
||||
if (isUnmanaged()) {
|
||||
return false;
|
||||
}
|
||||
if (!hasNETSupport() && !m_motif.resize()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -4085,6 +4240,9 @@ bool X11Window::isResizable() const
|
|||
|
||||
bool X11Window::isMaximizable() const
|
||||
{
|
||||
if (isUnmanaged()) {
|
||||
return false;
|
||||
}
|
||||
if (!isResizable() || isToolbar()) { // SELI isToolbar() ?
|
||||
return false;
|
||||
}
|
||||
|
@ -4113,6 +4271,11 @@ void X11Window::moveResizeInternal(const QRectF &rect, MoveResizeMode mode)
|
|||
// Such code is wrong and should be changed to handle the case when the window is shaded,
|
||||
// for example using X11Window::clientSize()
|
||||
|
||||
if (isUnmanaged()) {
|
||||
qCWarning(KWIN_CORE) << "Cannot move or resize unmanaged window" << this;
|
||||
return;
|
||||
}
|
||||
|
||||
QRectF frameGeometry = Xcb::fromXNative(Xcb::toXNative(rect));
|
||||
|
||||
if (shade_geometry_change) {
|
||||
|
@ -4215,6 +4378,11 @@ void X11Window::updateServerGeometry()
|
|||
static bool changeMaximizeRecursion = false;
|
||||
void X11Window::maximize(MaximizeMode mode)
|
||||
{
|
||||
if (isUnmanaged()) {
|
||||
qCWarning(KWIN_CORE) << "Cannot change maximized state of unmanaged window" << this;
|
||||
return;
|
||||
}
|
||||
|
||||
if (changeMaximizeRecursion) {
|
||||
return;
|
||||
}
|
||||
|
@ -4487,6 +4655,9 @@ void X11Window::maximize(MaximizeMode mode)
|
|||
|
||||
bool X11Window::userCanSetFullScreen() const
|
||||
{
|
||||
if (isUnmanaged()) {
|
||||
return false;
|
||||
}
|
||||
if (!isFullScreenable()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -4773,7 +4944,7 @@ void X11Window::applyWindowRules()
|
|||
|
||||
bool X11Window::supportsWindowRules() const
|
||||
{
|
||||
return true;
|
||||
return !isUnmanaged();
|
||||
}
|
||||
|
||||
void X11Window::updateWindowRules(Rules::Types selection)
|
||||
|
@ -4814,4 +4985,31 @@ void X11Window::updateWindowPixmap()
|
|||
}
|
||||
}
|
||||
|
||||
void X11Window::associate()
|
||||
{
|
||||
if (surface()->isMapped()) {
|
||||
setReadyForPainting();
|
||||
} else {
|
||||
// Queued connection because we want to mark the window ready for painting after
|
||||
// the associated surface item has processed the new surface state.
|
||||
connect(surface(), &KWaylandServer::SurfaceInterface::mapped, this, &X11Window::setReadyForPainting, Qt::QueuedConnection);
|
||||
}
|
||||
}
|
||||
|
||||
QWindow *X11Window::findInternalWindow() const
|
||||
{
|
||||
const QWindowList windows = kwinApp()->topLevelWindows();
|
||||
for (QWindow *w : windows) {
|
||||
if (w->handle() && w->winId() == window()) {
|
||||
return w;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void X11Window::checkOutput()
|
||||
{
|
||||
setOutput(workspace()->outputAt(frameGeometry().center()));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -120,8 +120,12 @@ public:
|
|||
bool windowEvent(xcb_generic_event_t *e);
|
||||
NET::WindowType windowType(bool direct = false) const override;
|
||||
|
||||
bool track(xcb_window_t w);
|
||||
bool manage(xcb_window_t w, bool isMapped);
|
||||
|
||||
void releaseWindow(bool on_shutdown = false);
|
||||
bool hasScheduledRelease() const;
|
||||
|
||||
void destroyWindow() override;
|
||||
|
||||
QStringList activities() const override;
|
||||
|
@ -248,6 +252,8 @@ public:
|
|||
// sets whether the client should be faked as being on all activities (and be shown during session save)
|
||||
void setSessionActivityOverride(bool needed);
|
||||
bool isClient() const override;
|
||||
bool isOutline() const override;
|
||||
bool isUnmanaged() const override;
|
||||
|
||||
void cancelFocusOutTimer();
|
||||
|
||||
|
@ -297,6 +303,7 @@ private:
|
|||
bool mapRequestEvent(xcb_map_request_event_t *e);
|
||||
void unmapNotifyEvent(xcb_unmap_notify_event_t *e);
|
||||
void destroyNotifyEvent(xcb_destroy_notify_event_t *e);
|
||||
void configureNotifyEvent(xcb_configure_notify_event_t *e);
|
||||
void configureRequestEvent(xcb_configure_request_event_t *e);
|
||||
void propertyNotifyEvent(xcb_property_notify_event_t *e) override;
|
||||
void clientMessageEvent(xcb_client_message_event_t *e) override;
|
||||
|
@ -407,6 +414,10 @@ private:
|
|||
void createDecoration(const QRectF &oldgeom);
|
||||
void destroyDecoration();
|
||||
|
||||
QWindow *findInternalWindow() const;
|
||||
void checkOutput();
|
||||
void associate();
|
||||
|
||||
Xcb::Window m_client;
|
||||
Xcb::Window m_wrapper;
|
||||
Xcb::Window m_frame;
|
||||
|
@ -477,6 +488,7 @@ private:
|
|||
QPointF input_offset;
|
||||
|
||||
QTimer *m_focusOutTimer;
|
||||
QTimer m_releaseTimer;
|
||||
|
||||
QMetaObject::Connection m_edgeRemoveConnection;
|
||||
QMetaObject::Connection m_edgeGeometryTrackingConnection;
|
||||
|
@ -487,6 +499,9 @@ private:
|
|||
QRectF m_lastFrameGeometry;
|
||||
QRectF m_lastClientGeometry;
|
||||
std::unique_ptr<X11DecorationRenderer> m_decorationRenderer;
|
||||
|
||||
bool m_unmanaged = false;
|
||||
bool m_outline = false;
|
||||
};
|
||||
|
||||
inline xcb_window_t X11Window::wrapperId() const
|
||||
|
|
Loading…
Reference in a new issue