stage one, call martin

This commit is contained in:
Thomas Lübking 2011-03-07 22:31:44 +01:00
parent dd19f5e1a7
commit 0b1599680d
6 changed files with 145 additions and 281 deletions

View file

@ -258,12 +258,11 @@ public:
void resizeWithChecks(int w, int h, ForceGeometry_t force = NormalGeometrySet);
void resizeWithChecks(const QSize& s, ForceGeometry_t force = NormalGeometrySet);
void keepInArea(QRect area, bool partial = false);
void setElectricBorderMode(ElectricMaximizingMode mode);
ElectricMaximizingMode electricBorderMode() const;
void setElectricBorderMode(QuickTileMode mode);
QuickTileMode electricBorderMode() const;
void setElectricBorderMaximizing(bool maximizing);
bool isElectricBorderMaximizing() const;
QRect electricBorderMaximizeGeometry();
QRect electricBorderMaximizeGeometry(QPoint pos, int desktop);
QSize sizeForClientSize(const QSize&, Sizemode mode = SizemodeAny, bool noframe = false) const;
/** Set the quick tile mode ("snap") of this window.
@ -598,7 +597,7 @@ private:
/** The quick tile mode of this window.
*/
QuickTileMode quick_tile_mode;
int quick_tile_mode;
QRect geom_pretile;
void readTransient();
@ -708,7 +707,7 @@ private:
TabBox::TabBoxClientImpl* m_tabBoxClient;
bool electricMaximizing;
ElectricMaximizingMode electricMode;
QuickTileMode electricMode;
friend bool performTransiencyCheck();
friend class SWrapper::Client;

View file

