/** Switch desktops if appropriate. */ void SignalMove(const TimeType *now, int x, int y, Window w, void *data) { if(settings.desktopDelay == 0) { return; } if(GetTimeDifference(now, &moveTime) < settings.desktopDelay) { return; } moveTime = *now; if(atLeft && LeftDesktop()) { SetClientDesktop(currentClient, currentDesktop); RestackClients(); } else if(atRight && RightDesktop()) { SetClientDesktop(currentClient, currentDesktop); RestackClients(); } else if(atTop && AboveDesktop()) { SetClientDesktop(currentClient, currentDesktop); RestackClients(); } else if(atBottom && BelowDesktop()) { SetClientDesktop(currentClient, currentDesktop); RestackClients(); } }
/** Toggle the "show desktop" state. */ void ShowDesktop() { ClientNode *np; int layer; for(layer = 0; layer < LAYER_COUNT; layer++) { for(np = nodes[layer]; np; np = np->next) { /* Skip "nolist" items. */ if(np->state.status & STAT_NOLIST) { continue; } if(showingDesktop) { if(np->state.status & STAT_SDESKTOP) { RestoreClient(np, 0); } } else if(np->state.desktop == currentDesktop || (np->state.status & STAT_STICKY)) { if(np->state.status & (STAT_MAPPED | STAT_SHADED)) { MinimizeClient(np); np->state.status |= STAT_SDESKTOP; } } } } showingDesktop = !showingDesktop; RestackClients(); }
/** Move to the next window in the window stack. */ void WalkWindowStack(char forward) { ClientNode *np; if(windowStack != NULL) { int x; if(wasMinimized) { np = FindClientByWindow(windowStack[windowStackCurrent]); if(np) { MinimizeClient(np, 1); } } /* Loop until we either raise a window or go through them all. */ for(x = 0; x < windowStackSize; x++) { /* Move to the next/previous window (wrap if needed). */ if(forward) { windowStackCurrent = (windowStackCurrent + 1) % windowStackSize; } else { if(windowStackCurrent == 0) { windowStackCurrent = windowStackSize; } windowStackCurrent -= 1; } /* Look up the window. */ np = FindClientByWindow(windowStack[windowStackCurrent]); /* Skip this window if it no longer exists or is currently in * a state that doesn't allow focus. */ if(np == NULL || !ShouldFocus(np, 1)) { continue; } /* Show the window. * Only when the walk completes do we update the stacking order. */ RestackClients(); if(np->state.status & STAT_MINIMIZED) { RestoreClient(np, 1); wasMinimized = 1; } else { wasMinimized = 0; } JXRaiseWindow(display, np->parent ? np->parent : np->window); FocusClient(np); break; } } }
/** Change to the specified desktop. */ void ChangeDesktop(unsigned int desktop) { ClientNode *np; unsigned int x; if(desktop >= desktopCount) { return; } if(currentDesktop == desktop && !initializing) { return; } /* Hide clients from the old desktop. * Note that we show clients in a separate loop to prevent an issue * with clients losing focus. */ for(x = 0; x < LAYER_COUNT; x++) { for(np = nodes[x]; np; np = np->next) { if(np->state.status & STAT_STICKY) { continue; } if(np->state.desktop == currentDesktop) { HideClient(np); } } } /* Show clients on the new desktop. */ for(x = 0; x < LAYER_COUNT; x++) { for(np = nodes[x]; np; np = np->next) { if(np->state.status & STAT_STICKY) { continue; } if(np->state.desktop == desktop) { ShowClient(np); } } } currentDesktop = desktop; SetCardinalAtom(rootWindow, ATOM_NET_CURRENT_DESKTOP, currentDesktop); SetCardinalAtom(rootWindow, ATOM_WIN_WORKSPACE, currentDesktop); RestackClients(); UpdatePager(); UpdateTaskBar(); LoadBackground(desktop); }
/** Handle a map request. */ void HandleMapRequest(const XMapEvent *event) { ClientNode *np; Assert(event); if(CheckSwallowMap(event)) { return; } np = FindClientByWindow(event->window); if(!np) { JXSync(display, False); JXGrabServer(display); np = AddClientWindow(event->window, 0, 1); if(np) { if(focusModel == FOCUS_CLICK && !(np->state.status & STAT_NOFOCUS)) { FocusClient(np); } } else { JXMapWindow(display, event->window); } JXSync(display, False); JXUngrabServer(display); } else { if(!(np->state.status & STAT_MAPPED)) { np->state = ReadWindowState(np->window); np->state.status |= STAT_MAPPED; if(!(np->state.status & STAT_STICKY)) { np->state.desktop = currentDesktop; } JXMapWindow(display, np->window); JXMapWindow(display, np->parent); if(!(np->state.status & STAT_NOFOCUS)) { RaiseClient(np); FocusClient(np); } UpdateTaskBar(); UpdatePager(); } } RestackClients(); }
/** Handle a map request. */ void HandleMapRequest(const XMapEvent *event) { ClientNode *np; Assert(event); if(CheckSwallowMap(event->window)) { return; } np = FindClientByWindow(event->window); if(!np) { GrabServer(); np = AddClientWindow(event->window, 0, 1); if(np) { if(!(np->state.status & STAT_NOFOCUS)) { FocusClient(np); } } else { JXMapWindow(display, event->window); } UngrabServer(); } else { if(!(np->state.status & STAT_MAPPED)) { UpdateState(np); np->state.status |= STAT_MAPPED; XMapWindow(display, np->window); XMapWindow(display, np->parent); if(!(np->state.status & STAT_STICKY)) { np->state.desktop = currentDesktop; } if(!(np->state.status & STAT_NOFOCUS)) { FocusClient(np); RaiseClient(np); } WriteState(np); UpdateTaskBar(); UpdatePager(); } } RestackClients(); }
/** Wait for an event and process it. */ char WaitForEvent(XEvent *event) { struct timeval timeout; CallbackNode *cp; fd_set fds; long sleepTime; int fd; char handled; #ifdef ConnectionNumber fd = ConnectionNumber(display); #else fd = JXConnectionNumber(display); #endif /* Compute how long we should sleep. */ sleepTime = 10 * 1000; /* 10 seconds. */ for(cp = callbacks; cp; cp = cp->next) { if(cp->freq > 0 && cp->freq < sleepTime) { sleepTime = cp->freq; } } do { if(restack_pending) { RestackClients(); restack_pending = 0; } if(task_update_pending) { UpdateTaskBar(); task_update_pending = 0; } if(pager_update_pending) { UpdatePager(); pager_update_pending = 0; } while(JXPending(display) == 0) { FD_ZERO(&fds); FD_SET(fd, &fds); timeout.tv_sec = sleepTime / 1000; timeout.tv_usec = (sleepTime % 1000) * 1000; if(select(fd + 1, &fds, NULL, NULL, &timeout) <= 0) { Signal(); } if(JUNLIKELY(shouldExit)) { return 0; } } Signal(); JXNextEvent(display, event); UpdateTime(event); switch(event->type) { case ConfigureRequest: HandleConfigureRequest(&event->xconfigurerequest); handled = 1; break; case MapRequest: HandleMapRequest(&event->xmap); handled = 1; break; case PropertyNotify: handled = HandlePropertyNotify(&event->xproperty); break; case ClientMessage: HandleClientMessage(&event->xclient); handled = 1; break; case UnmapNotify: HandleUnmapNotify(&event->xunmap); handled = 1; break; case Expose: handled = HandleExpose(&event->xexpose); break; case ColormapNotify: HandleColormapChange(&event->xcolormap); handled = 1; break; case DestroyNotify: handled = HandleDestroyNotify(&event->xdestroywindow); break; case SelectionClear: handled = HandleSelectionClear(&event->xselectionclear); break; case ResizeRequest: handled = HandleDockResizeRequest(&event->xresizerequest); break; case MotionNotify: SetMousePosition(event->xmotion.x_root, event->xmotion.y_root, event->xmotion.window); handled = 0; break; case ButtonPress: case ButtonRelease: SetMousePosition(event->xbutton.x_root, event->xbutton.y_root, event->xbutton.window); handled = 0; break; case EnterNotify: SetMousePosition(event->xcrossing.x_root, event->xcrossing.y_root, event->xcrossing.window); handled = 0; break; case LeaveNotify: SetMousePosition(event->xcrossing.x_root, event->xcrossing.y_root, None); handled = 0; break; case ReparentNotify: HandleDockReparentNotify(&event->xreparent); handled = 1; break; case ConfigureNotify: handled = HandleConfigureNotify(&event->xconfigure); break; case CreateNotify: case MapNotify: case GraphicsExpose: case NoExpose: handled = 1; break; default: if(0) { #ifdef USE_SHAPE } else if(haveShape && event->type == shapeEvent) { HandleShapeEvent((XShapeEvent*)event); handled = 1; #endif } else { handled = 0; } break; } if(!handled) { handled = ProcessTrayEvent(event); } if(!handled) { handled = ProcessDialogEvent(event); } if(!handled) { handled = ProcessSwallowEvent(event); } if(!handled) { handled = ProcessPopupEvent(event); } } while(handled && JLIKELY(!shouldExit)); return !handled; }