KWin
Loading...
Searching...
No Matches
inputpanelv1window.cpp
Go to the documentation of this file.
1/*
2 KWin - the KDE window manager
3 This file is part of the KDE project.
4
5 SPDX-FileCopyrightText: 2020 Aleix Pol Gonzalez <aleixpol@kde.org>
6
7 SPDX-License-Identifier: GPL-2.0-or-later
8*/
9
10#include "inputpanelv1window.h"
11#include "core/output.h"
12#include "inputmethod.h"
13#include "wayland/output.h"
14#include "wayland/seat.h"
15#include "wayland/surface.h"
19#include "wayland_server.h"
20#include "workspace.h"
21
22namespace KWin
23{
24
26 : WaylandWindow(panelSurface->surface())
27 , m_panelSurface(panelSurface)
28{
29 setSkipSwitcher(true);
30 setSkipPager(true);
31 setSkipTaskbar(true);
32
34 connect(surface(), &SurfaceInterface::sizeChanged, this, &InputPanelV1Window::reposition);
35 connect(surface(), &SurfaceInterface::inputChanged, this, &InputPanelV1Window::reposition);
36 connect(surface(), &SurfaceInterface::mapped, this, &InputPanelV1Window::handleMapped);
37
38 connect(panelSurface, &InputPanelSurfaceV1Interface::topLevel, this, &InputPanelV1Window::showTopLevel);
39 connect(panelSurface, &InputPanelSurfaceV1Interface::overlayPanel, this, &InputPanelV1Window::showOverlayPanel);
41
42 connect(workspace(), &Workspace::outputsChanged, this, &InputPanelV1Window::reposition);
43
44 kwinApp()->inputMethod()->setPanel(this);
45}
46
47void InputPanelV1Window::showOverlayPanel()
48{
49 m_mode = Mode::Overlay;
50 maybeShow();
51}
52
53void InputPanelV1Window::showTopLevel(OutputInterface *output, InputPanelSurfaceV1Interface::Position position)
54{
55 m_mode = Mode::VirtualKeyboard;
56 maybeShow();
57}
58
60{
61 m_allowed = true;
62 maybeShow();
63}
64
66{
67 m_virtualKeyboardShouldBeShown = true;
68 maybeShow();
69}
70
72{
73 m_virtualKeyboardShouldBeShown = false;
74 if (readyForPainting() && m_mode != Mode::Overlay) {
75 setHidden(true);
76 }
77}
78
79void InputPanelV1Window::reposition()
80{
81 if (!readyForPainting()) {
82 return;
83 }
84
85 switch (m_mode) {
86 case Mode::None: {
87 // should never happen
88 }; break;
90 // maliit creates a fullscreen overlay so use the input shape as the window geometry.
91 m_windowGeometry = surface()->input().boundingRect();
92
93 const auto activeOutput = workspace()->activeOutput();
94 QRectF availableArea;
95 if (waylandServer()->isScreenLocked()) {
96 availableArea = workspace()->clientArea(FullScreenArea, this, activeOutput);
97 } else {
98 availableArea = workspace()->clientArea(MaximizeArea, this, activeOutput);
99 }
100
101 QRectF geo = m_windowGeometry;
102 geo.moveLeft(availableArea.left() + (availableArea.width() - geo.width()) / 2);
103 geo.moveBottom(availableArea.bottom());
104
105 moveResize(geo);
106 } break;
107 case Mode::Overlay: {
108 auto textInputSurface = waylandServer()->seat()->focusedTextInputSurface();
109 auto textWindow = waylandServer()->findWindow(textInputSurface);
110 QRect cursorRectangle;
111 auto textInputV1 = waylandServer()->seat()->textInputV1();
112 if (textInputV1 && textInputV1->isEnabled() && textInputV1->surface() == textInputSurface) {
113 cursorRectangle = textInputV1->cursorRectangle();
114 }
115 auto textInputV2 = waylandServer()->seat()->textInputV2();
116 if (textInputV2 && textInputV2->isEnabled() && textInputV2->surface() == textInputSurface) {
117 cursorRectangle = textInputV2->cursorRectangle();
118 }
119 auto textInputV3 = waylandServer()->seat()->textInputV3();
120 if (textInputV3 && textInputV3->isEnabled() && textInputV3->surface() == textInputSurface) {
121 cursorRectangle = textInputV3->cursorRectangle();
122 }
123 if (textWindow) {
124 cursorRectangle.translate(textWindow->bufferGeometry().topLeft().toPoint());
125 const QRectF screen = Workspace::self()->clientArea(PlacementArea, this, cursorRectangle.bottomLeft());
126
127 m_windowGeometry = QRectF(QPointF(0, 0), surface()->size());
128
129 // Reuse the similar logic like xdg popup
130 QRectF popupRect(popupOffset(cursorRectangle, Qt::BottomEdge | Qt::LeftEdge, Qt::RightEdge | Qt::BottomEdge, m_windowGeometry.size()), m_windowGeometry.size());
131
132 if (popupRect.left() < screen.left()) {
133 popupRect.moveLeft(screen.left());
134 }
135 if (popupRect.right() > screen.right()) {
136 popupRect.moveRight(screen.right());
137 }
138 if (popupRect.top() < screen.top() || popupRect.bottom() > screen.bottom()) {
139 auto flippedPopupRect =
140 QRectF(popupOffset(cursorRectangle, Qt::TopEdge | Qt::LeftEdge, Qt::RightEdge | Qt::TopEdge, m_windowGeometry.size()), m_windowGeometry.size());
141
142 // if it still doesn't fit we should continue with the unflipped version
143 if (flippedPopupRect.top() >= screen.top() && flippedPopupRect.bottom() <= screen.bottom()) {
144 popupRect.moveTop(flippedPopupRect.top());
145 }
146 }
147 if (popupRect.top() < screen.top()) {
148 popupRect.moveTop(screen.top());
149 }
150 if (popupRect.bottom() > screen.bottom()) {
151 popupRect.moveBottom(screen.bottom());
152 }
153
154 moveResize(popupRect);
155 }
156 } break;
157 }
158}
159
161{
162 m_panelSurface->disconnect(this);
163 m_panelSurface->surface()->disconnect(this);
164
166
167 Q_EMIT closed();
170
171 unref();
172}
173
174NET::WindowType InputPanelV1Window::windowType() const
175{
176 return NET::Utility;
177}
178
179QRectF InputPanelV1Window::frameRectToBufferRect(const QRectF &rect) const
180{
181 return QRectF(rect.topLeft() - m_windowGeometry.topLeft(), surface()->size());
182}
183
185{
187}
188
189void InputPanelV1Window::handleMapped()
190{
191 maybeShow();
192}
193
194void InputPanelV1Window::maybeShow()
195{
196 const bool shouldShow = m_mode == Mode::Overlay || (m_mode == Mode::VirtualKeyboard && m_allowed && m_virtualKeyboardShouldBeShown);
197 if (shouldShow && !isDeleted() && surface()->isMapped()) {
198 markAsMapped();
199 reposition();
200 setHidden(false);
201 }
202}
203
204} // namespace KWin
205
206#include "moc_inputpanelv1window.cpp"
void topLevel(OutputInterface *output, Position position)
NET::WindowType windowType() const override
InputPanelV1Window(InputPanelSurfaceV1Interface *panelSurface)
void moveResizeInternal(const QRectF &rect, MoveResizeMode mode) override
QRectF frameRectToBufferRect(const QRectF &rect) const override
SurfaceInterface * focusedTextInputSurface() const
Definition seat.cpp:1259
TextInputV1Interface * textInputV1() const
Definition seat.cpp:1264
TextInputV2Interface * textInputV2() const
Definition seat.cpp:1269
TextInputV3Interface * textInputV3() const
Definition seat.cpp:1274
void inputChanged(const QRegion &)
bool isMapped() const
Definition surface.cpp:891
Window * findWindow(const SurfaceInterface *surface) const
SeatInterface * seat() const
void removeWindow(Window *c)
void updateGeometry(const QRectF &rect)
void moveResize(const QRectF &rect)
Definition window.cpp:3323
QSizeF size
Definition window.h:84
SurfaceInterface * surface() const
Definition window.cpp:342
void setSkipTaskbar(bool set)
Definition window.cpp:464
bool readyForPainting() const
Definition window.h:1917
void unref()
Definition window.cpp:118
void setHidden(bool hidden)
Definition window.cpp:4242
QRectF rect
Definition window.h:113
void setSkipPager(bool set)
Definition window.cpp:448
void setSkipSwitcher(bool set)
Definition window.cpp:436
bool isDeleted() const
Definition window.cpp:540
void markAsDeleted()
Definition window.cpp:545
QRectF clientArea(clientAreaOption, const Output *output, const VirtualDesktop *desktop) const
Output * activeOutput() const
static Workspace * self()
Definition workspace.h:91
void outputsChanged()
@ FullScreenArea
Definition globals.h:53
@ MaximizeArea
Definition globals.h:51
@ PlacementArea
Definition globals.h:49
WaylandServer * waylandServer()
Workspace * workspace()
Definition workspace.h:830
QPointF popupOffset(const QRectF &anchorRect, const Qt::Edges anchorEdge, const Qt::Edges gravity, const QSizeF popupSize)
Definition common.cpp:194