/** Move the window in the specified direction for reparenting. */ void GravitateClient(ClientNode *np, char negate) { int deltax, deltay; GetGravityDelta(np, np->gravity, &deltax, &deltay); if(negate) { np->x += deltax; np->y += deltay; } else { np->x -= deltax; np->y -= deltay; } }
/** Process a configure request. */ void HandleConfigureRequest(const XConfigureRequestEvent *event) { XWindowChanges wc; ClientNode *np; if(HandleDockConfigureRequest(event)) { return; } np = FindClientByWindow(event->window); if(np) { int deltax, deltay; char changed = 0; char resized = 0; GetGravityDelta(np, np->gravity, &deltax, &deltay); if((event->value_mask & CWWidth) && (event->width != np->width)) { switch(np->gravity) { case EastGravity: case NorthEastGravity: case SouthEastGravity: /* Right side should not move. */ np->x -= event->width - np->width; break; case WestGravity: case NorthWestGravity: case SouthWestGravity: /* Left side should not move. */ break; case CenterGravity: /* Center of the window should not move. */ np->x -= (event->width - np->width) / 2; break; default: break; } np->width = event->width; changed = 1; resized = 1; } if((event->value_mask & CWHeight) && (event->height != np->height)) { switch(np->gravity) { case NorthGravity: case NorthEastGravity: case NorthWestGravity: /* Top should not move. */ break; case SouthGravity: case SouthEastGravity: case SouthWestGravity: /* Bottom should not move. */ np->y -= event->height - np->height; break; case CenterGravity: /* Center of the window should not move. */ np->y -= (event->height - np->height) / 2; break; default: break; } np->height = event->height; changed = 1; resized = 1; } if((event->value_mask & CWX) && (event->x - deltax != np->x)) { np->x = event->x - deltax; changed = 1; } if((event->value_mask & CWY) && (event->y - deltay != np->y)) { np->y = event->y - deltay; changed = 1; } /* Update stacking. */ if((event->value_mask & CWStackMode)) { Window above = None; if(event->value_mask & CWSibling) { above = event->above; } RestackClient(np, above, event->detail); } /* Return early if there's nothing to do. */ if(!changed) { return; } if(np->controller) { (np->controller)(0); } if(np->state.maxFlags) { MaximizeClient(np, MAX_NONE); } if(np->state.border & BORDER_CONSTRAIN) { resized = 1; } if(resized) { ConstrainSize(np); ConstrainPosition(np); ResetBorder(np); } else { int north, south, east, west; GetBorderSize(&np->state, &north, &south, &east, &west); if(np->parent != None) { JXMoveWindow(display, np->parent, np->x - west, np->y - north); } else { JXMoveWindow(display, np->window, np->x, np->y); } } SendConfigureEvent(np); RequirePagerUpdate(); } else { /* We don't know about this window, just let the configure through. */ wc.stack_mode = event->detail; wc.sibling = event->above; wc.border_width = event->border_width; wc.x = event->x; wc.y = event->y; wc.width = event->width; wc.height = event->height; JXConfigureWindow(display, event->window, event->value_mask, &wc); } }
/** Handle a _NET_MOVERESIZE_WINDOW request. */ void HandleNetMoveResize(const XClientMessageEvent *event, ClientNode *np) { long flags; int gravity; int deltax, deltay; Assert(event); Assert(np); flags = event->data.l[0] >> 8; gravity = event->data.l[0] & 0xFF; if(gravity == 0) { gravity = np->gravity; } GetGravityDelta(np, gravity, &deltax, &deltay); if(flags & (1 << 2)) { const long width = event->data.l[3]; switch(gravity) { case EastGravity: case NorthEastGravity: case SouthEastGravity: /* Right side should not move. */ np->x -= width - np->width; break; case WestGravity: case NorthWestGravity: case SouthWestGravity: /* Left side should not move. */ break; case CenterGravity: /* Center of the window should not move. */ np->x -= (width - np->width) / 2; break; default: break; } np->width = width; } if(flags & (1 << 3)) { const long height = event->data.l[4]; switch(gravity) { case NorthGravity: case NorthEastGravity: case NorthWestGravity: /* Top should not move. */ break; case SouthGravity: case SouthEastGravity: case SouthWestGravity: /* Bottom should not move. */ np->y -= height - np->height; break; case CenterGravity: /* Center of the window should not move. */ np->y -= (height - np->height) / 2; break; default: break; } np->height = height; } if(flags & (1 << 0)) { np->x = event->data.l[1] - deltax; } if(flags & (1 << 1)) { np->y = event->data.l[2] - deltay; } /* Don't let maximized clients be moved or resized. */ if(JUNLIKELY(np->state.status & STAT_FULLSCREEN)) { SetClientFullScreen(np, 0); } if(JUNLIKELY(np->state.maxFlags)) { MaximizeClient(np, MAX_NONE); } ConstrainSize(np); ResetBorder(np); SendConfigureEvent(np); RequirePagerUpdate(); }
/** Handle a _NET_MOVERESIZE_WINDOW request. */ void HandleNetMoveResize(const XClientMessageEvent *event, ClientNode *np) { long flags, gravity; long x, y; long width, height; int deltax, deltay; int north, south, east, west; Assert(event); Assert(np); gravity = event->data.l[0] & 0xFF; flags = event->data.l[0] >> 8; x = np->x; y = np->y; width = np->width; height = np->height; if(flags & (1 << 0)) { x = event->data.l[1]; } if(flags & (1 << 1)) { y = event->data.l[2]; } if(flags & (1 << 2)) { width = event->data.l[3]; } if(flags & (1 << 3)) { height = event->data.l[4]; } if(gravity == 0) { gravity = np->gravity; } GetBorderSize(np, &north, &south, &east, &west); GetGravityDelta(np, &deltax, &deltay); x -= deltax; y -= deltay; np->x = x; np->y = y; np->width = width; np->height = height; if(np->state.status & STAT_FULLSCREEN) { Warning("Fullscreen state will be shaped!"); } /** Reset shaped bound */ ResetRoundedRectWindow(np->parent); ShapeRoundedRectWindow(np->parent, np->width + east + west, np->height + north + south); JXMoveResizeWindow(display, np->parent, np->x - west, np->y - north, np->width + east + west, np->height + north + south); JXMoveResizeWindow(display, np->window, west, north, np->width, np->height); WriteState(np); SendConfigureEvent(np); }