Support text-input-v3 cursor position and position the overlay mode input panel within the screen.
This commit is contained in:
parent
7a270b5d78
commit
e71fe9ba79
4 changed files with 89 additions and 58 deletions
|
@ -18,6 +18,7 @@
|
||||||
#include <KWaylandServer/seat_interface.h>
|
#include <KWaylandServer/seat_interface.h>
|
||||||
#include <KWaylandServer/surface_interface.h>
|
#include <KWaylandServer/surface_interface.h>
|
||||||
#include <KWaylandServer/textinput_v2_interface.h>
|
#include <KWaylandServer/textinput_v2_interface.h>
|
||||||
|
#include <KWaylandServer/textinput_v3_interface.h>
|
||||||
|
|
||||||
using namespace KWaylandServer;
|
using namespace KWaylandServer;
|
||||||
|
|
||||||
|
@ -90,11 +91,40 @@ void KWin::InputPanelV1Client::reposition()
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case Overlay: {
|
case Overlay: {
|
||||||
auto textClient = waylandServer()->findClient(waylandServer()->seat()->focusedTextInputSurface());
|
auto textInputSurface = waylandServer()->seat()->focusedTextInputSurface();
|
||||||
auto textInput = waylandServer()->seat()->textInputV2();
|
auto textClient = waylandServer()->findClient(textInputSurface);
|
||||||
if (textClient && textInput) {
|
QRect cursorRectangle;
|
||||||
const auto cursorRectangle = textInput->cursorRectangle();
|
auto textInputV2 = waylandServer()->seat()->textInputV2();
|
||||||
moveResize({textClient->pos() + textClient->clientPos() + cursorRectangle.bottomLeft(), surface()->size()});
|
if (textInputV2 && textInputV2->isEnabled() && textInputV2->surface() == textInputSurface) {
|
||||||
|
cursorRectangle = textInputV2->cursorRectangle();
|
||||||
|
}
|
||||||
|
auto textInputV3 = waylandServer()->seat()->textInputV3();
|
||||||
|
if (textInputV3 && textInputV3->isEnabled() && textInputV3->surface() == textInputSurface) {
|
||||||
|
cursorRectangle = textInputV3->cursorRectangle();
|
||||||
|
}
|
||||||
|
if (textClient) {
|
||||||
|
cursorRectangle.translate(textClient->pos() + textClient->clientPos());
|
||||||
|
const QRect screen = Workspace::self()->clientArea(PlacementArea, cursorRectangle.bottomLeft(), 0);
|
||||||
|
|
||||||
|
// Reuse the similar logic like xdg popup
|
||||||
|
QRect popupRect(popupOffset(cursorRectangle, Qt::TopEdge | Qt::LeftEdge, Qt::RightEdge | Qt::BottomEdge, surface()->size()), surface()->size());
|
||||||
|
|
||||||
|
if (popupRect.left() < screen.left()) {
|
||||||
|
popupRect.moveLeft(screen.left());
|
||||||
|
}
|
||||||
|
if (popupRect.right() > screen.right()) {
|
||||||
|
popupRect.moveRight(screen.right());
|
||||||
|
}
|
||||||
|
if (popupRect.top() < screen.top() || popupRect.bottom() > screen.bottom()) {
|
||||||
|
auto flippedPopupRect =
|
||||||
|
QRect(popupOffset(cursorRectangle, Qt::BottomEdge | Qt::LeftEdge, Qt::RightEdge | Qt::TopEdge, surface()->size()), surface()->size());
|
||||||
|
|
||||||
|
// if it still doesn't fit we should continue with the unflipped version
|
||||||
|
if (flippedPopupRect.top() >= screen.top() || flippedPopupRect.bottom() <= screen.bottom()) {
|
||||||
|
popupRect.moveTop(flippedPopupRect.top());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
moveResize(popupRect);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -203,6 +203,58 @@ qreal qPainterEffectiveDevicePixelRatio(const QPainter *painter)
|
||||||
return std::max(qreal(1), painter->device()->devicePixelRatioF());
|
return std::max(qreal(1), painter->device()->devicePixelRatioF());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QPoint popupOffset(const QRect &anchorRect, const Qt::Edges anchorEdge, const Qt::Edges gravity, const QSize popupSize)
|
||||||
|
{
|
||||||
|
QPoint anchorPoint;
|
||||||
|
switch (anchorEdge & (Qt::LeftEdge | Qt::RightEdge)) {
|
||||||
|
case Qt::LeftEdge:
|
||||||
|
anchorPoint.setX(anchorRect.x());
|
||||||
|
break;
|
||||||
|
case Qt::RightEdge:
|
||||||
|
anchorPoint.setX(anchorRect.x() + anchorRect.width());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
anchorPoint.setX(qRound(anchorRect.x() + anchorRect.width() / 2.0));
|
||||||
|
}
|
||||||
|
switch (anchorEdge & (Qt::TopEdge | Qt::BottomEdge)) {
|
||||||
|
case Qt::TopEdge:
|
||||||
|
anchorPoint.setY(anchorRect.y());
|
||||||
|
break;
|
||||||
|
case Qt::BottomEdge:
|
||||||
|
anchorPoint.setY(anchorRect.y() + anchorRect.height());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
anchorPoint.setY(qRound(anchorRect.y() + anchorRect.height() / 2.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculate where the top left point of the popup will end up with the applied gravity
|
||||||
|
// gravity indicates direction. i.e if gravitating towards the top the popup's bottom edge
|
||||||
|
// will next to the anchor point
|
||||||
|
QPoint popupPosAdjust;
|
||||||
|
switch (gravity & (Qt::LeftEdge | Qt::RightEdge)) {
|
||||||
|
case Qt::LeftEdge:
|
||||||
|
popupPosAdjust.setX(-popupSize.width());
|
||||||
|
break;
|
||||||
|
case Qt::RightEdge:
|
||||||
|
popupPosAdjust.setX(0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
popupPosAdjust.setX(qRound(-popupSize.width() / 2.0));
|
||||||
|
}
|
||||||
|
switch (gravity & (Qt::TopEdge | Qt::BottomEdge)) {
|
||||||
|
case Qt::TopEdge:
|
||||||
|
popupPosAdjust.setY(-popupSize.height());
|
||||||
|
break;
|
||||||
|
case Qt::BottomEdge:
|
||||||
|
popupPosAdjust.setY(0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
popupPosAdjust.setY(qRound(-popupSize.height() / 2.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
return anchorPoint + popupPosAdjust;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
#ifndef KCMRULES
|
#ifndef KCMRULES
|
||||||
|
|
|
@ -280,6 +280,8 @@ private:
|
||||||
int m_capacity = 10;
|
int m_capacity = 10;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
KWIN_EXPORT QPoint popupOffset(const QRect &anchorRect, const Qt::Edges anchorEdge, const Qt::Edges gravity, const QSize popupSize);
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
// Must be outside namespace
|
// Must be outside namespace
|
||||||
|
|
|
@ -1865,59 +1865,6 @@ bool XdgPopupClient::hasTransientPlacementHint() const
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static QPoint popupOffset(const QRect &anchorRect, const Qt::Edges anchorEdge,
|
|
||||||
const Qt::Edges gravity, const QSize popupSize)
|
|
||||||
{
|
|
||||||
QPoint anchorPoint;
|
|
||||||
switch (anchorEdge & (Qt::LeftEdge | Qt::RightEdge)) {
|
|
||||||
case Qt::LeftEdge:
|
|
||||||
anchorPoint.setX(anchorRect.x());
|
|
||||||
break;
|
|
||||||
case Qt::RightEdge:
|
|
||||||
anchorPoint.setX(anchorRect.x() + anchorRect.width());
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
anchorPoint.setX(qRound(anchorRect.x() + anchorRect.width() / 2.0));
|
|
||||||
}
|
|
||||||
switch (anchorEdge & (Qt::TopEdge | Qt::BottomEdge)) {
|
|
||||||
case Qt::TopEdge:
|
|
||||||
anchorPoint.setY(anchorRect.y());
|
|
||||||
break;
|
|
||||||
case Qt::BottomEdge:
|
|
||||||
anchorPoint.setY(anchorRect.y() + anchorRect.height());
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
anchorPoint.setY(qRound(anchorRect.y() + anchorRect.height() / 2.0));
|
|
||||||
}
|
|
||||||
|
|
||||||
// calculate where the top left point of the popup will end up with the applied gravity
|
|
||||||
// gravity indicates direction. i.e if gravitating towards the top the popup's bottom edge
|
|
||||||
// will next to the anchor point
|
|
||||||
QPoint popupPosAdjust;
|
|
||||||
switch (gravity & (Qt::LeftEdge | Qt::RightEdge)) {
|
|
||||||
case Qt::LeftEdge:
|
|
||||||
popupPosAdjust.setX(-popupSize.width());
|
|
||||||
break;
|
|
||||||
case Qt::RightEdge:
|
|
||||||
popupPosAdjust.setX(0);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
popupPosAdjust.setX(qRound(-popupSize.width() / 2.0));
|
|
||||||
}
|
|
||||||
switch (gravity & (Qt::TopEdge | Qt::BottomEdge)) {
|
|
||||||
case Qt::TopEdge:
|
|
||||||
popupPosAdjust.setY(-popupSize.height());
|
|
||||||
break;
|
|
||||||
case Qt::BottomEdge:
|
|
||||||
popupPosAdjust.setY(0);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
popupPosAdjust.setY(qRound(-popupSize.height() / 2.0));
|
|
||||||
}
|
|
||||||
|
|
||||||
return anchorPoint + popupPosAdjust;
|
|
||||||
}
|
|
||||||
|
|
||||||
QRect XdgPopupClient::transientPlacement(const QRect &bounds) const
|
QRect XdgPopupClient::transientPlacement(const QRect &bounds) const
|
||||||
{
|
{
|
||||||
const XdgPositioner positioner = m_shellSurface->positioner();
|
const XdgPositioner positioner = m_shellSurface->positioner();
|
||||||
|
|
Loading…
Reference in a new issue