/** Start walking windows in client list order. */ void StartWindowWalk(void) { JXGrabKeyboard(display, rootWindow, False, GrabModeAsync, GrabModeAsync, CurrentTime); RaiseTrays(); walkingWindows = 1; }
/** Start walking the window stack. */ void StartWindowStackWalk(void) { /* Get an image of the window stack. * Here we get the Window IDs rather than client pointers so * clients can be added/removed without disrupting the stack walk. */ ClientNode *np; int layer; int count; /* If we are already walking the stack, just return. */ if(windowStack != NULL) { return; } /* First determine how much space to allocate for windows. */ count = 0; for(layer = LAST_LAYER; layer >= FIRST_LAYER; layer--) { for(np = nodes[layer]; np; np = np->next) { if(ShouldFocus(np, 1)) { ++count; } } } /* If there were no windows to walk, don't even start. */ if(count == 0) { return; } /* Allocate space for the windows. */ windowStack = Allocate(sizeof(Window) * count); /* Copy windows into the array. */ windowStackSize = 0; for(layer = LAST_LAYER; layer >= FIRST_LAYER; layer--) { for(np = nodes[layer]; np; np = np->next) { if(ShouldFocus(np, 1)) { windowStack[windowStackSize++] = np->window; } } } Assert(windowStackSize == count); windowStackCurrent = 0; JXGrabKeyboard(display, rootWindow, False, GrabModeAsync, GrabModeAsync, CurrentTime); RaiseTrays(); walkingWindows = 1; wasMinimized = 0; }
/** Move a client window (keyboard or menu initiated). */ char MoveClientKeyboard(ClientNode *np) { XEvent event; int oldx, oldy; int moved; int height; int north, south, east, west; MaxFlags maxFlags; Assert(np); if(!(np->state.border & BORDER_MOVE)) { return 0; } if(np->state.status & STAT_FULLSCREEN) { return 0; } maxFlags = np->state.maxFlags; if(np->state.maxFlags != MAX_NONE) { MaximizeClient(np, MAX_NONE); } if(JUNLIKELY(JXGrabKeyboard(display, np->parent, True, GrabModeAsync, GrabModeAsync, CurrentTime))) { Debug("MoveClient: could not grab keyboard"); return 0; } GrabMouseForMove(); GetBorderSize(&np->state, &north, &south, &east, &west); oldx = np->x; oldy = np->y; RegisterCallback(0, SignalMove, NULL); np->controller = MoveController; shouldStopMove = 0; CreateMoveWindow(np); UpdateMoveWindow(np); MoveMouse(rootWindow, np->x, np->y); DiscardMotionEvents(&event, np->window); if(np->state.status & STAT_SHADED) { height = 0; } else { height = np->height; } for(;;) { WaitForEvent(&event); if(shouldStopMove) { np->controller = NULL; SetDefaultCursor(np->parent); UnregisterCallback(SignalMove, NULL); return 1; } moved = 0; if(event.type == KeyPress) { DiscardKeyEvents(&event, np->window); switch(GetKey(&event.xkey) & 0xFF) { case KEY_UP: if(np->y + height > 0) { np->y -= 10; } break; case KEY_DOWN: if(np->y < rootHeight) { np->y += 10; } break; case KEY_RIGHT: if(np->x < rootWidth) { np->x += 10; } break; case KEY_LEFT: if(np->x + np->width > 0) { np->x -= 10; } break; default: StopMove(np, 1, oldx, oldy, maxFlags); return 1; } MoveMouse(rootWindow, np->x, np->y); DiscardMotionEvents(&event, np->window); moved = 1; } else if(event.type == MotionNotify) { DiscardMotionEvents(&event, np->window); np->x = event.xmotion.x; np->y = event.xmotion.y; moved = 1; } else if(event.type == ButtonRelease) { StopMove(np, 1, oldx, oldy, maxFlags); return 1; } if(moved) { if(settings.moveMode == MOVE_OUTLINE) { ClearOutline(); DrawOutline(np->x - west, np->y - west, np->width + west + east, height + north + west); } else { JXMoveWindow(display, np->parent, np->x - west, np->y - north); SendConfigureEvent(np); } UpdateMoveWindow(np); RequirePagerUpdate(); } } }