diff options
-rw-r--r-- | src/move.c | 75 | ||||
-rw-r--r-- | src/move.h | 5 | ||||
-rw-r--r-- | src/place.c | 101 |
3 files changed, 128 insertions, 53 deletions
@@ -530,6 +530,81 @@ void DoSnapBorder(ClientNode *np, int north, int west) { /**************************************************************************** ****************************************************************************/ +void ReturnToBorder(ClientNode *np, int north, int west) { + + const ScreenType *screen; + const TrayType *tray; + int layer; + RectangleType bottom = { 0 }; + RectangleType client, other; + RectangleType left = { 0 }; + RectangleType right = { 0 }; + RectangleType top = { 0 }; + + GetClientRectangle(np, &client); + screen = GetCurrentScreen(client.left, client.top); + + /* Check screen boundaries. */ + if(client.right > (screen->width - screen->x)) + np->x = screen->x + screen->width - west - np->width; + if(client.left < screen->x) + np->x = screen->x + west; + if(client.bottom > (screen->height - screen->y)) { + np->y = screen->y + screen->height - west; + if(!(np->state.status & STAT_SHADED)) + np->y -= np->height; + } + if(client.top < screen->y) + np->y = north + screen->y; + + GetClientRectangle(np, &client); + other.valid = 1; + + /* Work from the bottom of the window stack to the top. */ + for(layer = 0; layer < LAYER_COUNT; layer++) { + + /* Check tray windows. */ + for(tray = GetTrays(); tray; tray = tray->next) { + + if(tray->hidden) + continue; + + other.left = tray->x; + other.right = tray->x + tray->width; + other.top = tray->y; + other.bottom = tray->y + tray->height; + + left.valid = CheckLeftValid(&client, &other, &left); + right.valid = CheckRightValid(&client, &other, &right); + top.valid = CheckTopValid(&client, &other, &top); + bottom.valid = CheckBottomValid(&client, &other, &bottom); + + if(other.top == screen->y + && client.top < other.bottom) + top = other; + if(other.bottom == screen->height + && client.bottom > other.top) + bottom = other; + } + + } + + if(right.valid) + np->x = right.left - np->width - west; + if(left.valid) + np->x = left.right + west; + if(bottom.valid) { + np->y = bottom.top - west; + if(!(np->state.status & STAT_SHADED)) + np->y -= np->height; + } + if(top.valid) + np->y = top.bottom + north; + +} + +/**************************************************************************** + ****************************************************************************/ int ShouldSnap(const ClientNode *np) { if(np->state.status & STAT_HIDDEN) { return 0; @@ -57,5 +57,10 @@ void SetDefaultSnapDistance(); */ void SetMoveMode(MoveModeType mode); +/** Make the client return to the screen/tray bounds. + * @param mode The client node to affect. + */ +void ReturnToBorder(struct ClientNode *np, int north, int west); + #endif diff --git a/src/place.c b/src/place.c index f70ce73..cad5d96 100644 --- a/src/place.c +++ b/src/place.c @@ -8,6 +8,7 @@ #include "client.h" #include "screen.h" #include "border.h" +#include "move.h" #include "tray.h" #include "main.h" @@ -26,9 +27,12 @@ typedef struct Strut { static Strut *struts = NULL; static Strut *strutsTail = NULL; +static int prevx = -1; +static int prevy = -1; +static int offset = 0; + /* desktopCount x screenCount */ /* Note that we assume x and y are 0 based for all screens here. */ -static int *cascadeOffsets = NULL; static void GetScreenBounds(const ScreenType *sp, BoundingBox *box); static void UpdateTrayBounds(BoundingBox *box, unsigned int layer); @@ -43,17 +47,6 @@ void InitializePlacement() { /**************************************************************************** ****************************************************************************/ void StartupPlacement() { - - int count; - int x; - - count = desktopCount * GetScreenCount(); - cascadeOffsets = Allocate(count * sizeof(int)); - - for(x = 0; x < count; x++) { - cascadeOffsets[x] = borderWidth + titleHeight; - } - } /**************************************************************************** @@ -62,8 +55,6 @@ void ShutdownPlacement() { Strut *sp; - Release(cascadeOffsets); - while(struts) { sp = struts->next; Release(struts); @@ -374,10 +365,11 @@ void UpdateStrutBounds(BoundingBox *box) { void PlaceClient(ClientNode *np, int alreadyMapped) { BoundingBox box; - int north, south, east, west; const ScreenType *sp; - int cascadeIndex; - int overflow; + int height, overflow, width, winx, winy, x, y; + int north, south, east, west; + unsigned int mask; + Window rootReturn, childReturn; Assert(np); @@ -403,47 +395,50 @@ void PlaceClient(ClientNode *np, int alreadyMapped) { UpdateTrayBounds(&box, np->state.layer); UpdateStrutBounds(&box); - cascadeIndex = sp->index * desktopCount + currentDesktop; - - /* Set the cascaded location. */ - np->x = box.x + west + cascadeOffsets[cascadeIndex]; - np->y = box.y + north + cascadeOffsets[cascadeIndex]; - cascadeOffsets[cascadeIndex] += borderWidth + titleHeight; - - /* Check for cascade overflow. */ - overflow = 0; - if(np->x + np->width - box.x > box.width) { - overflow = 1; - } else if(np->y + np->height - box.y > box.height) { - overflow = 1; + /* Check cursor location. */ + JXQueryPointer(display, rootWindow, &rootReturn, &childReturn, + &x, &y, &winx, &winy, &mask); + + if(prevx > -1 + && prevy > -1 + && (abs(x - prevx) <= borderWidth + || abs(y - prevy) <= borderWidth)) { + offset += borderWidth + titleHeight; + } else { + offset = 0; + prevx = x; + prevy = y; } - if(overflow) { - - cascadeOffsets[cascadeIndex] = borderWidth + titleHeight; - np->x = box.x + west + cascadeOffsets[cascadeIndex]; - np->y = box.y + north + cascadeOffsets[cascadeIndex]; - - /* Check for client overflow. */ - overflow = 0; - if(np->x + np->width - box.x > box.width) { - overflow = 1; - } else if(np->y + np->height - box.y > box.height) { - overflow = 1; - } - - /* Update cascade position or position client. */ - if(overflow) { - np->x = box.x + west; - np->y = box.y + north; - } else { - cascadeOffsets[cascadeIndex] += borderWidth + titleHeight; - } - + /* Show window at cursor. */ + width = np->width; + height = np->height; + if(np->state.border & BORDER_OUTLINE) { + x += borderWidth; + y += borderWidth; + width += borderWidth * 2; + height += borderWidth * 2; } - + if(np->state.border & BORDER_TITLE) { + y += titleHeight; + height += titleHeight; + } + x -= width / 2; + y -= height / 2; + np->x = x + offset; + np->y = y + offset; + + /* Correct for overflow. */ + /* + if(np->x + np->width - box.x > box.width) + np->x = box.width - (np->width - box.x); + if(np->y + np->height - box.y > box.height) + np->y = box.height - (np->height - box.y); + */ + ReturnToBorder(np, north, west); } + if(np->state.status & STAT_FULLSCREEN) { JXMoveWindow(display, np->parent, sp->x, sp->y); } else { |