From a041d9898e6d699bd8c0c25482ec574feb03c547 Mon Sep 17 00:00:00 2001 From: "John Ankarstr\\xf6m" Date: Sat, 29 May 2021 12:54:47 +0200 Subject: First commit This is the original state of the released tarball for JWM 1.8, which will serve as my starting point for further modifications. --- src/clock.c | 332 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 332 insertions(+) create mode 100644 src/clock.c (limited to 'src/clock.c') diff --git a/src/clock.c b/src/clock.c new file mode 100644 index 0000000..147c1f6 --- /dev/null +++ b/src/clock.c @@ -0,0 +1,332 @@ +/** + * @file clock.c + * @author Joe Wingbermuehle + * @date 2005-2006 + * + * @brief Clock tray component. + * + */ + +#include "jwm.h" +#include "clock.h" +#include "tray.h" +#include "color.h" +#include "font.h" +#include "timing.h" +#include "main.h" +#include "root.h" +#include "cursor.h" +#include "popup.h" +#include "misc.h" + +/** Structure to respresent a clock tray component. */ +typedef struct ClockType { + + TrayComponentType *cp; /**< Common component data. */ + + char *format; /**< The time format to use. */ + char *command; /**< A command to run when clicked. */ + char shortTime[80]; /**< Currently displayed time. */ + + /* The following are used to control popups. */ + int mousex; /**< Last mouse x-coordinate. */ + int mousey; /**< Last mouse y-coordinate. */ + TimeType mouseTime; /**< Time of the last mouse motion. */ + + int userWidth; /**< User-specified clock width (or 0). */ + + struct ClockType *next; /**< Next clock in the list. */ + +} ClockType; + +/** The default time format to use. */ +static const char *DEFAULT_FORMAT = "%I:%M %p"; + +static ClockType *clocks; +static TimeType lastUpdate = ZERO_TIME; + +static void Create(TrayComponentType *cp); +static void Resize(TrayComponentType *cp); +static void Destroy(TrayComponentType *cp); +static void ProcessClockButtonEvent(TrayComponentType *cp, + int x, int y, int mask); +static void ProcessClockMotionEvent(TrayComponentType *cp, + int x, int y, int mask); + +static void DrawClock(ClockType *clk, const TimeType *now, int x, int y); + +/** Initialize clocks. */ +void InitializeClock() { + clocks = NULL; +} + +/** Start clock(s). */ +void StartupClock() { + + ClockType *clk; + + for(clk = clocks; clk; clk = clk->next) { + if(clk->cp->requestedWidth == 0) { + clk->cp->requestedWidth = GetStringWidth(FONT_CLOCK, clk->format) + 4; + } + if(clk->cp->requestedHeight == 0) { + clk->cp->requestedHeight = GetStringHeight(FONT_CLOCK) + 4; + } + } + +} + +/** Stop clock(s). */ +void ShutdownClock() { +} + +/** Destroy clock(s). */ +void DestroyClock() { + + ClockType *cp; + + while(clocks) { + cp = clocks->next; + + if(clocks->format) { + Release(clocks->format); + } + if(clocks->command) { + Release(clocks->command); + } + + Release(clocks); + clocks = cp; + } + +} + +/** Create a clock tray component. */ +TrayComponentType *CreateClock(const char *format, const char *command, + int width, int height) { + + TrayComponentType *cp; + ClockType *clk; + + clk = Allocate(sizeof(ClockType)); + clk->next = clocks; + clocks = clk; + + clk->mousex = 0; + clk->mousey = 0; + clk->mouseTime.seconds = 0; + clk->mouseTime.ms = 0; + clk->userWidth = 0; + + if(!format) { + format = DEFAULT_FORMAT; + } + clk->format = CopyString(format); + + clk->command = CopyString(command); + + clk->shortTime[0] = 0; + + cp = CreateTrayComponent(); + cp->object = clk; + clk->cp = cp; + if(width > 0) { + cp->requestedWidth = width; + clk->userWidth = 1; + } else { + cp->requestedWidth = 0; + clk->userWidth = 0; + } + cp->requestedHeight = height; + + cp->Create = Create; + cp->Resize = Resize; + cp->Destroy = Destroy; + cp->ProcessButtonEvent = ProcessClockButtonEvent; + cp->ProcessMotionEvent = ProcessClockMotionEvent; + + return cp; + +} + +/** Initialize a clock tray component. */ +void Create(TrayComponentType *cp) { + + ClockType *clk; + + Assert(cp); + + clk = (ClockType*)cp->object; + + Assert(clk); + + cp->pixmap = JXCreatePixmap(display, rootWindow, cp->width, cp->height, + rootDepth); + + JXSetForeground(display, rootGC, colors[COLOR_CLOCK_BG]); + JXFillRectangle(display, cp->pixmap, rootGC, 0, 0, cp->width, cp->height); + +} + +/** Resize a clock tray component. */ +void Resize(TrayComponentType *cp) { + + ClockType *clk; + TimeType now; + int x, y; + + Assert(cp); + + clk = (ClockType*)cp->object; + + Assert(clk); + + if(cp->pixmap != None) { + JXFreePixmap(display, cp->pixmap); + } + + cp->pixmap = JXCreatePixmap(display, rootWindow, cp->width, cp->height, + rootDepth); + + clk->shortTime[0] = 0; + + GetCurrentTime(&now); + GetMousePosition(&x, &y); + DrawClock(clk, &now, x, y); + +} + +/** Destroy a clock tray component. */ +void Destroy(TrayComponentType *cp) { + + ClockType *clk; + + Assert(cp); + + clk = (ClockType*)cp->object; + + Assert(clk); + + if(cp->pixmap != None) { + JXFreePixmap(display, cp->pixmap); + } +} + +/** Process a click event on a clock tray component. */ +void ProcessClockButtonEvent(TrayComponentType *cp, int x, int y, int mask) { + + ClockType *clk; + + Assert(cp); + + clk = (ClockType*)cp->object; + + Assert(clk); + + if(clk->command) { + RunCommand(clk->command); + } + +} + +/** Process a motion event on a clock tray component. */ +void ProcessClockMotionEvent(TrayComponentType *cp, + int x, int y, int mask) { + + Assert(cp); + + ClockType *clk = (ClockType*)cp->object; + clk->mousex = cp->screenx + x; + clk->mousey = cp->screeny + y; + GetCurrentTime(&clk->mouseTime); + +} + +/** Update a clock tray component. */ +void SignalClock(const TimeType *now, int x, int y) { + + ClockType *cp; + int shouldDraw; + char *longTime; + time_t t; + + Assert(now); + + /* Determine if we should update the clock(s). */ + if(GetTimeDifference(&lastUpdate, now) > 900) { + shouldDraw = 1; + lastUpdate = *now; + } else { + shouldDraw = 0; + } + + /* Update each clock. */ + for(cp = clocks; cp; cp = cp->next) { + + if(shouldDraw) { + DrawClock(cp, now, x, y); + } + + if(abs(cp->mousex - x) < POPUP_DELTA + && abs(cp->mousey - y) < POPUP_DELTA) { + if(GetTimeDifference(now, &cp->mouseTime) >= popupDelay) { + time(&t); + longTime = asctime(localtime(&t)); + Trim(longTime); + ShowPopup(x, y, longTime); + } + } + + } + +} + +/** Draw a clock tray component. */ +void DrawClock(ClockType *clk, const TimeType *now, int x, int y) { + + TrayComponentType *cp; + const char *shortTime; + int width; + int rwidth; + + Assert(clk); + Assert(now); + + /* Only draw if the label changed. */ + shortTime = GetTimeString(clk->format); + if(!strcmp(clk->shortTime, shortTime)) { + return; + } + strcpy(clk->shortTime, shortTime); + + cp = clk->cp; + + /* Clear the area. */ + JXSetForeground(display, rootGC, colors[COLOR_CLOCK_BG]); + JXFillRectangle(display, cp->pixmap, rootGC, 0, 0, + cp->width, cp->height); + + /* Determine if the clock is the right size. */ + width = GetStringWidth(FONT_CLOCK, shortTime); + rwidth = width + 4; + if(rwidth == clk->cp->requestedWidth || clk->userWidth) { + + /* Draw the clock. */ + RenderString(cp->pixmap, FONT_CLOCK, COLOR_CLOCK_FG, + cp->width / 2 - width / 2, + cp->height / 2 - GetStringHeight(FONT_CLOCK) / 2, + cp->width, NULL, shortTime); + + UpdateSpecificTray(clk->cp->tray, clk->cp); + + } else { + + /* Wrong size. Resize. */ + clk->cp->requestedWidth = rwidth; + ResizeTray(clk->cp->tray); + + } + +} + + -- cgit v1.2.3