remove moveResizeMaximized option

REVIEW: 103948
BUG: 91703
BUG: 299245
FIXED-IN: 4.11

- The setting is ignored, the decoration always gets a "true" for it
- moving a maximized window requires breaking a "strong" snap (1/16 of screen height - unless you use quick maximization)
- all snapping is done towards the client, not the frame
- QuickTileMode is exported to the decoration (just as the maximizeMode) so that it can fix the bordersize alongside that.
This commit is contained in:
Thomas Lübking 2013-02-17 01:56:01 +01:00
parent 903c95dd52
commit 6fb5353cab
14 changed files with 144 additions and 75 deletions

View file

@ -43,6 +43,7 @@ Bridge::Bridge(Client* cl)
BRIDGE_HELPER(bool, isCloseable, , , const)
BRIDGE_HELPER(bool, isMaximizable, , , const)
BRIDGE_HELPER(Bridge::MaximizeMode, maximizeMode, , , const)
BRIDGE_HELPER(Bridge::QuickTileMode, quickTileMode, , , const)
BRIDGE_HELPER(bool, isMinimizable, , , const)
BRIDGE_HELPER(bool, providesContextHelp, , , const)
BRIDGE_HELPER(int, desktop, , , const)

View file

@ -36,6 +36,7 @@ public:
virtual bool isCloseable() const;
virtual bool isMaximizable() const;
virtual MaximizeMode maximizeMode() const;
virtual QuickTileMode quickTileMode() const;
virtual bool isMinimizable() const;
virtual bool providesContextHelp() const;
virtual int desktop() const;

View file

