Changeset View
Changeset View
Standalone View
Standalone View
plugins/platforms/wayland/wayland_output.cpp
- This file was added.
1 | /******************************************************************** | ||||
---|---|---|---|---|---|
2 | KWin - the KDE window manager | ||||
3 | This file is part of the KDE project. | ||||
4 | | ||||
5 | Copyright 2019 Roman Gilg <subdiff@gmail.com> | ||||
6 | | ||||
7 | This program is free software; you can redistribute it and/or modify | ||||
8 | it under the terms of the GNU General Public License as published by | ||||
9 | the Free Software Foundation; either version 2 of the License, or | ||||
10 | (at your option) any later version. | ||||
11 | | ||||
12 | This program is distributed in the hope that it will be useful, | ||||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
15 | GNU General Public License for more details. | ||||
16 | | ||||
17 | You should have received a copy of the GNU General Public License | ||||
18 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||||
19 | *********************************************************************/ | ||||
20 | | ||||
21 | #include "wayland_output.h" | ||||
22 | #include "wayland_backend.h" | ||||
23 | | ||||
24 | #include "wayland_server.h" | ||||
25 | | ||||
26 | #include <KWayland/Client/pointerconstraints.h> | ||||
27 | #include <KWayland/Client/surface.h> | ||||
28 | #include <KWayland/Client/shell.h> | ||||
29 | | ||||
30 | #include <KWayland/Server/display.h> | ||||
31 | | ||||
32 | #include <KLocalizedString> | ||||
33 | | ||||
34 | namespace KWin | ||||
35 | { | ||||
36 | namespace Wayland | ||||
37 | { | ||||
38 | | ||||
39 | using namespace KWayland::Client; | ||||
40 | | ||||
41 | WaylandOutput::WaylandOutput(Surface *surface, QObject *parent) | ||||
42 | : AbstractOutput(parent), | ||||
43 | m_surface(surface) | ||||
44 | { | ||||
45 | connect(surface, &Surface::frameRendered, [this] { | ||||
46 | m_rendered = true; | ||||
47 | emit frameRendered(); | ||||
48 | }); | ||||
49 | } | ||||
50 | | ||||
51 | WaylandOutput::~WaylandOutput() | ||||
52 | { | ||||
53 | m_surface->destroy(); | ||||
54 | delete m_surface; | ||||
55 | } | ||||
56 | | ||||
57 | QSize WaylandOutput::pixelSize() const | ||||
58 | { | ||||
59 | return m_pixelSize; | ||||
60 | } | ||||
61 | | ||||
62 | void WaylandOutput::setGeometry(const QPoint &logicalPosition, const QSize &pixelSize) | ||||
63 | { | ||||
64 | m_pixelSize = pixelSize; | ||||
65 | setRawPhysicalSize(pixelSize); | ||||
66 | setGlobalPos(logicalPosition); | ||||
67 | } | ||||
68 | | ||||
69 | ShellOutput::ShellOutput(Surface *surface, Shell *shell, WaylandBackend *backend) | ||||
70 | : WaylandOutput(surface, backend) | ||||
71 | { | ||||
72 | auto shellSurface = shell->createSurface(surface, this); | ||||
73 | shellSurface->setToplevel(); | ||||
74 | } | ||||
75 | | ||||
76 | ShellOutput::~ShellOutput() | ||||
77 | { | ||||
78 | m_shellSurface->destroy(); | ||||
79 | delete m_shellSurface; | ||||
80 | } | ||||
81 | | ||||
82 | XdgShellOutput::XdgShellOutput(Surface *surface, XdgShell *xdgShell, WaylandBackend *backend, int number) | ||||
83 | : WaylandOutput(surface, backend) | ||||
84 | , m_backend(backend) | ||||
85 | , m_number(number) | ||||
86 | { | ||||
87 | m_xdgShellSurface = xdgShell->createSurface(surface, this); | ||||
88 | updateWindowTitle(); | ||||
89 | | ||||
90 | connect(m_xdgShellSurface, &XdgShellSurface::configureRequested, this, &XdgShellOutput::handleConfigure); | ||||
91 | connect(m_xdgShellSurface, &XdgShellSurface::closeRequested, qApp, &QCoreApplication::quit); | ||||
92 | | ||||
93 | connect(backend, &WaylandBackend::pointerLockSupportedChanged, this, &XdgShellOutput::updateWindowTitle); | ||||
94 | connect(backend, &WaylandBackend::pointerLockChanged, this, [this](bool locked) { | ||||
95 | if (locked) { | ||||
96 | if (!m_hasPointerLock) { | ||||
97 | // some other output has locked the pointer | ||||
98 | // this surface can stop trying to lock the pointer | ||||
99 | lockPointer(nullptr, false); | ||||
100 | // set it true for the other surface | ||||
101 | m_hasPointerLock = true; | ||||
102 | } | ||||
103 | } else { | ||||
104 | // just try unlocking | ||||
105 | lockPointer(nullptr, false); | ||||
106 | } | ||||
107 | updateWindowTitle(); | ||||
108 | }); | ||||
109 | } | ||||
110 | | ||||
111 | XdgShellOutput::~XdgShellOutput() | ||||
112 | { | ||||
113 | m_xdgShellSurface->destroy(); | ||||
114 | delete m_xdgShellSurface; | ||||
115 | } | ||||
116 | | ||||
117 | void XdgShellOutput::handleConfigure(const QSize &size, XdgShellSurface::States states, quint32 serial) | ||||
118 | { | ||||
119 | Q_UNUSED(states); | ||||
120 | if (size.width() == 0 || size.height() == 0) { | ||||
121 | return; | ||||
122 | } | ||||
123 | setGeometry(geometry().topLeft(), size); | ||||
124 | m_xdgShellSurface->ackConfigure(serial); | ||||
125 | emit sizeChanged(size); | ||||
126 | } | ||||
127 | | ||||
128 | void XdgShellOutput::updateWindowTitle() | ||||
129 | { | ||||
130 | QString grab; | ||||
131 | if (m_hasPointerLock) { | ||||
132 | grab = i18n("Press right control to ungrab pointer"); | ||||
133 | } else if (m_backend->pointerConstraints()) { | ||||
134 | grab = i18n("Press right control key to grab pointer"); | ||||
135 | } | ||||
136 | const QString title = i18nc("Title of nested KWin Wayland with Wayland socket identifier as argument", | ||||
137 | "KDE Wayland Compositor #%1 (%2)", m_number, waylandServer()->display()->socketName()); | ||||
138 | | ||||
139 | if (grab.isEmpty()) { | ||||
140 | m_xdgShellSurface->setTitle(title); | ||||
141 | } else { | ||||
142 | m_xdgShellSurface->setTitle(title + QStringLiteral(" — ") + grab); | ||||
143 | } | ||||
144 | } | ||||
145 | | ||||
146 | void XdgShellOutput::lockPointer(Pointer *pointer, bool lock) | ||||
147 | { | ||||
148 | if (!lock) { | ||||
149 | const bool surfaceWasLocked = m_pointerLock && m_hasPointerLock; | ||||
150 | delete m_pointerLock; | ||||
151 | m_pointerLock = nullptr; | ||||
152 | m_hasPointerLock = false; | ||||
153 | if (surfaceWasLocked) { | ||||
154 | emit m_backend->pointerLockChanged(false); | ||||
155 | } | ||||
156 | return; | ||||
157 | } | ||||
158 | | ||||
159 | Q_ASSERT(!m_pointerLock); | ||||
160 | m_pointerLock = m_backend->pointerConstraints()->lockPointer(surface(), pointer, nullptr, | ||||
161 | PointerConstraints::LifeTime::OneShot, | ||||
162 | this); | ||||
163 | if (!m_pointerLock->isValid()) { | ||||
164 | delete m_pointerLock; | ||||
165 | m_pointerLock = nullptr; | ||||
166 | return; | ||||
167 | } | ||||
168 | connect(m_pointerLock, &LockedPointer::locked, this, | ||||
169 | [this] { | ||||
170 | m_hasPointerLock = true; | ||||
171 | emit m_backend->pointerLockChanged(true); | ||||
172 | } | ||||
173 | ); | ||||
174 | connect(m_pointerLock, &LockedPointer::unlocked, this, | ||||
175 | [this] { | ||||
176 | delete m_pointerLock; | ||||
177 | m_pointerLock = nullptr; | ||||
178 | m_hasPointerLock = false; | ||||
179 | emit m_backend->pointerLockChanged(false); | ||||
180 | } | ||||
181 | ); | ||||
182 | } | ||||
183 | | ||||
184 | } | ||||
185 | } |