/** Draw a specific tray. */ void DrawSpecificTray(const TrayType *tp) { TrayComponentType *cp; for(cp = tp->components; cp; cp = cp->next) { UpdateSpecificTray(tp, cp); } if(settings.trayDecorations == DECO_MOTIF) { JXSetForeground(display, rootGC, colors[COLOR_TRAY_UP]); JXDrawLine(display, tp->window, rootGC, 0, 0, tp->width - 1, 0); JXDrawLine(display, tp->window, rootGC, 0, tp->height - 1, 0, 0); JXSetForeground(display, rootGC, colors[COLOR_TRAY_DOWN]); JXDrawLine(display, tp->window, rootGC, 0, tp->height - 1, tp->width - 1, tp->height - 1); JXDrawLine(display, tp->window, rootGC, tp->width - 1, 0, tp->width - 1, tp->height - 1); } else { JXSetForeground(display, rootGC, colors[COLOR_TRAY_DOWN]); JXDrawRectangle(display, tp->window, rootGC, 0, 0, tp->width - 1, tp->height - 1); } }
/** Draw a specific tray. */ void DrawSpecificTray(const TrayType *tp) { TrayComponentType *cp; for(cp = tp->components; cp; cp = cp->next) { UpdateSpecificTray(tp, cp); } }
/** 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); } }
/** Draw a specific tray. */ void DrawSpecificTray(const TrayType *tp) { TrayComponentType *cp; int x; Assert(tp); /* Draw components. */ for(cp = tp->components; cp; cp = cp->next) { UpdateSpecificTray(tp, cp); } /* Draw the border. */ for(x = 0; x < tp->border; x++) { /* Top */ JXSetForeground(display, rootGC, colors[COLOR_TRAY_UP]); JXDrawLine(display, tp->window, rootGC, 0, x, tp->width - x - 1, x); /* Bottom */ JXSetForeground(display, rootGC, colors[COLOR_TRAY_DOWN]); JXDrawLine(display, tp->window, rootGC, x + 1, tp->height - x - 1, tp->width - x - 2, tp->height - x - 1); /* Left */ JXSetForeground(display, rootGC, colors[COLOR_TRAY_UP]); JXDrawLine(display, tp->window, rootGC, x, x, x, tp->height - x - 1); /* Right */ JXSetForeground(display, rootGC, colors[COLOR_TRAY_DOWN]); JXDrawLine(display, tp->window, rootGC, tp->width - x - 1, x + 1, tp->width - x - 1, tp->height - x - 1); } }
/** Process a button release. */ void ProcessActionRelease(struct ActionType *actions, struct TrayComponentType *cp, int x, int y, int button) { const ActionType *ap; const int mask = 1 << button; cp->grabbed = 0; if(cp->Redraw) { (cp->Redraw)(cp); UpdateSpecificTray(cp->tray, cp); } /* Since we grab the mouse, make sure the mouse is actually over * the button. */ if(x < 0 || x >= cp->width) { return; } if(y < 0 || y >= cp->height) { return; } /* Run the action (if any). */ for(ap = actions; ap; ap = ap->next) { if(ap->mask & mask) { if(ap->action && strlen(ap->action) > 0) { if(!strncmp(ap->action, "exec:", 5)) { RunCommand(ap->action + 5); } else if(!strcmp(ap->action, "showdesktop")) { ShowDesktop(); } } return; } } }
/** Process a button press. */ void ProcessActionPress(struct ActionType *actions, struct TrayComponentType *cp, int x, int y, int button) { const ScreenType *sp; const ActionType *ap; const int mask = 1 << button; int mwidth, mheight; int menu; menu = -1; for(ap = actions; ap; ap = ap->next) { if(ap->mask & mask) { if(ap->action && ap->action[0]) { if(strncmp(ap->action, "root:", 5) != 0) { /* Show the button being pressed. */ GrabMouse(cp->tray->window); cp->grabbed = 1; if(cp->Redraw) { (cp->Redraw)(cp); UpdateSpecificTray(cp->tray, cp); } return; } else { menu = GetRootMenuIndexFromString(&ap->action[5]); } } else { menu = 1; } break; } } if(menu < 0) { return; } GetRootMenuSize(menu, &mwidth, &mheight); sp = GetCurrentScreen(cp->screenx, cp->screeny); if(cp->tray->layout == LAYOUT_HORIZONTAL) { x = cp->screenx; if(cp->screeny + cp->height / 2 < sp->y + sp->height / 2) { y = cp->screeny + cp->height; } else { y = cp->screeny - mheight; } } else { y = cp->screeny; if(cp->screenx + cp->width / 2 < sp->x + sp->width / 2) { x = cp->screenx + cp->width; } else { x = cp->screenx - mwidth; } } cp->grabbed = 1; if(cp->Redraw) { (cp->Redraw)(cp); UpdateSpecificTray(cp->tray, cp); } ShowRootMenu(menu, x, y); cp->grabbed = 0; if(cp->Redraw) { (cp->Redraw)(cp); UpdateSpecificTray(cp->tray, cp); } }
/** Draw a specific task bar. */ void Render(const TaskBarType *bp) { TaskEntry *tp; char *displayName; ButtonNode button; int x, y; if(JUNLIKELY(shouldExit)) { return; } ClearTrayDrawable(bp->cp); if(!taskEntries) { UpdateSpecificTray(bp->cp->tray, bp->cp); return; } ResetButton(&button, bp->cp->pixmap); button.border = settings.trayDecorations == DECO_MOTIF; button.font = FONT_TASKLIST; button.height = bp->itemHeight; button.width = bp->itemWidth; button.text = NULL; x = 0; y = 0; for(tp = taskEntries; tp; tp = tp->next) { if(!ShouldShowEntry(tp)) { continue; } /* Check for an active or urgent window and count clients. */ ClientEntry *cp; unsigned clientCount = 0; button.type = BUTTON_TASK; for(cp = tp->clients; cp; cp = cp->next) { if(ShouldFocus(cp->client, 0)) { const char flash = (cp->client->state.status & STAT_FLASH) != 0; const char active = (cp->client->state.status & STAT_ACTIVE) && IsClientOnCurrentDesktop(cp->client); if(flash || active) { if(button.type == BUTTON_TASK) { button.type = BUTTON_TASK_ACTIVE; } else { button.type = BUTTON_TASK; } } clientCount += 1; } } button.x = x; button.y = y; if(!tp->clients->client->icon) { button.icon = GetDefaultIcon(); } else { button.icon = tp->clients->client->icon; } displayName = NULL; if(tp->clients->client->className && settings.groupTasks) { if(clientCount != 1) { const size_t len = strlen(tp->clients->client->className) + 16; displayName = Allocate(len); snprintf(displayName, len, "%s (%u)", tp->clients->client->className, clientCount); button.text = displayName; } else { button.text = tp->clients->client->className; } } else { button.text = tp->clients->client->name; } DrawButton(&button); if(displayName) { Release(displayName); } if(bp->layout == LAYOUT_HORIZONTAL) { x += bp->itemWidth; } else { y += bp->itemHeight; } } UpdateSpecificTray(bp->cp->tray, bp->cp); }