/** Discard key events for the specified window. */ void DiscardKeyEvents(XEvent *event, Window w) { JXSync(display, False); while(JXCheckTypedWindowEvent(display, w, KeyPress, event)) { UpdateTime(event); } }
/** Discard button events for the specified windows. */ void DiscardButtonEvents() { XEvent event; JXSync(display, False); while(JXCheckMaskEvent(display, ButtonPressMask | ButtonReleaseMask, &event)) { UpdateTime(&event); } }
/** Clear the last outline. */ void ClearOutline() { if(outlineDrawn) { JXDrawRectangle(display, rootWindow, outlineGC, lastX, lastY, lastWidth, lastHeight); outlineDrawn = 0; JXUngrabServer(display); JXSync(display, False); } }
/** Discard enter notify events. */ void DiscardEnterEvents() { XEvent event; JXSync(display, False); while(JXCheckMaskEvent(display, EnterWindowMask, &event)) { UpdateTime(&event); SetMousePosition(event.xmotion.x_root, event.xmotion.y_root, event.xmotion.window); } }
/** 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(); }
/** Draw an outline. */ void DrawOutline(int x, int y, int width, int height) { if(!outlineDrawn) { JXSync(display, False); JXGrabServer(display); JXDrawRectangle(display, rootWindow, outlineGC, x, y, width, height); lastX = x; lastY = y; lastWidth = width; lastHeight = height; outlineDrawn = 1; } }
/** Discard motion events for the specified window. */ void DiscardMotionEvents(XEvent *event, Window w) { XEvent temp; JXSync(display, False); while(JXCheckTypedEvent(display, MotionNotify, &temp)) { UpdateTime(&temp); SetMousePosition(temp.xmotion.x_root, temp.xmotion.y_root, temp.xmotion.window); if(temp.xmotion.window == w) { *event = temp; } } }
/** Callback to kill a client after a confirm dialog. */ void KillClientHandler(ClientNode *np) { Assert(np); if(np == activeClient) { FocusNextStacked(np); } GrabServer(); JXKillClient(display, np->window); JXSync(display, True); UngrabServer(); RemoveClient(np); }
/** Startup the various JWM components. * This is called after the X connection is opened. */ void Startup(void) { /* This order is important. */ /* First we grab the server to prevent clients from changing things * while we're still loading. */ GrabServer(); StartupSettings(); StartupScreens(); StartupGroups(); StartupColors(); StartupIcons(); StartupBackgrounds(); StartupFonts(); StartupCursors(); StartupPager(); StartupClock(); StartupTaskBar(); StartupTrayButtons(); StartupDesktops(); StartupHints(); StartupDock(); StartupTray(); StartupKeys(); StartupBorders(); StartupPlacement(); StartupClients(); # ifndef DISABLE_CONFIRM StartupDialogs(); # endif StartupPopup(); StartupRootMenu(); SetDefaultCursor(rootWindow); ReadCurrentDesktop(); JXFlush(display); RequireRestack(); /* Allow clients to do their thing. */ JXSync(display, True); UngrabServer(); StartupSwallow(); DrawTray(); /* Send expose events. */ ExposeCurrentDesktop(); /* Draw the background (if backgrounds are used). */ LoadBackground(currentDesktop); /* Run any startup commands. */ StartupCommands(); }
/** Prepare the connection. */ void StartupConnection(void) { XSetWindowAttributes attr; #ifdef USE_SHAPE int shapeError; #endif #ifdef USE_XRENDER int renderEvent; int renderError; #endif struct sigaction sa; char name[32]; Window win; XEvent event; int revert; initializing = 1; OpenConnection(); #if 0 XSynchronize(display, True); #endif /* Create the supporting window used to verify JWM is running. */ supportingWindow = JXCreateSimpleWindow(display, rootWindow, 0, 0, 1, 1, 0, 0, 0); /* Get the atom used for the window manager selection. */ snprintf(name, 32, "WM_S%d", rootScreen); managerSelection = JXInternAtom(display, name, False); /* Get the current window manager and take the selection. */ GrabServer(); win = JXGetSelectionOwner(display, managerSelection); if(win != None) { JXSelectInput(display, win, StructureNotifyMask); } JXSetSelectionOwner(display, managerSelection, supportingWindow, CurrentTime); UngrabServer(); /* Wait for the current selection owner to give up the selection. */ if(win != None) { /* Note that we need to wait for the current selection owner * to exit before we can expect to select SubstructureRedirectMask. */ XIfEvent(display, &event, SelectionReleased, (XPointer)&win); JXSync(display, False); } event.xclient.display = display; event.xclient.type = ClientMessage; event.xclient.window = rootWindow; event.xclient.message_type = JXInternAtom(display, managerProperty, False); event.xclient.format = 32; event.xclient.data.l[0] = CurrentTime; event.xclient.data.l[1] = managerSelection; event.xclient.data.l[2] = supportingWindow; event.xclient.data.l[3] = 2; event.xclient.data.l[4] = 0; JXSendEvent(display, rootWindow, False, StructureNotifyMask, &event); JXSync(display, False); JXSetErrorHandler(ErrorHandler); clientContext = XUniqueContext(); frameContext = XUniqueContext(); /* Set the events we want for the root window. * Note that asking for SubstructureRedirect will fail * if another window manager is already running. */ attr.event_mask = SubstructureRedirectMask | SubstructureNotifyMask | StructureNotifyMask | PropertyChangeMask | ColormapChangeMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | PointerMotionHintMask; JXChangeWindowAttributes(display, rootWindow, CWEventMask, &attr); memset(&sa, 0, sizeof(sa)); sa.sa_flags = 0; sa.sa_handler = HandleExit; sigaction(SIGTERM, &sa, NULL); sigaction(SIGINT, &sa, NULL); sigaction(SIGHUP, &sa, NULL); sa.sa_flags = SA_NOCLDWAIT; sa.sa_handler = SIG_DFL; sigaction(SIGCHLD, &sa, NULL); #ifdef USE_SHAPE haveShape = JXShapeQueryExtension(display, &shapeEvent, &shapeError); if (haveShape) { Debug("shape extension enabled"); } else { Debug("shape extension disabled"); } #endif #ifdef USE_XRENDER haveRender = JXRenderQueryExtension(display, &renderEvent, &renderError); if(haveRender) { Debug("render extension enabled"); } else { Debug("render extension disabled"); } #endif /* Make sure we have input focus. */ win = None; JXGetInputFocus(display, &win, &revert); if(win == None) { JXSetInputFocus(display, rootWindow, RevertToParent, CurrentTime); } initializing = 0; }
/** Startup trays. */ void StartupTray() { XSetWindowAttributes attr; Atom opacityAtom; unsigned long attrMask; TrayType *tp; TrayComponentType *cp; int variableSize; int variableRemainder; int width, height; int xoffset, yoffset; for(tp = trays; tp; tp = tp->next) { LayoutTray(tp, &variableSize, &variableRemainder); /* Create the tray window. */ /* The window is created larger for a border. */ attrMask = CWOverrideRedirect; attr.override_redirect = True; /* We can't use PointerMotionHintMask since the exact position * of the mouse on the tray is important for popups. */ attrMask |= CWEventMask; attr.event_mask = ButtonPressMask | ButtonReleaseMask | SubstructureNotifyMask | ExposureMask | KeyPressMask | KeyReleaseMask | EnterWindowMask | PointerMotionMask; attrMask |= CWBackPixel; attr.background_pixel = colors[COLOR_TRAY_BG]; tp->window = JXCreateWindow(display, rootWindow, tp->x, tp->y, tp->width, tp->height, 0, rootDepth, InputOutput, rootVisual, attrMask, &attr); if(trayOpacity < UINT_MAX) { /* Can't use atoms yet as it hasn't been initialized. */ opacityAtom = JXInternAtom(display, "_NET_WM_WINDOW_OPACITY", False); JXChangeProperty(display, tp->window, opacityAtom, XA_CARDINAL, 32, PropModeReplace, (unsigned char*)&trayOpacity, 1); JXSync(display, False); } SetDefaultCursor(tp->window); /* Create and layout items on the tray. */ xoffset = tp->border; yoffset = tp->border; for(cp = tp->components; cp; cp = cp->next) { if(cp->Create) { if(tp->layout == LAYOUT_HORIZONTAL) { height = tp->height - 2 * tp->border; width = cp->width; if(width == 0) { width = variableSize; if(variableRemainder) { ++width; --variableRemainder; } } } else { width = tp->width - 2 * tp->border; height = cp->height; if(height == 0) { height = variableSize; if(variableRemainder) { ++height; --variableRemainder; } } } cp->width = width; cp->height = height; (cp->Create)(cp); } cp->x = xoffset; cp->y = yoffset; cp->screenx = tp->x + xoffset; cp->screeny = tp->y + yoffset; if(cp->window != None) { JXReparentWindow(display, cp->window, tp->window, xoffset, yoffset); } if(tp->layout == LAYOUT_HORIZONTAL) { xoffset += cp->width; } else { yoffset += cp->height; } } /* Show the tray. */ JXMapWindow(display, tp->window); ++trayCount; } UpdatePager(); UpdateTaskBar(); }