Make support for the maximized mode partially optional

Summary:
Not all Client classes have support for the maximized mode. Therefore,
it can be made opt-in to reduce the amount of plumbed methods.

Unfortunately, there a few places, which don't have any connection with
the maximized mode, where AbstractClient::geometryRestore() is used, so
it cannot be made 100% optional at the moment.

Reviewers: #kwin

Subscribers: kwin

Tags: #kwin

Differential Revision: https://phabricator.kde.org/D27169
master
Vlad Zahorodnii 2020-02-04 21:14:13 +02:00
parent 34df058e54
commit 5af81c1cd7
8 changed files with 118 additions and 122 deletions

View File

@ -131,11 +131,6 @@ void AbstractClient::setClientShown(bool shown)
Q_UNUSED(shown)
}
MaximizeMode AbstractClient::requestedMaximizeMode() const
{
return maximizeMode();
}
xcb_timestamp_t AbstractClient::userTime() const
{
return XCB_TIME_CURRENT_TIME;
@ -3172,4 +3167,66 @@ bool AbstractClient::isMinimizable() const
return false;
}
/**
* Returns @c true if the AbstractClient can be maximized; otherwise @c false.
*
* Default implementation returns @c false.
*/
bool AbstractClient::isMaximizable() const
{
return false;
}
/**
* Returns the currently applied maximize mode.
*
* Default implementation returns MaximizeRestore.
*/
MaximizeMode AbstractClient::maximizeMode() const
{
return MaximizeRestore;
}
/**
* Returns the last requested maximize mode.
*
* On X11, this method always matches maximizeMode(). On Wayland, it is asynchronous.
*
* Default implementation matches maximizeMode().
*/
MaximizeMode AbstractClient::requestedMaximizeMode() const
{
return maximizeMode();
}
/**
* Returns the geometry of the AbstractClient before it was maximized or quick tiled.
*/
QRect AbstractClient::geometryRestore() const
{
return m_maximizeGeometryRestore;
}
/**
* Sets the geometry of the AbstractClient before it was maximized or quick tiled to @p rect.
*/
void AbstractClient::setGeometryRestore(const QRect &rect)
{
m_maximizeGeometryRestore = rect;
}
/**
* Toggles the maximized state along specified dimensions @p horizontal and @p vertical.
*
* If @p adjust is @c true, only frame geometry will be updated to match requestedMaximizeMode().
*
* Default implementation does nothing.
*/
void AbstractClient::changeMaximize(bool horizontal, bool vertical, bool adjust)
{
Q_UNUSED(horizontal)
Q_UNUSED(vertical)
Q_UNUSED(adjust)
}
}

View File