@ -638,8 +638,8 @@ void Client::updateFrameExtents()
/**
* Resizes the decoration, and makes sure the decoration widget gets resize event
* even if the size hasn't changed. This is needed to make sure the decoration
* re-layouts (e.g. when options()->moveResizeMaximizedWindows() changes,
* the decoration may turn on/off some borders, but the actual size
* re-layouts (e.g. when maximization state changes,
* the decoration may alter some borders, but the actual size
* of the decoration stays the same).
*/
void Client::resizeDecoration(const QSize& s)
@ -2425,6 +2425,16 @@ QRect Client::decorationRect() const
}
}
KDecorationDefines::Position Client::titlebarPosition()
{
Position titlePos = PositionCenter; // PositionTop is returned by the default implementation
// this will hint errors in the metaobject usage ;-)
if (decoration)
QMetaObject::invokeMethod(decoration, "titlebarPosition", Qt::DirectConnection,
Q_RETURN_ARG(KDecorationDefines::Position, titlePos));
return titlePos;
}
void Client::updateFirstInTabBox()
{
// TODO: move into KWindowInfo

View file

@ -615,6 +615,8 @@ public:
bool decorationHasAlpha() const;
Position titlebarPosition();
enum CoordinateMode {
DecorationRelative, // Relative to the top left corner of the decoration
WindowRelative // Relative to the top left corner of the window
@ -1156,9 +1158,9 @@ inline Client::MaximizeMode Client::maximizeMode() const
return max_mode;
}
inline KWin::QuickTileMode Client::quickTileMode() const
inline Client::QuickTileMode Client::quickTileMode() const
{
return (KWin::QuickTileMode)quick_tile_mode;
return (Client::QuickTileMode)quick_tile_mode;
}
inline bool Client::skipTaskbar(bool from_outside) const

View file

@ -379,7 +379,12 @@ QPoint Workspace::adjustClientPosition(Client* c, QPoint pos, bool unrestricted,
//CT 16mar98, 27May98 - magics: BorderSnapZone, WindowSnapZone
//CT adapted for kwin on 25Nov1999
//aleXXX 02Nov2000 added second snapping mode
if (options->windowSnapZone() || options->borderSnapZone() || options->centerSnapZone()) {
int borderSnapZone = options->borderSnapZone();
if (c->maximizeMode() != MaximizeRestore)
borderSnapZone = qMax(borderSnapZone + 2, clientArea(ScreenArea, c).height() / 16);
if (options->windowSnapZone() || borderSnapZone || options->centerSnapZone()) {
const bool sOWO = options->isSnapOnlyWhenOverlapping();
const QRect maxRect = clientArea(MovementArea, pos + c->rect().center(), c->desktop());
const int xmin = maxRect.left();
@ -394,6 +399,19 @@ QPoint Workspace::adjustClientPosition(Client* c, QPoint pos, bool unrestricted,
const int rx(cx + cw);
const int ry(cy + ch); //these don't change
// only enforce large snap while we're on a corresponding border
if (c->maximizeMode() != MaximizeRestore) {
QRect geo = c->geometry();
if (c->maximizeMode() & MaximizeVertical && geo.y() != maxRect.top() && geo.bottom() != maxRect.bottom()) {
borderSnapZone = options->borderSnapZone();
}
if (c->maximizeMode() & MaximizeHorizontal && geo.x() != maxRect.left() && geo.right() != maxRect.right()) {
borderSnapZone = options->borderSnapZone();
}
if (!(borderSnapZone || options->windowSnapZone() || options->centerSnapZone())) // ma have changed
return pos;
}
int nx(cx), ny(cy); //buffers
int deltaX(xmax);
int deltaY(ymax); //minimum distance to other clients
@ -401,24 +419,39 @@ QPoint Workspace::adjustClientPosition(Client* c, QPoint pos, bool unrestricted,
int lx, ly, lrx, lry; //coords and size for the comparison client, l
// border snap
int snap = options->borderSnapZone() * snapAdjust; //snap trigger
int snap = borderSnapZone * snapAdjust; //snap trigger
if (snap) {
const QPoint cp = c->clientPos();
const QSize cs = c->geometry().size() - c->clientSize();
int padding[4] = { cp.x(), cs.width() - cp.x(), cp.y(), cs.height() - cp.y() };
// snap to titlebar
Position titlePos = c->titlebarPosition();
if (titlePos == PositionLeft)
padding[0] = 0;
if (titlePos == PositionRight)
padding[1] = 0;
if (titlePos == PositionTop)
padding[2] = 0;
if (titlePos == PositionBottom)
padding[3] = 0;
if ((sOWO ? (cx < xmin) : true) && (qAbs(xmin - cx) < snap)) {
deltaX = xmin - cx;
nx = xmin;
deltaX = xmin - (cx - padding[0]);
nx = xmin - padding[0];
}
if ((sOWO ? (rx > xmax) : true) && (qAbs(rx - xmax) < snap) && (qAbs(xmax - rx) < deltaX)) {
deltaX = rx - xmax;
nx = xmax - cw;
deltaX = rx + padding[1] - xmax;
nx = xmax - cw + padding[1];
}
if ((sOWO ? (cy < ymin) : true) && (qAbs(ymin - cy) < snap)) {
deltaY = ymin - cy;
ny = ymin;
deltaY = ymin - (cy - padding[2]);
ny = ymin - padding[2];
}
if ((sOWO ? (ry > ymax) : true) && (qAbs(ry - ymax) < snap) && (qAbs(ymax - ry) < deltaY)) {
deltaY = ry - ymax;
ny = ymax - ch;
deltaY = ry + padding[3] - ymax;
ny = ymax - ch + padding[3];
}
}
@ -500,7 +533,7 @@ QPoint Workspace::adjustClientPosition(Client* c, QPoint pos, bool unrestricted,
deltaY = diffY;
nx = (xmin + xmax) / 2 - cw / 2;
ny = (ymin + ymax) / 2 - ch / 2;
} else if (options->borderSnapZone()) {
} else if (borderSnapZone) {
// Enhance border snap
if ((nx == xmin || nx == xmax - cw) && diffY < snap && diffY < deltaY) {
// Snap to vertical center on screen edge
@ -1205,7 +1238,6 @@ void Client::checkOffscreenPosition(QRect* geom, const QRect& screenArea)
QSize Client::adjustedSize(const QSize& frame, Sizemode mode) const
{
// first, get the window size for the given frame size s
QSize wsize(frame.width() - (border_left + border_right),
frame.height() - (border_top + border_bottom));
if (wsize.isEmpty())
@ -1762,8 +1794,6 @@ bool Client::isMovable() const
return false;
if (isSpecialWindow() && !isSplash() && !isToolbar()) // allow moving of splashscreens :)
return false;
if (maximizeMode() == MaximizeFull && !options->moveResizeMaximizedWindows())
return false;
if (rules()->checkPosition(invalidPoint) != invalidPoint) // forced position
return false;
return true;
@ -1792,8 +1822,6 @@ bool Client::isResizable() const
return false;
if (isSpecialWindow() || isSplash() || isToolbar())
return false;
if (maximizeMode() == MaximizeFull && !options->moveResizeMaximizedWindows())
return isMove(); // for quick tiling - maxmode will be unset if we tile
if (rules()->checkSize(QSize()).isValid()) // forced size
return false;
@ -2201,11 +2229,7 @@ void Client::changeMaximize(bool vertical, bool horizontal, bool adjust)
Notify::raise(Notify::UnMaximize);
}
ForceGeometry_t geom_mode = NormalGeometrySet;
if (decoration != NULL) { // decorations may turn off some borders when maximized
if (checkBorderSizes(false)) // only query, don't resize
geom_mode = ForceGeometrySet;
}
const ForceGeometry_t geom_mode = decoration && checkBorderSizes(false) ? ForceGeometrySet : NormalGeometrySet;
// Conditional quick tiling exit points
if (quick_tile_mode != QuickTileNone) {
@ -2553,17 +2577,7 @@ bool Client::startMoveResize()
// the top of the screen. When the setting is disabled then doing so is confusing.
bool fakeMove = false;
if (!isFullScreen()) { // xinerama move across screens -> window is FS, everything else is secondary and untouched
if (maximizeMode() != MaximizeRestore &&
(maximizeMode() != MaximizeFull || options->moveResizeMaximizedWindows())) {
// allow moveResize, but unset maximization state in resize case
if (mode != PositionCenter) { // means "isResize()" but moveResizeMode = true is set below
if (maximizeMode() == MaximizeFull) { // partial is cond. reset in finishMoveResize
geom_restore = geometry(); // "restore" to current geometry
setMaximize(false, false);
}
} else if (quick_tile_mode != QuickTileNone) // no longer now - we move, resize is handled below
setQuickTileMode(QuickTileNone); // otherwise we mess every second tile, bug #303937
} else if ((maximizeMode() == MaximizeFull && options->electricBorderMaximize()) ||
if ((maximizeMode() == MaximizeFull && options->electricBorderMaximize()) ||
(quick_tile_mode != QuickTileNone && isMovable() && mode == PositionCenter)) {
// Exit quick tile mode when the user attempts to move a tiled window, cannot use isMove() yet
const QRect before = geometry();
@ -2572,6 +2586,15 @@ bool Client::startMoveResize()
moveOffset = QPoint(double(moveOffset.x()) / double(before.width()) * double(geom_restore.width()),
double(moveOffset.y()) / double(before.height()) * double(geom_restore.height()));
fakeMove = true;
} else if (maximizeMode() != MaximizeRestore) {
// allow moveResize, but unset maximization state in resize case
if (mode != PositionCenter) { // means "isResize()" but moveResizeMode = true is set below
if (maximizeMode() == MaximizeFull) { // partial is cond. reset in finishMoveResize
geom_restore = geometry(); // "restore" to current geometry
setMaximize(false, false);
}
} else if (quick_tile_mode != QuickTileNone) // no longer now - we move, resize is handled below
setQuickTileMode(QuickTileNone); // otherwise we mess every second tile, bug #303937
}
}
@ -3069,7 +3092,7 @@ void Client::setElectricBorderMode(QuickTileMode mode)
electricMode = mode;
}
QuickTileMode Client::electricBorderMode() const
Client::QuickTileMode Client::electricBorderMode() const
{
return electricMode;
}
@ -3145,10 +3168,13 @@ void Client::setQuickTileMode(QuickTileMode mode, bool keyboard)
setMaximize(false, false);
// Temporary, so the maximize code doesn't get all confused
quick_tile_mode = QuickTileNone;
if (mode != QuickTileNone)
setGeometry(electricBorderMaximizeGeometry(keyboard ? geometry().center() : cursorPos(), desktop()));
if (mode != QuickTileNone) {
quick_tile_mode = mode;
// decorations may turn off some borders when tiled
const ForceGeometry_t geom_mode = decoration && checkBorderSizes(false) ? ForceGeometrySet : NormalGeometrySet;
quick_tile_mode = QuickTileNone; // Temporary, so the maximize code doesn't get all confused
setGeometry(electricBorderMaximizeGeometry(keyboard ? geometry().center() : cursorPos(), desktop()), geom_mode);
}
// Store the mode change
quick_tile_mode = mode;
@ -3164,7 +3190,9 @@ void Client::setQuickTileMode(QuickTileMode mode, bool keyboard)
// Untiling, so just restore geometry, and we're done.
if (!geom_restore.isValid()) // invalid if we started maximized and wait for placement
geom_restore = geometry();
setGeometry(geom_restore);
// decorations may turn off some borders when tiled
const ForceGeometry_t geom_mode = decoration && checkBorderSizes(false) ? ForceGeometrySet : NormalGeometrySet;
setGeometry(geom_restore, geom_mode);
checkWorkspacePosition(); // Just in case it's a different screen
return;
} else {
@ -3213,10 +3241,14 @@ void Client::setQuickTileMode(QuickTileMode mode, bool keyboard)
geom_restore = geometry();
}
if (mode != QuickTileNone) {
quick_tile_mode = mode;
// decorations may turn off some borders when tiled
const ForceGeometry_t geom_mode = decoration && checkBorderSizes(false) ? ForceGeometrySet : NormalGeometrySet;
// Temporary, so the maximize code doesn't get all confused
quick_tile_mode = QuickTileNone;
if (mode != QuickTileNone)
setGeometry(electricBorderMaximizeGeometry(whichScreen, desktop()));
setGeometry(electricBorderMaximizeGeometry(whichScreen, desktop()), geom_mode);
}
// Store the mode change
quick_tile_mode = mode;

View file

@ -214,6 +214,11 @@ KDecoration::MaximizeMode KDecorationPreviewBridge::maximizeMode() const
return KDecoration::MaximizeRestore;
}
KDecoration::QuickTileMode KDecorationPreviewBridge::quickTileMode() const
{
return KDecoration::QuickTileNone;
}
bool KDecorationPreviewBridge::isMinimizable() const
{
return true;

View file

@ -68,6 +68,7 @@ public:
virtual bool isCloseable() const;
virtual bool isMaximizable() const;
virtual MaximizeMode maximizeMode() const;
virtual QuickTileMode quickTileMode() const;
virtual bool isMinimizable() const;
virtual bool providesContextHelp() const;
virtual int desktop() const;

View file

@ -136,6 +136,11 @@ KDecoration::MaximizeMode KDecoration::maximizeMode() const
return bridge_->maximizeMode();
}
KDecoration::QuickTileMode KDecoration::quickTileMode() const
{
return bridge_->quickTileMode();
}
bool KDecoration::isMinimizable() const
{
return bridge_->isMinimizable();
@ -520,6 +525,11 @@ QRegion KDecoration::region(KDecorationDefines::Region)
return QRegion();
}
KDecorationDefines::Position KDecoration::titlebarPosition()
{
return PositionTop;
}
QString KDecorationDefines::tabDragMimeType()
{
return "text/ClientGroupItem";
@ -612,7 +622,8 @@ KDecorationOptions::BorderSize KDecorationOptions::preferredBorderSize(KDecorati
bool KDecorationOptions::moveResizeMaximizedWindows() const
{
return d->move_resize_maximized_windows;
// TODO KF5: remove function with API break
return false;
}
KDecorationDefines::WindowOperation KDecorationOptions::operationMaxButtonClick(Qt::MouseButtons button) const

View file

@ -98,6 +98,19 @@ public:
MaximizeFull = MaximizeVertical | MaximizeHorizontal
};
enum QuickTileFlag {
QuickTileNone = 0,
QuickTileLeft = 1,
QuickTileRight = 1<<1,
QuickTileTop = 1<<2,
QuickTileBottom = 1<<3,
QuickTileHorizontal = QuickTileLeft|QuickTileRight,
QuickTileVertical = QuickTileTop|QuickTileBottom,
QuickTileMaximize = QuickTileLeft|QuickTileRight|QuickTileTop|QuickTileBottom
};
Q_DECLARE_FLAGS(QuickTileMode, QuickTileFlag)
enum WindowOperation {
MaximizeOp = 5000,
RestoreOp,
@ -419,11 +432,9 @@ public:
*/
BorderSize preferredBorderSize(KDecorationFactory* factory) const;
/*
* When this functions returns false, moving and resizing of maximized windows
* is not allowed, and therefore the decoration is allowed to turn off (some of)
* its borders.
* The changed flags for this setting is SettingButtons.
/**
* This functions returns false
* @deprecated
*/
bool moveResizeMaximizedWindows() const;
@ -510,6 +521,13 @@ public:
/**
* Returns @a true if the decorated window can be minimized by the user.
*/
/**
* Returns the current quicktiling mode of the decorated window.
* (window is places into one of the corners or edges)
*/
QuickTileMode quickTileMode() const;
bool isMinimizable() const;
/**
* Return @a true if the decorated window can show context help
@ -930,6 +948,13 @@ public:
* Ungrabs X server (if the number of ungrab attempts matches the number of grab attempts).
*/
void ungrabXServer();
public: // invokables; runtime resolution
/**
* reimplement this invokable to signal the core where the titlebar is (usually PositionTop)
*/
Q_INVOKABLE KDecorationDefines::Position titlebarPosition();
public Q_SLOTS:
// requests from decoration
@ -1189,4 +1214,6 @@ inline int KDecoration::height() const
/** @} */
Q_DECLARE_OPERATORS_FOR_FLAGS(KDecoration::QuickTileMode)
#endif

View file

@ -38,7 +38,6 @@ KDecorationOptionsPrivate::KDecorationOptionsPrivate()
, show_tooltips(true)
, border_size(BorderNormal)
, cached_border_size(BordersCount) // invalid
, move_resize_maximized_windows(true)
, opMaxButtonRightClick(MaximizeOp)
, opMaxButtonMiddleClick(VMaximizeOp)
, opMaxButtonLeftClick(HMaximizeOp)
@ -193,12 +192,6 @@ unsigned long KDecorationOptionsPrivate::updateSettings(KConfig* config)
changed |= SettingBorder;
cached_border_size = BordersCount; // invalid
KConfigGroup windowsConfig(config, "Windows");
bool old_move_resize_maximized_windows = move_resize_maximized_windows;
move_resize_maximized_windows = windowsConfig.readEntry("MoveResizeMaximizedWindows", false);
if (old_move_resize_maximized_windows != move_resize_maximized_windows)
changed |= SettingBorder;
// destroy cached values
int i;
for (i = 0; i < NUM_COLORS * 2; ++i) {

View file

@ -50,7 +50,6 @@ public:
bool custom_button_positions;
bool show_tooltips;
BorderSize border_size, cached_border_size;
bool move_resize_maximized_windows;
WindowOperation opMaxButtonRightClick;
WindowOperation opMaxButtonMiddleClick;
WindowOperation opMaxButtonLeftClick;

View file

@ -42,6 +42,7 @@ public:
virtual bool isCloseable() const = 0;
virtual bool isMaximizable() const = 0;
virtual MaximizeMode maximizeMode() const = 0;
virtual QuickTileMode quickTileMode() const = 0;
virtual bool isMinimizable() const = 0;
virtual bool providesContextHelp() const = 0;
virtual int desktop() const = 0;

View file

@ -84,19 +84,6 @@ enum ElectricBorder {
ElectricNone
};
enum QuickTileFlag {
QuickTileNone = 0,
QuickTileLeft = 1,
QuickTileRight = 1<<1,
QuickTileTop = 1<<2,
QuickTileBottom = 1<<3,
QuickTileHorizontal = QuickTileLeft|QuickTileRight,
QuickTileVertical = QuickTileTop|QuickTileBottom,
QuickTileMaximize = QuickTileLeft|QuickTileRight|QuickTileTop|QuickTileBottom
};
Q_DECLARE_FLAGS(QuickTileMode, QuickTileFlag)
// TODO: Hardcoding is bad, need to add some way of registering global actions to these.
// When designing the new system we must keep in mind that we have conditional actions
// such as "only when moving windows" desktop switching that the current global action
@ -211,6 +198,4 @@ private:
} // namespace
Q_DECLARE_OPERATORS_FOR_FLAGS(KWin::QuickTileMode)
#endif

View file

@ -971,6 +971,7 @@ inline bool Workspace::decorationSupportsBlurBehind() const
return mgr->factory()->supports(AbilityUsesBlurBehind);
}
} // namespace
#endif