/** Set the active client. */ void FocusClient(ClientNode *np) { if(np->state.status & STAT_HIDDEN) { return; } if(!(np->state.status & (STAT_CANFOCUS | STAT_TAKEFOCUS))) { return; } if(activeClient != np || !(np->state.status & STAT_ACTIVE)) { if(activeClient) { activeClient->state.status &= ~STAT_ACTIVE; if(!(activeClient->state.status & STAT_OPACITY)) { SetOpacity(activeClient, settings.inactiveClientOpacity, 0); } DrawBorder(activeClient); } np->state.status |= STAT_ACTIVE; activeClient = np; if(!(np->state.status & STAT_OPACITY)) { SetOpacity(np, settings.activeClientOpacity, 0); } DrawBorder(np); RequirePagerUpdate(); RequireTaskUpdate(); } if(np->state.status & STAT_MAPPED) { UpdateClientColormap(np); SetWindowAtom(rootWindow, ATOM_NET_ACTIVE_WINDOW, np->window); if(np->state.status & STAT_CANFOCUS) { JXSetInputFocus(display, np->window, RevertToParent, eventTime); } if(np->state.status & STAT_TAKEFOCUS) { SendClientMessage(np->window, ATOM_WM_PROTOCOLS, ATOM_WM_TAKE_FOCUS); } } else { JXSetInputFocus(display, rootWindow, RevertToParent, eventTime); } }
/** Set root hints and intern atoms. */ void StartupHints(void) { unsigned long *array; char *data; Atom *supported; Window win; unsigned int x; unsigned int count; /* Determine how much space we will need on the stack and allocate it. */ count = 0; for(x = 0; x < settings.desktopCount; x++) { count += strlen(GetDesktopName(x)) + 1; } if(count < 2 * sizeof(unsigned long)) { count = 2 * sizeof(unsigned long); } if(count < ATOM_COUNT * sizeof(Atom)) { count = ATOM_COUNT * sizeof(Atom); } data = AllocateStack(count); array = (unsigned long*)data; supported = (Atom*)data; /* Intern the atoms */ for(x = 0; x < ATOM_COUNT; x++) { *atomList[x].atom = JXInternAtom(display, atomList[x].name, False); } /* _NET_SUPPORTED */ for(x = FIRST_NET_ATOM; x <= LAST_NET_ATOM; x++) { supported[x - FIRST_NET_ATOM] = atoms[x]; } JXChangeProperty(display, rootWindow, atoms[ATOM_NET_SUPPORTED], XA_ATOM, 32, PropModeReplace, (unsigned char*)supported, LAST_NET_ATOM - FIRST_NET_ATOM + 1); /* _NET_NUMBER_OF_DESKTOPS */ SetCardinalAtom(rootWindow, ATOM_NET_NUMBER_OF_DESKTOPS, settings.desktopCount); /* _NET_DESKTOP_NAMES */ count = 0; for(x = 0; x < settings.desktopCount; x++) { const char *name = GetDesktopName(x); const unsigned len = strlen(name); memcpy(&data[count], name, len + 1); count += len + 1; } JXChangeProperty(display, rootWindow, atoms[ATOM_NET_DESKTOP_NAMES], atoms[ATOM_UTF8_STRING], 8, PropModeReplace, (unsigned char*)data, count); /* _NET_DESKTOP_GEOMETRY */ array[0] = rootWidth; array[1] = rootHeight; JXChangeProperty(display, rootWindow, atoms[ATOM_NET_DESKTOP_GEOMETRY], XA_CARDINAL, 32, PropModeReplace, (unsigned char*)array, 2); /* _NET_DESKTOP_VIEWPORT */ array[0] = 0; array[1] = 0; JXChangeProperty(display, rootWindow, atoms[ATOM_NET_DESKTOP_VIEWPORT], XA_CARDINAL, 32, PropModeReplace, (unsigned char*)array, 2); /* _NET_WM_NAME */ win = supportingWindow; JXChangeProperty(display, win, atoms[ATOM_NET_WM_NAME], atoms[ATOM_UTF8_STRING], 8, PropModeReplace, (unsigned char*)"JWM", 3); /* _NET_WM_PID */ array[0] = getpid(); JXChangeProperty(display, win, atoms[ATOM_NET_WM_PID], XA_CARDINAL, 32, PropModeReplace, (unsigned char*)array, 1); /* _NET_SUPPORTING_WM_CHECK */ SetWindowAtom(rootWindow, ATOM_NET_SUPPORTING_WM_CHECK, win); SetWindowAtom(win, ATOM_NET_SUPPORTING_WM_CHECK, win); ReleaseStack(data); }
/** 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(); }