@ -1334,55 +1334,32 @@ static bool waitingMotionEvent()
// Checks if the mouse cursor is near the edge of the screen and if so activates quick tiling or maximization
void Client::checkQuickTilingMaximizationZones(int xroot, int yroot)
{
QuickTileMode mode = QuickTileNone;
foreach (Kephal::Screen * screen, Kephal::Screens::self()->screens()) {
if (screen->geom().contains(QPoint(xroot, yroot))) {
if (options->electricBorderTiling() &&
xroot <= screen->geom().x() + 20 &&
yroot > screen->geom().y() + screen->geom().height() / 4 &&
yroot < screen->geom().y() + screen->geom().height() - screen->geom().height() / 4) {
setElectricBorderMode(ElectricLeftMode);
setElectricBorderMaximizing(true);
return;
} else if (options->electricBorderTiling() &&
xroot <= screen->geom().x() + 20 &&
yroot <= screen->geom().y() + screen->geom().height() / 4) {
setElectricBorderMode(ElectricTopLeftMode);
setElectricBorderMaximizing(true);
return;
} else if (options->electricBorderTiling() &&
xroot <= screen->geom().x() + 20 &&
yroot >= screen->geom().y() + screen->geom().height() - screen->geom().height() / 4) {
setElectricBorderMode(ElectricBottomLeftMode);
setElectricBorderMaximizing(true);
return;
} else if (options->electricBorderTiling() &&
xroot >= screen->geom().x() + screen->geom().width() - 20 &&
yroot > screen->geom().y() + screen->geom().height() / 4 &&
yroot < screen->geom().y() + screen->geom().height() - screen->geom().height() / 4) {
setElectricBorderMode(ElectricRightMode);
setElectricBorderMaximizing(true);
return;
} else if (options->electricBorderTiling() &&
xroot >= screen->geom().x() + screen->geom().width() - 20 &&
yroot <= screen->geom().y() + screen->geom().height() / 4) {
setElectricBorderMode(ElectricTopRightMode);
setElectricBorderMaximizing(true);
return;
} else if (options->electricBorderTiling() &&
xroot >= screen->geom().x() + screen->geom().width() - 20 &&
yroot >= screen->geom().y() + screen->geom().height() - screen->geom().height() / 4) {
setElectricBorderMode(ElectricBottomRightMode);
setElectricBorderMaximizing(true);
return;
} else if (options->electricBorderMaximize() &&
yroot <= screen->geom().y() + 5 && isMaximizable()) {
setElectricBorderMode(ElectricMaximizeMode);
setElectricBorderMaximizing(true);
return;
}
const QRect &area = screen->geom();
if (!area.contains(QPoint(xroot, yroot)))
continue;
if (options->electricBorderTiling()) {
if (xroot <= screen->geom().x() + 20)
mode |= QuickTileLeft;
else if (xroot >= area.x() + area.width() - 20)
mode |= QuickTileRight;
}
if (mode != QuickTileNone) {
if (yroot <= area.y() + area.height() / 4)
mode |= QuickTileTop;
else if (yroot >= area.y() + area.height() - area.height() / 4)
mode |= QuickTileBottom;
} else if (options->electricBorderMaximize() && yroot <= area.y() + 5 && isMaximizable())
mode = QuickTileMaximize;
break; // no point in checking other screens to contain this... "point"...
}
setElectricBorderMaximizing(false);
setElectricBorderMode(mode);
setElectricBorderMaximizing(mode != QuickTileNone);
}
// return value matters only when filtering events before decoration gets them

View file

@ -2568,31 +2568,24 @@ bool Client::startMoveResize()
move_resize_grab_window = None;
return false;
}
if (maximizeMode() == MaximizeFull && options->electricBorderMaximize() &&
!options->moveResizeMaximizedWindows()) {
// If we have quick maximization enabled then it's safe to automatically restore windows
// when starting a move as the user can undo their action by moving the window back to
// the top of the screen. When the setting is disabled then doing so is confusing.
// If we have quick maximization enabled then it's safe to automatically restore windows
// when starting a move as the user can undo their action by moving the window back to
// the top of the screen. When the setting is disabled then doing so is confusing.
if ((maximizeMode() == MaximizeFull && options->electricBorderMaximize() &&
!options->moveResizeMaximizedWindows()) ||
// Exit quick tile mode when the user attempts to move a tiled window, cannot use isMove() yet
(quick_tile_mode != QuickTileNone && isMovable() && mode == PositionCenter)) {
const QRect before = geometry();
setMaximize(false, false);
setQuickTileMode(QuickTileNone);
// Move the window so it's under the cursor
moveOffset = QPoint(
double(moveOffset.x()) / double(before.width()) * double(geom_restore.width()),
double(moveOffset.y()) / double(before.height()) * double(geom_restore.height())
);
}
// if (maximizeMode() != MaximizeRestore)
// resetMaximize(); // TODO: I have no idea what this does... Is it needed?
if (quick_tile_mode != QuickTileNone && isMovable() && mode == PositionCenter) { // Cannot use isMove() yet
// Exit quick tile mode when the user attempts to move a tiled window
const QRect before = geometry();
setQuickTileMode(QuickTileNone);
// Move the window so it's under the cursor
moveOffset = QPoint(
double(moveOffset.x()) / double(before.width()) * double(geom_pretile.width()),
double(moveOffset.y()) / double(before.height()) * double(geom_pretile.height())
);
}
if (quick_tile_mode != QuickTileNone && mode != PositionCenter) { // Cannot use isResize() yet
// Exit quick tile mode when the user attempts to resize a tiled window
quick_tile_mode = QuickTileNone; // Do so without restoring original geometry
@ -2624,6 +2617,37 @@ bool Client::startMoveResize()
return true;
}
static ElectricBorder electricBorderFromMode(QuickTileMode mode)
{
// special case, currently maxmizing is done from the electric top corner
if (mode == QuickTileMaximize)
return ElectricTop;
// sanitize the mode, ie. simplify "invalid" combinations
if ((mode & QuickTileHorizontal) == QuickTileHorizontal)
mode &= ~QuickTileHorizontal;
if ((mode & QuickTileVertical) == QuickTileVertical)
mode &= ~QuickTileVertical;
if (mode == QuickTileLeft)
return ElectricLeft;
if (mode == QuickTileRight)
return ElectricRight;
if (mode == (QuickTileTop|QuickTileLeft))
return ElectricTopLeft;
if (mode == (QuickTileTop|QuickTileRight))
return ElectricTopRight;
if (mode == (QuickTileBottom|QuickTileLeft))
return ElectricBottomLeft;
if (mode == (QuickTileBottom|QuickTileRight))
return ElectricBottomRight;
if (mode == QuickTileTop)
return ElectricTop;
if (mode == QuickTileBottom)
return ElectricBottom;
return ElectricNone;
}
void Client::finishMoveResize(bool cancel)
{
// store for notification
@ -2648,78 +2672,13 @@ void Client::finishMoveResize(bool cancel)
if (isElectricBorderMaximizing()) {
cancel = true;
}
if (isElectricBorderMaximizing()) {
switch(electricMode) {
case ElectricMaximizeMode:
if (maximizeMode() == MaximizeFull)
setMaximize(false, false);
else
setMaximize(true, true);
workspace()->restoreElectricBorderSize(ElectricTop);
break;
case ElectricLeftMode:
setQuickTileMode(QuickTileLeft);
workspace()->restoreElectricBorderSize(ElectricLeft);
break;
case ElectricRightMode:
setQuickTileMode(QuickTileRight);
workspace()->restoreElectricBorderSize(ElectricRight);
break;
case ElectricTopLeftMode:
setQuickTileMode(QuickTileTopLeft);
workspace()->restoreElectricBorderSize(ElectricLeft);
break;
case ElectricTopRightMode:
setQuickTileMode(QuickTileTopRight);
workspace()->restoreElectricBorderSize(ElectricRight);
break;
case ElectricBottomLeftMode:
setQuickTileMode(QuickTileBottomLeft);
workspace()->restoreElectricBorderSize(ElectricLeft);
break;
case ElectricBottomRightMode:
setQuickTileMode(QuickTileBottomRight);
workspace()->restoreElectricBorderSize(ElectricRight);
break;
}
electricMaximizing = false;
workspace()->hideElectricBorderWindowOutline();
}
if (isElectricBorderMaximizing()) {
switch(electricMode) {
case ElectricMaximizeMode:
if (maximizeMode() == MaximizeFull)
setMaximize(false, false);
else
setMaximize(true, true);
workspace()->restoreElectricBorderSize(ElectricTop);
break;
case ElectricLeftMode:
setQuickTileMode(QuickTileLeft);
workspace()->restoreElectricBorderSize(ElectricLeft);
break;
case ElectricRightMode:
setQuickTileMode(QuickTileRight);
workspace()->restoreElectricBorderSize(ElectricRight);
break;
case ElectricTopLeftMode:
setQuickTileMode(QuickTileTopLeft);
workspace()->restoreElectricBorderSize(ElectricLeft);
break;
case ElectricTopRightMode:
setQuickTileMode(QuickTileTopRight);
workspace()->restoreElectricBorderSize(ElectricRight);
break;
case ElectricBottomLeftMode:
setQuickTileMode(QuickTileBottomLeft);
workspace()->restoreElectricBorderSize(ElectricLeft);
break;
case ElectricBottomRightMode:
setQuickTileMode(QuickTileBottomRight);
workspace()->restoreElectricBorderSize(ElectricRight);
break;
}
setQuickTileMode(electricMode);
const ElectricBorder border = electricBorderFromMode(electricMode);
if (border == ElectricNone)
kDebug(1212) << "invalid electric mode" << electricMode << "leading to invalid array acces,\
this should not have happened!";
else
workspace()->restoreElectricBorderSize(border);
electricMaximizing = false;
workspace()->hideElectricBorderWindowOutline();
}
@ -3130,12 +3089,19 @@ void Client::syncTimeout()
performMoveResize();
}
void Client::setElectricBorderMode(ElectricMaximizingMode mode)
void Client::setElectricBorderMode(QuickTileMode mode)
{
if (mode != QuickTileMaximize) {
// sanitize the mode, ie. simplify "invalid" combinations
if ((mode & QuickTileHorizontal) == QuickTileHorizontal)
mode &= ~QuickTileHorizontal;
if ((mode & QuickTileVertical) == QuickTileVertical)
mode &= ~QuickTileVertical;
}
electricMode = mode;
}
ElectricMaximizingMode Client::electricBorderMode() const
QuickTileMode Client::electricBorderMode() const
{
return electricMode;
}
@ -3154,48 +3120,25 @@ void Client::setElectricBorderMaximizing(bool maximizing)
workspace()->hideElectricBorderWindowOutline();
}
QRect Client::electricBorderMaximizeGeometry()
QRect Client::electricBorderMaximizeGeometry(QPoint pos, int desktop)
{
QRect ret;
switch(electricMode) {
case ElectricMaximizeMode: {
if (electricMode == QuickTileMaximize) {
if (maximizeMode() == MaximizeFull)
ret = geometryRestore();
return geometryRestore();
else
ret = workspace()->clientArea(MaximizeArea, cursorPos() , workspace()->currentDesktop());
break;
}
case ElectricLeftMode: {
QRect max = workspace()->clientArea(MaximizeArea, cursorPos() , workspace()->currentDesktop());
ret = QRect(max.x(), max.y(), max.width() / 2, max.height());
break;
}
case ElectricRightMode: {
QRect max = workspace()->clientArea(MaximizeArea, cursorPos() , workspace()->currentDesktop());
ret = QRect(max.x() + max.width() / 2, max.y(), max.width() / 2, max.height());
break;
}
case ElectricTopLeftMode: {
QRect max = workspace()->clientArea(MaximizeArea, cursorPos(), workspace()->currentDesktop());
ret = QRect(max.x(), max.y(), max.width() / 2, max.height() / 2);
break;
}
case ElectricTopRightMode: {
QRect max = workspace()->clientArea(MaximizeArea, cursorPos(), workspace()->currentDesktop());
ret = QRect(max.x() + max.width() / 2, max.y(), max.width() / 2, max.height() / 2);
break;
}
case ElectricBottomLeftMode: {
QRect max = workspace()->clientArea(MaximizeArea, cursorPos(), workspace()->currentDesktop());
ret = QRect(max.x(), max.y() + max.height() / 2, max.width() / 2, max.height() / 2);
break;
}
case ElectricBottomRightMode: {
QRect max = workspace()->clientArea(MaximizeArea, cursorPos(), workspace()->currentDesktop());
ret = QRect(max.x() + max.width() / 2, max.y() + max.height() / 2, max.width() / 2, max.height() / 2);
break;
}
return workspace()->clientArea(MaximizeArea, pos, desktop);
}
QRect ret = workspace()->clientArea(MaximizeArea, pos, desktop);
if (electricMode & QuickTileLeft)
ret.setRight(ret.left()+ret.width()/2);
else if (electricMode & QuickTileRight)
ret.setLeft(ret.right()-ret.width()/2);
if (electricMode & QuickTileTop)
ret.setBottom(ret.top()+ret.height()/2);
else if (electricMode & QuickTileBottom)
ret.setTop(ret.bottom()-ret.height()/2);
return ret;
}
@ -3205,50 +3148,35 @@ void Client::setQuickTileMode(QuickTileMode mode, bool keyboard)
if (!isResizable() && maximizeMode() != MaximizeFull)
return;
if (mode == QuickTileMaximize)
{
quick_tile_mode = QuickTileNone;
if (maximizeMode() == MaximizeFull)
setMaximize(false, false);
else
{
setMaximize(true, true);
quick_tile_mode = QuickTileMaximize;
}
return;
}
// sanitize the mode, ie. simplify "invalid" combinations
if ((mode & QuickTileHorizontal) == QuickTileHorizontal)
mode &= ~QuickTileHorizontal;
if ((mode & QuickTileVertical) == QuickTileVertical)
mode &= ~QuickTileVertical;
setElectricBorderMode(mode); // used by ::electricBorderMaximizeGeometry(.)
// restore from maximized so that it is possible to tile maximized windows with one hit or by dragging
if (maximizeMode() == MaximizeFull) {
setMaximize(false, false);
QPoint whichScreen = keyboard ? geometry().center() : cursorPos();
// DUPLICATED BELOW: --------------------------------------------------
// Temporary, so the maximize code doesn't get all confused
quick_tile_mode = QuickTileNone;
// Do the actual tile.
switch(mode) {
case QuickTileLeft: {
QRect max = workspace()->clientArea(MaximizeArea, whichScreen, desktop());
setGeometry(QRect(max.x(), max.y(), max.width() / 2, max.height()));
break;
}
case QuickTileRight: {
QRect max = workspace()->clientArea(MaximizeArea, whichScreen, desktop());
setGeometry(QRect(max.x() + max.width() / 2, max.y(), max.width() / 2, max.height()));
break;
}
case QuickTileTopLeft: {
QRect max = workspace()->clientArea(MaximizeArea, whichScreen, desktop());
setGeometry(QRect(max.x(), max.y(), max.width() / 2, max.height() / 2));
break;
}
case QuickTileTopRight: {
QRect max = workspace()->clientArea(MaximizeArea, whichScreen, desktop());
setGeometry(QRect(max.x() + max.width() / 2, max.y(), max.width() / 2, max.height() / 2));
break;
}
case QuickTileBottomLeft: {
QRect max = workspace()->clientArea(MaximizeArea, whichScreen, desktop());
setGeometry(QRect(max.x(), max.y() + max.height() / 2, max.width() / 2, max.height() / 2));
break;
}
case QuickTileBottomRight: {
QRect max = workspace()->clientArea(MaximizeArea, whichScreen, desktop());
setGeometry(QRect(max.x() + max.width() / 2, max.y() + max.height() / 2, max.width() / 2, max.height() / 2));
break;
}
}
if (mode != QuickTileNone)
setGeometry(electricBorderMaximizeGeometry(keyboard ? geometry().center() : cursorPos(), desktop()));
// Store the mode change
quick_tile_mode = mode;
@ -3257,9 +3185,7 @@ void Client::setQuickTileMode(QuickTileMode mode, bool keyboard)
// First, check if the requested tile negates the tile we're in now: move right when left or left when right
// is the same as explicitly untiling this window, so allow it.
if (mode == QuickTileNone ||
(quick_tile_mode == QuickTileLeft && mode == QuickTileRight) ||
(quick_tile_mode == QuickTileRight && mode == QuickTileLeft)) {
if (mode == QuickTileNone || ((quick_tile_mode & QuickTileHorizontal) && (mode & QuickTileHorizontal))) {
// Untiling, so just restore geometry, and we're done.
setGeometry(geom_pretile);
checkWorkspacePosition(); // Just in case it's a different screen
@ -3308,46 +3234,13 @@ void Client::setQuickTileMode(QuickTileMode mode, bool keyboard)
// Store geometry first, so we can go out of this tile later.
geom_pretile = geometry();
// DUPLICATED ABOVE: --------------------------------------------------
// Temporary, so the maximize code doesn't get all confused
quick_tile_mode = QuickTileNone;
// Do the actual tile.
switch(mode) {
case QuickTileLeft: {
QRect max = workspace()->clientArea(MaximizeArea, whichScreen, desktop());
setGeometry(QRect(max.x(), max.y(), max.width() / 2, max.height()));
break;
}
case QuickTileRight: {
QRect max = workspace()->clientArea(MaximizeArea, whichScreen, desktop());
setGeometry(QRect(max.x() + max.width() / 2, max.y(), max.width() / 2, max.height()));
break;
}
case QuickTileTopLeft: {
QRect max = workspace()->clientArea(MaximizeArea, whichScreen, desktop());
setGeometry(QRect(max.x(), max.y(), max.width() / 2, max.height() / 2));
break;
}
case QuickTileTopRight: {
QRect max = workspace()->clientArea(MaximizeArea, whichScreen, desktop());
setGeometry(QRect(max.x() + max.width() / 2, max.y(), max.width() / 2, max.height() / 2));
break;
}
case QuickTileBottomLeft: {
QRect max = workspace()->clientArea(MaximizeArea, whichScreen, desktop());
setGeometry(QRect(max.x(), max.y() + max.height() / 2, max.width() / 2, max.height() / 2));
break;
}
case QuickTileBottomRight: {
QRect max = workspace()->clientArea(MaximizeArea, whichScreen, desktop());
setGeometry(QRect(max.x() + max.width() / 2, max.y() + max.height() / 2, max.width() / 2, max.height() / 2));
break;
}
}
if (mode != QuickTileNone)
setGeometry(electricBorderMaximizeGeometry(whichScreen, desktop()));
// Store the mode change
quick_tile_mode = mode;
}
}

View file

@ -69,25 +69,18 @@ enum ElectricBorder {
ElectricNone
};
enum ElectricMaximizingMode {
ElectricMaximizeMode,
ElectricLeftMode,
ElectricRightMode,
ElectricTopLeftMode,
ElectricTopRightMode,
ElectricBottomLeftMode,
ElectricBottomRightMode
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
};
enum QuickTileMode {
QuickTileNone,
QuickTileLeft,
QuickTileRight,
QuickTileTopLeft,
QuickTileTopRight,
QuickTileBottomLeft,
QuickTileBottomRight
};
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
@ -202,4 +195,6 @@ private:
} // namespace
Q_DECLARE_OPERATORS_FOR_FLAGS(KWin::QuickTileMode)
#endif

View file

@ -705,7 +705,7 @@ void Workspace::slotWindowQuickTileTopLeft()
if (!active_client) {
return;
}
active_client->setQuickTileMode(QuickTileTopLeft, true);
active_client->setQuickTileMode(QuickTileTop|QuickTileLeft, true);
}
void Workspace::slotWindowQuickTileTopRight()
@ -713,7 +713,7 @@ void Workspace::slotWindowQuickTileTopRight()
if (!active_client) {
return;
}
active_client->setQuickTileMode(QuickTileTopRight, true);
active_client->setQuickTileMode(QuickTileTop|QuickTileRight, true);
}
void Workspace::slotWindowQuickTileBottomLeft()
@ -721,7 +721,7 @@ void Workspace::slotWindowQuickTileBottomLeft()
if (!active_client) {
return;
}
active_client->setQuickTileMode(QuickTileBottomLeft, true);
active_client->setQuickTileMode(QuickTileBottom|QuickTileLeft, true);
}
void Workspace::slotWindowQuickTileBottomRight()
@ -729,7 +729,7 @@ void Workspace::slotWindowQuickTileBottomRight()
if (!active_client) {
return;
}
active_client->setQuickTileMode(QuickTileBottomRight, true);
active_client->setQuickTileMode(QuickTileBottom|QuickTileRight, true);
}
int Workspace::packPositionLeft(const Client* cl, int oldx, bool left_edge) const

View file

@ -2441,7 +2441,7 @@ void Workspace::showElectricBorderWindowOutline()
if (!movingClient)
return;
// code copied from TabBox::updateOutline() in tabbox.cpp
QRect c = movingClient->electricBorderMaximizeGeometry();
QRect c = movingClient->electricBorderMaximizeGeometry(cursorPos(), currentDesktop());
// left/right parts are between top/bottom, they don't reach as far as the corners
XMoveResizeWindow(QX11Info::display(), outline_left, c.x(), c.y() + 5, 5, c.height() - 10);
XMoveResizeWindow(QX11Info::display(), outline_right, c.x() + c.width() - 5, c.y() + 5, 5, c.height() - 10);