@ -488,16 +488,8 @@ public:
virtual void setClientShown(bool shown);
virtual QRect geometryRestore() const = 0;
/**
* The currently applied maximize mode
*/
virtual MaximizeMode maximizeMode() const = 0;
/**
* The maximise mode requested by the server.
* For X this always matches maximizeMode, for wayland clients it
* is asynchronous
*/
QRect geometryRestore() const;
virtual MaximizeMode maximizeMode() const;
virtual MaximizeMode requestedMaximizeMode() const;
void maximize(MaximizeMode);
/**
@ -540,10 +532,7 @@ public:
* Whether the Client can be shaded. Default implementation returns @c false.
*/
virtual bool isShadeable() const;
/**
* Returns whether the window is maximizable or not.
*/
virtual bool isMaximizable() const = 0;
virtual bool isMaximizable() const;
virtual bool isMinimizable() const;
virtual QRect iconGeometry() const;
virtual bool userCanSetFullScreen() const;
@ -1027,8 +1016,8 @@ protected:
int borderRight() const;
int borderTop() const;
int borderBottom() const;
virtual void changeMaximize(bool horizontal, bool vertical, bool adjust) = 0;
virtual void setGeometryRestore(const QRect &geo) = 0;
virtual void changeMaximize(bool horizontal, bool vertical, bool adjust);
void setGeometryRestore(const QRect &rect);
/**
* Called from move after updating the geometry. Can be reimplemented to perform specific tasks.
@ -1269,6 +1258,7 @@ private:
QRect m_frameGeometryBeforeUpdateBlocking;
QRect m_virtualKeyboardGeometry;
QRect m_keyboardGeometryRestore;
QRect m_maximizeGeometryRestore;
struct {
bool enabled = false;

View File

@ -208,11 +208,6 @@ bool InternalClient::isCloseable() const
return true;
}
bool InternalClient::isMaximizable() const
{
return false;
}
bool InternalClient::isMovable() const
{
return true;
@ -277,16 +272,6 @@ quint32 InternalClient::windowId() const
return m_windowId;
}
MaximizeMode InternalClient::maximizeMode() const
{
return MaximizeRestore;
}
QRect InternalClient::geometryRestore() const
{
return m_maximizeRestoreGeometry;
}
bool InternalClient::isShown(bool shaded_is_shown) const
{
Q_UNUSED(shaded_is_shown)
@ -355,11 +340,6 @@ void InternalClient::setFrameGeometry(int x, int y, int w, int h, ForceGeometry_
}
}
void InternalClient::setGeometryRestore(const QRect &rect)
{
m_maximizeRestoreGeometry = rect;
}
bool InternalClient::supportsWindowRules() const
{
return false;
@ -506,15 +486,6 @@ bool InternalClient::belongsToSameApplication(const AbstractClient *other, SameA
return qobject_cast<const InternalClient *>(other) != nullptr;
}
void InternalClient::changeMaximize(bool horizontal, bool vertical, bool adjust)
{
Q_UNUSED(horizontal)
Q_UNUSED(vertical)
Q_UNUSED(adjust)
// Internal clients are not maximizable.
}
void InternalClient::destroyDecoration()
{
if (!isDecorated()) {

View File

@ -53,7 +53,6 @@ public:
QByteArray windowRole() const override;
void closeWindow() override;
bool isCloseable() const override;
bool isMaximizable() const override;
bool isMovable() const override;
bool isMovableAcrossScreens() const override;
bool isResizable() const override;
@ -65,8 +64,6 @@ public:
bool isInputMethod() const override;
bool isOutline() const override;
quint32 windowId() const override;
MaximizeMode maximizeMode() const override;
QRect geometryRestore() const override;
bool isShown(bool shaded_is_shown) const override;
bool isHiddenInternal() const override;
void hideClient(bool hide) override;
@ -74,7 +71,6 @@ public:
void resizeWithChecks(int w, int h, ForceGeometry_t force = NormalGeometrySet) override;
using AbstractClient::setFrameGeometry;
void setFrameGeometry(int x, int y, int w, int h, ForceGeometry_t force = NormalGeometrySet) override;
void setGeometryRestore(const QRect &rect) override;
bool supportsWindowRules() const override;
AbstractClient *findModal(bool allow_itself = false) override;
void setOnAllActivities(bool set) override;
@ -92,7 +88,6 @@ public:
protected:
bool acceptsFocus() const override;
bool belongsToSameApplication(const AbstractClient *other, SameApplicationChecks checks) const override;
void changeMaximize(bool horizontal, bool vertical, bool adjust) override;
void destroyDecoration() override;
void doMove(int x, int y) override;
void doResizeSync() override;
@ -108,7 +103,6 @@ private:
void updateInternalWindowGeometry();
QWindow *m_internalWindow = nullptr;
QRect m_maximizeRestoreGeometry;
QSize m_clientSize = QSize(0, 0);
QString m_captionNormal;
QString m_captionSuffix;

View File

@ -653,7 +653,7 @@ bool X11Client::manage(xcb_window_t w, bool isMapped)
// TODO: get KMainWindow a correct state storage what will allow to store the restore size as well.
if (!session) { // has a better handling of this
geom_restore = frameGeometry(); // Remember restore geometry
setGeometryRestore(frameGeometry()); // Remember restore geometry
if (isMaximizable() && (width() >= area.width() || height() >= area.height())) {
// Window is too large for the screen, maximize in the
// directions necessary
@ -689,15 +689,16 @@ bool X11Client::manage(xcb_window_t w, bool isMapped)
maximize((MaximizeMode)pseudo_max);
// from now on, care about maxmode, since the maximization call will override mode for fix aspects
dontKeepInArea |= (max_mode == MaximizeFull);
geom_restore = QRect(); // Use placement when unmaximizing ...
QRect savedGeometry; // Use placement when unmaximizing ...
if (!(max_mode & MaximizeVertical)) {
geom_restore.setY(y()); // ...but only for horizontal direction
geom_restore.setHeight(height());
savedGeometry.setY(y()); // ...but only for horizontal direction
savedGeometry.setHeight(height());
}
if (!(max_mode & MaximizeHorizontal)) {
geom_restore.setX(x()); // ...but only for vertical direction
geom_restore.setWidth(width());
savedGeometry.setX(x()); // ...but only for vertical direction
savedGeometry.setWidth(width());
}
setGeometryRestore(savedGeometry);
}
if (keepInFsArea)
keepInArea(fsa, partial_keep_in_area);
@ -752,7 +753,7 @@ bool X11Client::manage(xcb_window_t w, bool isMapped)
setSkipSwitcher(session->skipSwitcher);
setShade(session->shaded ? ShadeNormal : ShadeNone);
setOpacity(session->opacity);
geom_restore = session->restore;
setGeometryRestore(session->restore);
if (session->maximized != MaximizeRestore) {
maximize(MaximizeMode(session->maximized));
}
@ -760,8 +761,10 @@ bool X11Client::manage(xcb_window_t w, bool isMapped)
setFullScreen(true, false);
geom_fs_restore = session->fsrestore;
}
checkOffscreenPosition(&geom_restore, area);
QRect checkedGeometryRestore = geometryRestore();
checkOffscreenPosition(&checkedGeometryRestore, area);
checkOffscreenPosition(&geom_fs_restore, area);
setGeometryRestore(checkedGeometryRestore);
} else {
// Window may want to be maximized
// done after checking that the window isn't larger than the workarea, so that
@ -4022,7 +4025,7 @@ void X11Client::configureRequest(int value_mask, int rx, int ry, int rw, int rh,
}
}
}
geom_restore = frameGeometry();
setGeometryRestore(frameGeometry());
// No need to send synthetic configure notify event here, either it's sent together
// with geometry change, or there's no need to send it.
// Handling of the real ConfigureRequest event forces sending it, as there it's necessary.
@ -4396,14 +4399,16 @@ void X11Client::changeMaximize(bool horizontal, bool vertical, bool adjust)
sz = size();
if (quickTileMode() == QuickTileMode(QuickTileFlag::None)) {
QRect savedGeometry = geometryRestore();
if (!adjust && !(old_mode & MaximizeVertical)) {
geom_restore.setTop(y());
geom_restore.setHeight(sz.height());
savedGeometry.setTop(y());
savedGeometry.setHeight(sz.height());
}
if (!adjust && !(old_mode & MaximizeHorizontal)) {
geom_restore.setLeft(x());
geom_restore.setWidth(sz.width());
savedGeometry.setLeft(x());
savedGeometry.setWidth(sz.width());
}
setGeometryRestore(savedGeometry);
}
// call into decoration update borders
@ -4435,7 +4440,7 @@ void X11Client::changeMaximize(bool horizontal, bool vertical, bool adjust)
// Conditional quick tiling exit points
if (quickTileMode() != QuickTileMode(QuickTileFlag::None)) {
if (old_mode == MaximizeFull &&
!clientArea.contains(geom_restore.center())) {
!clientArea.contains(geometryRestore().center())) {
// Not restoring on the same screen
// TODO: The following doesn't work for some reason
//quick_tile_mode = QuickTileFlag::None; // And exit quick tile mode manually
@ -4450,13 +4455,13 @@ void X11Client::changeMaximize(bool horizontal, bool vertical, bool adjust)
case MaximizeVertical: {
if (old_mode & MaximizeHorizontal) { // actually restoring from MaximizeFull
if (geom_restore.width() == 0 || !clientArea.contains(geom_restore.center())) {
if (geometryRestore().width() == 0 || !clientArea.contains(geometryRestore().center())) {
// needs placement
plainResize(adjustedSize(QSize(width() * 2 / 3, clientArea.height()), SizeModeFixedH), geom_mode);
Placement::self()->placeSmart(this, clientArea);
} else {
setFrameGeometry(QRect(QPoint(geom_restore.x(), clientArea.top()),
adjustedSize(QSize(geom_restore.width(), clientArea.height()), SizeModeFixedH)), geom_mode);
setFrameGeometry(QRect(QPoint(geometryRestore().x(), clientArea.top()),
adjustedSize(QSize(geometryRestore().width(), clientArea.height()), SizeModeFixedH)), geom_mode);
}
} else {
QRect r(x(), clientArea.top(), width(), clientArea.height());
@ -4470,13 +4475,13 @@ void X11Client::changeMaximize(bool horizontal, bool vertical, bool adjust)
case MaximizeHorizontal: {
if (old_mode & MaximizeVertical) { // actually restoring from MaximizeFull
if (geom_restore.height() == 0 || !clientArea.contains(geom_restore.center())) {
if (geometryRestore().height() == 0 || !clientArea.contains(geometryRestore().center())) {
// needs placement
plainResize(adjustedSize(QSize(clientArea.width(), height() * 2 / 3), SizeModeFixedW), geom_mode);
Placement::self()->placeSmart(this, clientArea);
} else {
setFrameGeometry(QRect(QPoint(clientArea.left(), geom_restore.y()),
adjustedSize(QSize(clientArea.width(), geom_restore.height()), SizeModeFixedW)), geom_mode);
setFrameGeometry(QRect(QPoint(clientArea.left(), geometryRestore().y()),
adjustedSize(QSize(clientArea.width(), geometryRestore().height()), SizeModeFixedW)), geom_mode);
}
} else {
QRect r(clientArea.left(), y(), clientArea.width(), height());
@ -4492,34 +4497,39 @@ void X11Client::changeMaximize(bool horizontal, bool vertical, bool adjust)
QRect restore = frameGeometry();
// when only partially maximized, geom_restore may not have the other dimension remembered
if (old_mode & MaximizeVertical) {
restore.setTop(geom_restore.top());
restore.setBottom(geom_restore.bottom());
restore.setTop(geometryRestore().top());
restore.setBottom(geometryRestore().bottom());
}
if (old_mode & MaximizeHorizontal) {
restore.setLeft(geom_restore.left());
restore.setRight(geom_restore.right());
restore.setLeft(geometryRestore().left());
restore.setRight(geometryRestore().right());
}
if (!restore.isValid()) {
QSize s = QSize(clientArea.width() * 2 / 3, clientArea.height() * 2 / 3);
if (geom_restore.width() > 0)
s.setWidth(geom_restore.width());
if (geom_restore.height() > 0)
s.setHeight(geom_restore.height());
if (geometryRestore().width() > 0) {
s.setWidth(geometryRestore().width());
}
if (geometryRestore().height() > 0) {
s.setHeight(geometryRestore().height());
}
plainResize(adjustedSize(s));
Placement::self()->placeSmart(this, clientArea);
restore = frameGeometry();
if (geom_restore.width() > 0)
restore.moveLeft(geom_restore.x());
if (geom_restore.height() > 0)
restore.moveTop(geom_restore.y());
geom_restore = restore; // relevant for mouse pos calculation, bug #298646
if (geometryRestore().width() > 0) {
restore.moveLeft(geometryRestore().x());
}
if (geometryRestore().height() > 0) {
restore.moveTop(geometryRestore().y());
}
setGeometryRestore(restore); // relevant for mouse pos calculation, bug #298646
}
if (m_geometryHints.hasAspect()) {
restore.setSize(adjustedSize(restore.size(), SizeModeAny));
}
setFrameGeometry(restore, geom_mode);
if (!clientArea.contains(geom_restore.center())) // Not restoring to the same screen
if (!clientArea.contains(geometryRestore().center())) { // Not restoring to the same screen
Placement::self()->place(this, clientArea);
}
info->setState(NET::States(), NET::Max);
updateQuickTileMode(QuickTileFlag::None);
break;

View File

@ -144,7 +144,6 @@ public:
bool isShadeable() const override;
bool isMaximizable() const override;
QRect geometryRestore() const override;
MaximizeMode maximizeMode() const override;
bool isMinimizable() const override;
@ -367,7 +366,6 @@ protected:
void doSetSkipSwitcher() override;
void doSetDemandsAttention() override;
bool belongsToDesktop() const override;
void setGeometryRestore(const QRect &geo) override;
bool doStartMoveResize() override;
void doPerformMoveResize() override;
bool isWaitingForMoveResizeSync() const override;
@ -523,7 +521,6 @@ private:
MaximizeMode max_mode;
QRect m_bufferGeometry = QRect(0, 0, 100, 100);
QRect m_clientGeometry = QRect(0, 0, 100, 100);
QRect geom_restore;
QRect geom_fs_restore;
QTimer* shadeHoverTimer;
xcb_colormap_t m_colormap;
@ -615,16 +612,6 @@ inline ShadeMode X11Client::shadeMode() const
return shade_mode;
}
inline QRect X11Client::geometryRestore() const
{
return geom_restore;
}
inline void X11Client::setGeometryRestore(const QRect &geo)
{
geom_restore = geo;
}
inline MaximizeMode X11Client::maximizeMode() const
{
return max_mode;

View File

@ -569,9 +569,9 @@ void XdgShellClient::doSetGeometry(const QRect &rect)
return;
}
if (m_unmapped && m_geomMaximizeRestore.isEmpty() && !m_frameGeometry.isEmpty()) {
if (m_unmapped && geometryRestore().isEmpty() && !m_frameGeometry.isEmpty()) {
// use first valid geometry as restore geometry
m_geomMaximizeRestore = m_frameGeometry;
setGeometryRestore(m_frameGeometry);
}
if (frameGeometryIsChanged) {
@ -834,7 +834,7 @@ void XdgShellClient::changeMaximize(bool horizontal, bool vertical, bool adjust)
const auto oldQuickTileMode = quickTileMode();
if (quickTileMode() != QuickTileMode(QuickTileFlag::None)) {
if (oldMode == MaximizeFull &&
!clientArea.contains(m_geomMaximizeRestore.center())) {
!clientArea.contains(geometryRestore().center())) {
// Not restoring on the same screen
// TODO: The following doesn't work for some reason
//quick_tile_mode = QuickTileNone; // And exit quick tile mode manually
@ -846,7 +846,7 @@ void XdgShellClient::changeMaximize(bool horizontal, bool vertical, bool adjust)
}
if (m_requestedMaximizeMode == MaximizeFull) {
m_geomMaximizeRestore = oldGeometry;
setGeometryRestore(oldGeometry);
// TODO: Client has more checks
if (options->electricBorderMaximize()) {
updateQuickTileMode(QuickTileFlag::Maximize);
@ -866,19 +866,14 @@ void XdgShellClient::changeMaximize(bool horizontal, bool vertical, bool adjust)
emit quickTileModeChanged();
}
if (m_geomMaximizeRestore.isValid()) {
setFrameGeometry(m_geomMaximizeRestore);
if (geometryRestore().isValid()) {
setFrameGeometry(geometryRestore());
} else {
setFrameGeometry(workspace()->clientArea(PlacementArea, this));
}
}
}
void XdgShellClient::setGeometryRestore(const QRect &geo)
{
m_geomMaximizeRestore = geo;
}
MaximizeMode XdgShellClient::maximizeMode() const
{
return m_maximizeMode;
@ -889,11 +884,6 @@ MaximizeMode XdgShellClient::requestedMaximizeMode() const
return m_requestedMaximizeMode;
}
QRect XdgShellClient::geometryRestore() const
{
return m_geomMaximizeRestore;
}
bool XdgShellClient::noBorder() const
{
if (m_serverDecoration) {

View File

@ -87,7 +87,6 @@ public:
void hideClient(bool hide) override;
MaximizeMode maximizeMode() const override;
MaximizeMode requestedMaximizeMode() const override;
QRect geometryRestore() const override;
bool noBorder() const override;
void setFullScreen(bool set, bool user = true) override;
void setNoBorder(bool set) override;
@ -136,7 +135,6 @@ protected:
bool belongsToDesktop() const override;
Layer layerForDock() const override;
void changeMaximize(bool horizontal, bool vertical, bool adjust) override;
void setGeometryRestore(const QRect &geo) override;
void doResizeSync() override;
bool acceptsFocus() const override;
void doMinimize() override;
@ -225,7 +223,6 @@ private:
bool m_closing = false;
quint32 m_windowId = 0;
bool m_unmapped = true;
QRect m_geomMaximizeRestore; // size and position of the window before it was set to maximize
NET::WindowType m_windowType = NET::Normal;
QPointer<KWayland::Server::PlasmaShellSurfaceInterface> m_plasmaShellSurface;
QPointer<KWayland::Server::AppMenuInterface> m_appMenuInterface;