/** Handle an unmap notify event. */ void HandleUnmapNotify(const XUnmapEvent *event) { ClientNode *np; XEvent e; Assert(event); if(event->window != event->event) { /* Allow ICCCM synthetic UnmapNotify events through. */ if (event->event != rootWindow || !event->send_event) { return; } } np = FindClientByWindow(event->window); if(np) { /* Grab the server to prevent the client from destroying the * window after we check for a DestroyNotify. */ GrabServer(); if(np->controller) { (np->controller)(1); } if(JXCheckTypedWindowEvent(display, np->window, DestroyNotify, &e)) { UpdateTime(&e); RemoveClient(np); } else if((np->state.status & STAT_MAPPED) || event->send_event) { if(!(np->state.status & STAT_HIDDEN)) { np->state.status &= ~STAT_MAPPED; JXUngrabButton(display, AnyButton, AnyModifier, np->window); GravitateClient(np, 1); JXReparentWindow(display, np->window, rootWindow, np->x, np->y); WriteState(np); JXRemoveFromSaveSet(display, np->window); RemoveClient(np); } } UngrabServer(); } }
/** Destroy a swallow tray component. */ void Destroy(TrayComponentType *cp) { ClientProtocolType protocols; /* Destroy the window if there is one. */ if(cp->window) { JXReparentWindow(display, cp->window, rootWindow, 0, 0); JXRemoveFromSaveSet(display, cp->window); protocols = ReadWMProtocols(cp->window); if(protocols & PROT_DELETE) { SendClientMessage(cp->window, ATOM_WM_PROTOCOLS, ATOM_WM_DELETE_WINDOW); } else { JXKillClient(display, cp->window); } } }
/** Remove a client window from management. */ void RemoveClient(ClientNode *np) { ColormapNode *cp; Assert(np); Assert(np->window != None); /* Remove this client from the client list */ if(np->next) { np->next->prev = np->prev; } else { nodeTail[np->state.layer] = np->prev; } if(np->prev) { np->prev->next = np->next; } else { nodes[np->state.layer] = np->next; } clientCount -= 1; XDeleteContext(display, np->window, clientContext); if(np->parent != None) { XDeleteContext(display, np->parent, frameContext); } if(np->state.status & STAT_URGENT) { UnregisterCallback(SignalUrgent, np); } /* Make sure this client isn't active */ if(activeClient == np && !shouldExit) { FocusNextStacked(np); } if(activeClient == np) { /* Must be the last client. */ SetWindowAtom(rootWindow, ATOM_NET_ACTIVE_WINDOW, None); activeClient = NULL; JXSetInputFocus(display, rootWindow, RevertToParent, eventTime); } /* If the window manager is exiting (ie, not the client), then * reparent etc. */ if(shouldExit && !(np->state.status & STAT_WMDIALOG)) { if(np->state.maxFlags) { np->x = np->oldx; np->y = np->oldy; np->width = np->oldWidth; np->height = np->oldHeight; JXMoveResizeWindow(display, np->window, np->x, np->y, np->width, np->height); } GravitateClient(np, 1); if(!(np->state.status & STAT_MAPPED) && (np->state.status & (STAT_MINIMIZED | STAT_SHADED))) { JXMapWindow(display, np->window); } JXUngrabButton(display, AnyButton, AnyModifier, np->window); JXReparentWindow(display, np->window, rootWindow, np->x, np->y); JXRemoveFromSaveSet(display, np->window); } /* Destroy the parent */ if(np->parent) { JXDestroyWindow(display, np->parent); } if(np->name) { Release(np->name); } if(np->instanceName) { JXFree(np->instanceName); } if(np->className) { JXFree(np->className); } RemoveClientFromTaskBar(np); RemoveClientStrut(np); while(np->colormaps) { cp = np->colormaps->next; Release(np->colormaps); np->colormaps = cp; } DestroyIcon(np->icon); Release(np); RequireRestack(); }