/** Determine if this is a window to be swallowed, if it is, swallow it. */ int CheckSwallowMap(const XMapEvent *event) { SwallowNode *np; XClassHint hint; XWindowAttributes attr; for(np = swallowNodes; np; np = np->next) { if(np->cp->window != None) { continue; } Assert(np->cp->tray->window != None); if(JXGetClassHint(display, event->window, &hint)) { if(!strcmp(hint.res_name, np->name)) { /* Swallow the window. */ JXSelectInput(display, event->window, StructureNotifyMask | ResizeRedirectMask); JXAddToSaveSet(display, event->window); JXSetWindowBorder(display, event->window, colors[COLOR_TRAY_BG]); JXReparentWindow(display, event->window, np->cp->tray->window, 0, 0); JXMapRaised(display, event->window); JXFree(hint.res_name); JXFree(hint.res_class); np->cp->window = event->window; /* Update the size. */ JXGetWindowAttributes(display, event->window, &attr); np->border = attr.border_width; if(!np->userWidth) { np->cp->requestedWidth = attr.width + 2 * np->border; } if(!np->userHeight) { np->cp->requestedHeight = attr.height + 2 * np->border; } ResizeTray(np->cp->tray); return 1; } else { JXFree(hint.res_name); JXFree(hint.res_class); } } } return 0; }
/** 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); } } }
/** Add a window to the dock. */ void DockWindow(Window win) { DockNode *np; /* If no dock is running, just return. */ if(!dock) { return; } /* Make sure we have a valid window to add. */ if(JUNLIKELY(win == None)) { return; } /* If this window is already docked ignore it. */ for(np = dock->nodes; np; np = np->next) { if(np->window == win) { return; } } /* Add the window to our list. */ np = Allocate(sizeof(DockNode)); np->window = win; np->needs_reparent = 0; np->next = dock->nodes; dock->nodes = np; /* Update the requested size. */ GetDockSize(&dock->cp->requestedWidth, &dock->cp->requestedHeight); /* It's safe to reparent at (0, 0) since we call * ResizeTray which will invoke the Resize callback. */ JXAddToSaveSet(display, win); JXReparentWindow(display, win, dock->cp->window, 0, 0); JXMapRaised(display, win); /* Resize the tray containing the dock. */ ResizeTray(dock->cp->tray); }
/** Show a popup window. */ void ShowPopup(int x, int y, const char *text, const PopupMaskType context) { const ScreenType *sp; Assert(text); if(!(settings.popupMask & context)) { return; } if(popup.text) { if(x == popup.x && y == popup.y && !strcmp(popup.text, text)) { // This popup is already shown. return; } Release(popup.text); popup.text = NULL; } if(text[0] == 0) { return; } GetMousePosition(&popup.mx, &popup.my, &popup.mw); popup.text = CopyString(text); popup.height = GetStringHeight(FONT_POPUP) + 2; popup.width = GetStringWidth(FONT_POPUP, popup.text) + 9; sp = GetCurrentScreen(x, y); if(popup.width > sp->width) { popup.width = sp->width; } popup.x = x; if(y + 2 * popup.height + 2 >= sp->height) { popup.y = y - popup.height - 2; } else { popup.y = y + popup.height + 2; } if(popup.width + popup.x > sp->x + sp->width) { popup.x = sp->x + sp->width - popup.width - 2; } if(popup.height + popup.y > sp->y + sp->height) { popup.y = sp->y + sp->height - popup.height - 2; } if(popup.x < 2) { popup.x = 2; } if(popup.y < 2) { popup.y = 2; } if(popup.window == None) { XSetWindowAttributes attr; unsigned long attrMask = 0; attrMask |= CWEventMask; attr.event_mask = ExposureMask | PointerMotionMask | PointerMotionHintMask; attrMask |= CWSaveUnder; attr.save_under = True; attrMask |= CWDontPropagate; attr.do_not_propagate_mask = PointerMotionMask | ButtonPressMask | ButtonReleaseMask; popup.window = JXCreateWindow(display, rootWindow, popup.x, popup.y, popup.width, popup.height, 0, CopyFromParent, InputOutput, CopyFromParent, attrMask, &attr); SetAtomAtom(popup.window, ATOM_NET_WM_WINDOW_TYPE, ATOM_NET_WM_WINDOW_TYPE_NOTIFICATION); JXMapRaised(display, popup.window); } else { JXMoveResizeWindow(display, popup.window, popup.x, popup.y, popup.width, popup.height); JXFreePixmap(display, popup.pmap); } popup.pmap = JXCreatePixmap(display, popup.window, popup.width, popup.height, rootDepth); JXSetForeground(display, rootGC, colors[COLOR_POPUP_BG]); JXFillRectangle(display, popup.pmap, rootGC, 0, 0, popup.width - 1, popup.height - 1); JXSetForeground(display, rootGC, colors[COLOR_POPUP_OUTLINE]); JXDrawRectangle(display, popup.pmap, rootGC, 0, 0, popup.width - 1, popup.height - 1); RenderString(popup.pmap, FONT_POPUP, COLOR_POPUP_FG, 4, 1, popup.width, popup.text); JXCopyArea(display, popup.pmap, popup.window, rootGC, 0, 0, popup.width, popup.height, 0, 0); }