/** Send a configure event to a client window. */ void SendConfigureEvent(ClientNode *np) { XConfigureEvent event; const ScreenType *sp; Assert(np); memset(&event, 0, sizeof(event)); event.type = ConfigureNotify; event.event = np->window; event.window = np->window; if(np->state.status & STAT_FULLSCREEN) { sp = GetCurrentScreen(np->x, np->y); event.x = sp->x; event.y = sp->y; event.width = sp->width; event.height = sp->height; } else { event.x = np->x; event.y = np->y; event.width = np->width; event.height = np->height; } JXSendEvent(display, np->window, False, StructureNotifyMask, (XEvent*)&event); }
/** Send a JWM message to the root window. */ void SendJWMMessage(const char *message) { XEvent event; OpenConnection(); memset(&event, 0, sizeof(event)); event.xclient.type = ClientMessage; event.xclient.window = rootWindow; event.xclient.message_type = JXInternAtom(display, message, False); event.xclient.format = 32; JXSendEvent(display, rootWindow, False, SubstructureRedirectMask, &event); CloseConnection(); }
/** Initialize a dock component. */ void Create(TrayComponentType *cp) { XEvent event; Assert(cp); /* Map the dock window. */ if(cp->window != None) { JXResizeWindow(display, cp->window, cp->width, cp->height); JXMapRaised(display, cp->window); } /* Set the orientation atom. */ SetCardinalAtom(dock->cp->window, ATOM_NET_SYSTEM_TRAY_ORIENTATION, orientation); /* Get the selection if we don't already own it. * If we did already own it, getting it again would cause problems * with some clients due to the way restarts are handled. */ if(!owner) { owner = 1; JXSetSelectionOwner(display, dockAtom, dock->cp->window, CurrentTime); if(JUNLIKELY(JXGetSelectionOwner(display, dockAtom) != dock->cp->window)) { owner = 0; Warning(_("could not acquire system tray selection")); } else { memset(&event, 0, sizeof(event)); event.xclient.type = ClientMessage; event.xclient.window = rootWindow; event.xclient.message_type = atoms[ATOM_MANAGER]; event.xclient.format = 32; event.xclient.data.l[0] = CurrentTime; event.xclient.data.l[1] = dockAtom; event.xclient.data.l[2] = dock->cp->window; event.xclient.data.l[3] = 0; event.xclient.data.l[4] = 0; JXSendEvent(display, rootWindow, False, StructureNotifyMask, &event); } } }
/** Layout items on the dock. */ void UpdateDock(void) { XConfigureEvent event; DockNode *np; int x, y; int itemSize; Assert(dock); /* Determine the size of items in the dock. */ GetDockItemSize(&itemSize); x = 0; y = 0; memset(&event, 0, sizeof(event)); for(np = dock->nodes; np; np = np->next) { JXMoveResizeWindow(display, np->window, x, y, itemSize, itemSize); /* Reparent if this window likes to go other places. */ if(np->needs_reparent) { JXReparentWindow(display, np->window, dock->cp->window, x, y); } event.type = ConfigureNotify; event.event = np->window; event.window = np->window; event.x = x; event.y = y; event.width = itemSize; event.height = itemSize; JXSendEvent(display, np->window, False, StructureNotifyMask, (XEvent*)&event); if(orientation == SYSTEM_TRAY_ORIENTATION_HORZ) { x += itemSize; } else { y += itemSize; } } }
/** Send a client message to a window. */ void SendClientMessage(Window w, AtomType type, AtomType message) { XEvent event; int status; memset(&event, 0, sizeof(event)); event.xclient.type = ClientMessage; event.xclient.window = w; event.xclient.message_type = atoms[type]; event.xclient.format = 32; event.xclient.data.l[0] = atoms[message]; event.xclient.data.l[1] = eventTime; status = JXSendEvent(display, w, False, 0, &event); if(JUNLIKELY(status == False)) { Debug("SendClientMessage failed"); } }
/** 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; }
/** Set a client's full screen state. */ void SetClientFullScreen(ClientNode *np, char fullScreen) { XEvent event; int north, south, east, west; BoundingBox box; const ScreenType *sp; Assert(np); /* Make sure there's something to do. */ if(!fullScreen == !(np->state.status & STAT_FULLSCREEN)) { return; } if(!(np->state.border & BORDER_FULLSCREEN)) { return; } if(np->state.status & STAT_SHADED) { UnshadeClient(np); } if(fullScreen) { np->state.status |= STAT_FULLSCREEN; if(!(np->state.maxFlags)) { np->oldx = np->x; np->oldy = np->y; np->oldWidth = np->width; np->oldHeight = np->height; } sp = GetCurrentScreen(np->x, np->y); GetScreenBounds(sp, &box); GetBorderSize(&np->state, &north, &south, &east, &west); box.x += west; box.y += north; box.width -= east + west; box.height -= north + south; np->x = box.x; np->y = box.y; np->width = box.width; np->height = box.height; ResetBorder(np); } else { np->state.status &= ~STAT_FULLSCREEN; np->x = np->oldx; np->y = np->oldy; np->width = np->oldWidth; np->height = np->oldHeight; ConstrainSize(np); ConstrainPosition(np); if(np->state.maxFlags != MAX_NONE) { PlaceMaximizedClient(np, np->state.maxFlags); } ResetBorder(np); event.type = MapRequest; event.xmaprequest.send_event = True; event.xmaprequest.display = display; event.xmaprequest.parent = np->parent; event.xmaprequest.window = np->window; JXSendEvent(display, rootWindow, False, SubstructureRedirectMask, &event); } WriteState(np); SendConfigureEvent(np); RequireRestack(); }