/** Update all task bars. */ void UpdateTaskBar(void) { TaskBarType *bp; int lastHeight = -1; if(JUNLIKELY(shouldExit)) { return; } for(bp = bars; bp; bp = bp->next) { if(bp->layout == LAYOUT_VERTICAL) { TaskEntry *tp; lastHeight = bp->cp->requestedHeight; if(bp->userHeight > 0) { bp->itemHeight = bp->userHeight; } else { bp->itemHeight = GetStringHeight(FONT_TASKLIST) + 12; } bp->cp->requestedHeight = 0; for(tp = taskEntries; tp; tp = tp->next) { if(ShouldShowEntry(tp)) { bp->cp->requestedHeight += bp->itemHeight; } } bp->cp->requestedHeight = Max(1, bp->cp->requestedHeight); if(lastHeight != bp->cp->requestedHeight) { ResizeTray(bp->cp->tray); } } ComputeItemSize(bp); Render(bp); } }
/** Remove a window from the dock. */ char HandleDockDestroy(Window win) { DockNode **np; /* If no dock is running, just return. */ if(!dock) { return 0; } for(np = &dock->nodes; *np; np = &(*np)->next) { DockNode *dp = *np; if(dp->window == win) { /* Remove the window from our list. */ *np = dp->next; Release(dp); /* Update the requested size. */ GetDockSize(&dock->cp->requestedWidth, &dock->cp->requestedHeight); /* Resize the tray. */ ResizeTray(dock->cp->tray); return 1; } } return 0; }
/** 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; }
/** Process an event on a swallowed window. */ int ProcessSwallowEvent(const XEvent *event) { SwallowNode *np; int width, height; for(np = swallowNodes; np; np = np->next) { if(event->xany.window == np->cp->window) { switch(event->type) { case DestroyNotify: np->cp->window = None; np->cp->requestedWidth = 1; np->cp->requestedHeight = 1; ResizeTray(np->cp->tray); break; case ResizeRequest: np->cp->requestedWidth = event->xresizerequest.width + np->border * 2; np->cp->requestedHeight = event->xresizerequest.height + np->border * 2; ResizeTray(np->cp->tray); break; case ConfigureNotify: /* I don't think this should be necessary, but somehow * resize requests slip by sometimes... */ width = event->xconfigure.width + np->border * 2; height = event->xconfigure.height + np->border * 2; if( width != np->cp->requestedWidth && height != np->cp->requestedHeight) { np->cp->requestedWidth = width; np->cp->requestedHeight = height; ResizeTray(np->cp->tray); } break; default: break; } return 1; } } return 0; }
/** Draw a clock tray component. */ void DrawClock(ClockType *clk, const TimeType *now) { TrayComponentType *cp; const char *timeString; int width; int rwidth; /* Only draw if the time changed. */ if(now->seconds == clk->lastTime.seconds) { return; } /* Clear the area. */ cp = clk->cp; if(colors[COLOR_CLOCK_BG1] == colors[COLOR_CLOCK_BG2]) { JXSetForeground(display, rootGC, colors[COLOR_CLOCK_BG1]); JXFillRectangle(display, cp->pixmap, rootGC, 0, 0, cp->width, cp->height); } else { DrawHorizontalGradient(cp->pixmap, rootGC, colors[COLOR_CLOCK_BG1], colors[COLOR_CLOCK_BG2], 0, 0, cp->width, cp->height); } /* Determine if the clock is the right size. */ timeString = GetTimeString(clk->format, clk->zone); width = GetStringWidth(FONT_CLOCK, timeString); rwidth = width + 4; if(rwidth == clk->cp->requestedWidth || clk->userWidth) { /* Draw the clock. */ RenderString(cp->pixmap, FONT_CLOCK, COLOR_CLOCK_FG, (cp->width - width) / 2, (cp->height - GetStringHeight(FONT_CLOCK)) / 2, cp->width, timeString); UpdateSpecificTray(clk->cp->tray, clk->cp); } else { /* Wrong size. Resize. */ clk->cp->requestedWidth = rwidth; ResizeTray(clk->cp->tray); } }
/** 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); }