Commit 0be0e8a7 authored by Vlad Zahorodnii's avatar Vlad Zahorodnii
Browse files

Add Window::moveResizeOutput()

The Window::moveResizeOutput() property is used to track the output
where the window is expected to land after the move or resize operation
completes.

This can be used to decouple the current output from the next output,
which allows us to send better xdg_toplevel.configure_bounds events or
make windows stick to outputs while keeping Window::output() in sync
with the current output layout.
parent 0ea72e92
......@@ -667,10 +667,10 @@ void Window::packTo(qreal left, qreal top)
{
workspace()->updateFocusMousePosition(Cursors::self()->mouse()->pos()); // may cause leave event;
const Output *oldOutput = output();
const Output *oldOutput = moveResizeOutput();
move(QPointF(left, top));
if (output() != oldOutput) {
workspace()->sendWindowToOutput(this, output()); // checks rule validity
if (moveResizeOutput() != oldOutput) {
workspace()->sendWindowToOutput(this, moveResizeOutput()); // checks rule validity
if (maximizeMode() != MaximizeRestore) {
checkWorkspacePosition();
}
......
......@@ -23,7 +23,7 @@ PlacementTracker::PlacementTracker(Workspace *workspace)
PlacementTracker::WindowData PlacementTracker::dataForWindow(Window *window) const
{
return WindowData{
.outputUuid = workspace()->outputAt(window->moveResizeGeometry().center())->uuid(),
.outputUuid = window->moveResizeOutput()->uuid(),
.geometry = window->moveResizeGeometry(),
.maximize = window->requestedMaximizeMode(),
.quickTile = window->quickTileMode(),
......@@ -142,7 +142,7 @@ void PlacementTracker::saveGeometry(Window *window)
if (m_inhibitCount == 0) {
auto &data = m_data[m_currentKey][window];
data.geometry = window->moveResizeGeometry();
data.outputUuid = workspace()->outputAt(window->moveResizeGeometry().center())->uuid();
data.outputUuid = window->moveResizeOutput()->uuid();
}
}
......
......@@ -1383,14 +1383,14 @@ void Workspace::slotWindowToScreen()
void Workspace::slotWindowToNextScreen()
{
if (USABLE_ACTIVE_WINDOW) {
sendWindowToOutput(m_activeWindow, nextOutput(m_activeWindow->output()));
sendWindowToOutput(m_activeWindow, nextOutput(m_activeWindow->moveResizeOutput()));
}
}
void Workspace::slotWindowToPrevScreen()
{
if (USABLE_ACTIVE_WINDOW) {
sendWindowToOutput(m_activeWindow, previousOutput(m_activeWindow->output()));
sendWindowToOutput(m_activeWindow, previousOutput(m_activeWindow->moveResizeOutput()));
}
}
......
......@@ -78,6 +78,7 @@ Window::Window()
, m_tabBoxClient(QSharedPointer<TabBox::TabBoxClientImpl>::create(this))
#endif
, m_colorScheme(QStringLiteral("kdeglobals"))
, m_moveResizeOutput(workspace()->activeOutput())
{
connect(this, &Window::bufferGeometryChanged, this, &Window::inputTransformationChanged);
......@@ -1684,8 +1685,8 @@ void Window::finishInteractiveMoveResize(bool cancel)
if (cancel) {
moveResize(initialInteractiveMoveResizeGeometry());
}
if (output() != interactiveMoveResizeStartOutput()) {
workspace()->sendWindowToOutput(this, output()); // checks rule validity
if (moveResizeOutput() != interactiveMoveResizeStartOutput()) {
workspace()->sendWindowToOutput(this, moveResizeOutput()); // checks rule validity
if (isFullScreen() || maximizeMode() != MaximizeRestore) {
checkWorkspacePosition();
}
......@@ -3648,24 +3649,39 @@ QRectF Window::moveResizeGeometry() const
void Window::setMoveResizeGeometry(const QRectF &geo)
{
m_moveResizeGeometry = geo;
m_moveResizeOutput = workspace()->outputAt(geo.center());
}
Output *Window::moveResizeOutput() const
{
return m_moveResizeOutput;
}
void Window::setMoveResizeOutput(Output *output)
{
m_moveResizeOutput = output;
}
void Window::move(const QPointF &point)
{
m_moveResizeGeometry.moveTopLeft(point);
moveResizeInternal(m_moveResizeGeometry, MoveResizeMode::Move);
const QRectF rect = QRectF(point, m_moveResizeGeometry.size());
setMoveResizeGeometry(rect);
moveResizeInternal(rect, MoveResizeMode::Move);
}
void Window::resize(const QSizeF &size)
{
m_moveResizeGeometry.setSize(size);
moveResizeInternal(m_moveResizeGeometry, MoveResizeMode::Resize);
const QRectF rect = QRectF(m_moveResizeGeometry.topLeft(), size);
setMoveResizeGeometry(rect);
moveResizeInternal(rect, MoveResizeMode::Resize);
}
void Window::moveResize(const QRectF &rect)
{
m_moveResizeGeometry = rect;
moveResizeInternal(m_moveResizeGeometry, MoveResizeMode::MoveResize);
setMoveResizeGeometry(rect);
moveResizeInternal(rect, MoveResizeMode::MoveResize);
}
void Window::setElectricBorderMode(QuickTileMode mode)
......@@ -3813,7 +3829,7 @@ void Window::setQuickTileMode(QuickTileMode mode, bool keyboard)
// screen if it exists, otherwise toggle the mode (set QuickTileFlag::None)
if (quickTileMode() == mode) {
const QList<Output *> outputs = workspace()->outputs();
const Output *currentOutput = output();
const Output *currentOutput = moveResizeOutput();
const Output *nextOutput = currentOutput;
for (const Output *output : outputs) {
......@@ -3936,12 +3952,11 @@ void Window::sendToOutput(Output *newOutput)
}
}
}
const QRectF oldGeom = moveResizeGeometry();
// output() may be outdated here
if (workspace()->outputAt(oldGeom.center()) == newOutput) {
if (moveResizeOutput() == newOutput) {
return;
}
const QRectF oldGeom = moveResizeGeometry();
const QRectF oldScreenArea = workspace()->clientArea(MaximizeArea, this);
const QRectF screenArea = workspace()->clientArea(MaximizeArea, this, newOutput);
......@@ -3992,12 +4007,12 @@ void Window::checkWorkspacePosition(QRectF oldGeometry, const VirtualDesktop *ol
QRect screenArea;
if (workspace()->inUpdateClientArea()) {
// check if the window is on an about to be destroyed output
Output *newOutput = output();
Output *newOutput = moveResizeOutput();
if (!workspace()->outputs().contains(newOutput)) {
newOutput = workspace()->outputAt(newGeom.center());
}
// we need to find the screen area as it was before the change
oldScreenArea = workspace()->previousScreenSizes().value(output());
oldScreenArea = workspace()->previousScreenSizes().value(moveResizeOutput());
if (oldScreenArea.isNull()) {
oldScreenArea = newOutput->geometry();
}
......@@ -4425,7 +4440,7 @@ void Window::applyWindowRules()
// MinSize, MaxSize handled by Geometry
// IgnoreGeometry
setDesktops(desktops());
workspace()->sendWindowToOutput(this, output());
workspace()->sendWindowToOutput(this, moveResizeOutput());
setOnActivities(activities());
// Type
maximize(maximizeMode());
......
......@@ -1206,6 +1206,13 @@ public:
*/
QRectF moveResizeGeometry() const;
/**
* Returns the output where the last move or resize operation has occurred. The
* window is expected to land on this output after the move/resize operation completes.
*/
Output *moveResizeOutput() const;
void setMoveResizeOutput(Output *output);
/**
* Returns @c true if the Client is being interactively moved; otherwise @c false.
*/
......@@ -1964,6 +1971,7 @@ private:
int m_blockGeometryUpdates = 0; // > 0 = New geometry is remembered, but not actually set
MoveResizeMode m_pendingMoveResizeMode = MoveResizeMode::None;
friend class GeometryUpdatesBlocker;
Output *m_moveResizeOutput;
QRectF m_moveResizeGeometry;
QRectF m_keyboardGeometryRestore;
QRectF m_maximizeGeometryRestore;
......
......@@ -1487,6 +1487,9 @@ void Workspace::removeOutput(Output *output)
if (window->output() == output) {
window->setOutput(outputAt(window->frameGeometry().center()));
}
if (window->moveResizeOutput() == output) {
window->setMoveResizeOutput(kwinApp()->platform()->outputAt(window->moveResizeGeometry().center()));
}
}
Q_EMIT outputRemoved(output);
......
......@@ -4610,9 +4610,9 @@ void X11Window::setFullScreen(bool set, bool user)
}
} else {
Q_ASSERT(!fullscreenGeometryRestore().isNull());
Output *currentOutput = output();
Output *currentOutput = moveResizeOutput();
moveResize(QRectF(fullscreenGeometryRestore().topLeft(), constrainFrameSize(fullscreenGeometryRestore().size())));
if (currentOutput != output()) {
if (currentOutput != moveResizeOutput()) {
workspace()->sendWindowToOutput(this, currentOutput);
}
}
......
......@@ -1614,16 +1614,16 @@ void XdgToplevelWindow::setFullScreen(bool set, bool user)
configureDecoration();
if (set) {
const Output *output = m_fullScreenRequestedOutput ? m_fullScreenRequestedOutput.data() : workspace()->outputAt(moveResizeGeometry().center());
const Output *output = m_fullScreenRequestedOutput ? m_fullScreenRequestedOutput.data() : moveResizeOutput();
setFullscreenGeometryRestore(moveResizeGeometry());
moveResize(workspace()->clientArea(FullScreenArea, this, output));
} else {
m_fullScreenRequestedOutput.clear();
if (fullscreenGeometryRestore().isValid()) {
Output *currentOutput = output();
Output *currentOutput = moveResizeOutput();
moveResize(QRectF(fullscreenGeometryRestore().topLeft(),
constrainFrameSize(fullscreenGeometryRestore().size())));
if (currentOutput != output()) {
if (currentOutput != moveResizeOutput()) {
workspace()->sendWindowToOutput(this, currentOutput);
}
} else {
......@@ -1650,7 +1650,7 @@ void XdgToplevelWindow::changeMaximize(bool horizontal, bool vertical, bool adju
return;
}
const QRectF clientArea = isElectricBorderMaximizing() ? workspace()->clientArea(MaximizeArea, this, Cursors::self()->mouse()->pos()) : workspace()->clientArea(MaximizeArea, this, moveResizeGeometry().center());
const QRectF clientArea = isElectricBorderMaximizing() ? workspace()->clientArea(MaximizeArea, this, Cursors::self()->mouse()->pos()) : workspace()->clientArea(MaximizeArea, this, moveResizeOutput());
const MaximizeMode oldMode = m_requestedMaximizeMode;
const QRectF oldGeometry = moveResizeGeometry();
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment