/** Process a configure request. */ void HandleConfigureRequest(const XConfigureRequestEvent *event) { XWindowChanges wc; ClientNode *np; int north, south, east, west; int changed; int handled; handled = HandleDockConfigureRequest(event); if(handled) { return; } np = FindClientByWindow(event->window); if(np && np->window == event->window) { /* We own this window, make sure it's not trying to do something bad. */ changed = 0; if((event->value_mask & CWWidth) && (event->width != np->width)) { if(!(np->state.status & STAT_HMAX)) { np->width = event->width; changed = 1; } } if((event->value_mask & CWHeight) && (event->height != np->height)) { if(!(np->state.status & STAT_VMAX)) { np->height = event->height; changed = 1; } } if((event->value_mask & CWX) && (event->x != np->x)) { if(!(np->state.status & STAT_HMAX)) { np->x = event->x; changed = 1; } } if((event->value_mask & CWY) && (event->y != np->y)) { if(!(np->state.status & STAT_VMAX)) { np->y = event->y; changed = 1; } } if(!changed) { return; } if(np->controller) { (np->controller)(0); } GetBorderSize(np, &north, &south, &east, &west); ResetRoundedRectWindow(np->parent); wc.stack_mode = Above; wc.sibling = np->parent; wc.border_width = 0; ConstrainSize(np); wc.x = np->x; wc.y = np->y; wc.width = np->width + east + west; wc.height = np->height + north + south; JXConfigureWindow(display, np->parent, event->value_mask, &wc); wc.x = west; wc.y = north; wc.width = np->width; wc.height = np->height; JXConfigureWindow(display, np->window, event->value_mask, &wc); } 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 > rootWidth ? rootWidth : event->width; wc.height = event->height > rootHeight ? rootHeight : 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, 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); }
/** Resize a client window (mouse initiated). */ void ResizeClient(ClientNode *np, BorderActionType action, int startx, int starty) { XEvent event; int oldx, oldy; int oldw, oldh; int gwidth, gheight; int lastgwidth, lastgheight; int delta; int north, south, east, west; int ratio, minr, maxr; Assert(np); if(!(np->state.border & BORDER_RESIZE)) { return; } if(JUNLIKELY(!GrabMouseForResize(action))) { Debug("ResizeClient: could not grab mouse"); return; } if(np->state.status & STAT_SHADED) { action &= ~(BA_RESIZE_N | BA_RESIZE_S); } np->controller = ResizeController; shouldStopResize = 0; oldx = np->x; oldy = np->y; oldw = np->width; oldh = np->height; gwidth = (np->width - np->baseWidth) / np->xinc; gheight = (np->height - np->baseHeight) / np->yinc; GetBorderSize(np, &north, &south, &east, &west); startx += np->x - west; starty += np->y - north; CreateResizeWindow(np); UpdateResizeWindow(np, gwidth, gheight); if(!(GetMouseMask() & (Button1Mask | Button3Mask))) { StopResize(np); return; } for(;;) { WaitForEvent(&event); if(shouldStopResize) { np->controller = NULL; return; } switch(event.type) { case ButtonRelease: if( event.xbutton.button == Button1 || event.xbutton.button == Button3) { StopResize(np); return; } break; case MotionNotify: SetMousePosition(event.xmotion.x_root, event.xmotion.y_root); DiscardMotionEvents(&event, np->window); if(action & BA_RESIZE_N) { delta = (event.xmotion.y - starty) / np->yinc; delta *= np->yinc; if(oldh - delta >= np->minHeight && (oldh - delta <= np->maxHeight || delta > 0)) { np->height = oldh - delta; np->y = oldy + delta; } if(!(action & (BA_RESIZE_E | BA_RESIZE_W))) { FixWidth(np); } } if(action & BA_RESIZE_S) { delta = (event.xmotion.y - starty) / np->yinc; delta *= np->yinc; np->height = oldh + delta; np->height = Max(np->height, np->minHeight); np->height = Min(np->height, np->maxHeight); if(!(action & (BA_RESIZE_E | BA_RESIZE_W))) { FixWidth(np); } } if(action & BA_RESIZE_E) { delta = (event.xmotion.x - startx) / np->xinc; delta *= np->xinc; np->width = oldw + delta; np->width = Max(np->width, np->minWidth); np->width = Min(np->width, np->maxWidth); if(!(action & (BA_RESIZE_N | BA_RESIZE_S))) { FixHeight(np); } } if(action & BA_RESIZE_W) { delta = (event.xmotion.x - startx) / np->xinc; delta *= np->xinc; if(oldw - delta >= np->minWidth && (oldw - delta <= np->maxWidth || delta > 0)) { np->width = oldw - delta; np->x = oldx + delta; } if(!(action & (BA_RESIZE_N | BA_RESIZE_S))) { FixHeight(np); } } if(np->sizeFlags & PAspect) { if((action & (BA_RESIZE_N | BA_RESIZE_S)) && (action & (BA_RESIZE_E | BA_RESIZE_W))) { /* Fixed point with a 16-bit fraction. */ ratio = (np->width << 16) / np->height; minr = (np->aspect.minx << 16) / np->aspect.miny; if(ratio < minr) { delta = np->width; np->width = (np->height * minr) >> 16; if(action & BA_RESIZE_W) { np->x -= np->width - delta; } } maxr = (np->aspect.maxx << 16) / np->aspect.maxy; if(ratio > maxr) { delta = np->height; np->height = (np->width << 16) / maxr; if(action & BA_RESIZE_N) { np->y -= np->height - delta; } } } } lastgwidth = gwidth; lastgheight = gheight; gwidth = (np->width - np->baseWidth) / np->xinc; gheight = (np->height - np->baseHeight) / np->yinc; if(lastgheight != gheight || lastgwidth != gwidth) { if(np->state.status & (STAT_HMAX | STAT_VMAX)) { np->state.status &= ~(STAT_HMAX | STAT_VMAX); WriteState(np); SendConfigureEvent(np); } UpdateResizeWindow(np, gwidth, gheight); if(resizeMode == RESIZE_OUTLINE) { ClearOutline(); if(np->state.status & STAT_SHADED) { DrawOutline(np->x - west, np->y - north, np->width + west + east, north + south); } else { DrawOutline(np->x - west, np->y - north, np->width + west + east, np->height + north + south); } } else { ResetRoundedRectWindow(np->parent); if(np->state.status & STAT_SHADED) { ShapeRoundedRectWindow(np->parent, np->width + east + west, north + south); JXMoveResizeWindow(display, np->parent, np->x - west, np->y - north, np->width + west + east, north + south); } else { ShapeRoundedRectWindow(np->parent, np->width + east + west, np->height + north + south); JXMoveResizeWindow(display, np->parent, np->x - west, np->y - north, np->width + west + east, np->height + north + south); } JXMoveResizeWindow(display, np->window, west, north, np->width, np->height); SendConfigureEvent(np); } UpdatePager(); } break; default: break; }