1
1
/* xdaliclock - a melting digital clock
2
* Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
2
* Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2002, 2003
3
3
* Jamie Zawinski <jwz@jwz.org>
5
5
* Permission to use, copy, modify, distribute, and sell this software and its
196
204
static int colon_char_width;
197
205
static int time_digits [6];
198
206
static int last_time_digits [6];
199
static int button_down = 0; /* #### */
208
static enum date_state { DTime, DDateIn, DDate, DDateOut, DDateOut2,
201
212
static Pixmap memory_pig_zeros [9] [10];
202
213
static Pixmap memory_pig_digits [8] [10];
633
644
(test_hack == '-' ? -1 : test_hack - '0');
636
else if (! button_down)
647
else if (display_date == DTime ||
648
display_date == DDash ||
649
display_date == DDash2)
651
if (display_date == DDash)
652
display_date = DDash2;
653
else if (display_date == DDash2)
654
display_date = DTime;
640
658
int delta = countdown - clock;
641
659
if (delta < 0) delta = -delta;
642
660
tm->tm_sec = delta % 60;
643
661
tm->tm_min = (delta / 60) % 60;
644
tm->tm_hour = (delta / (60 * 60)) % 60;
662
tm->tm_hour = (delta / (60 * 60)) % 100;
645
663
twelve_hour_time = 0;
647
665
if (twelve_hour_time && tm->tm_hour > 12) tm->tm_hour -= 12;
665
683
y0 = (y0 - (y0 % 10)) / 10;
666
684
y1 = tm->tm_year % 10;
686
if (display_date == DDateIn)
687
display_date = DDate;
688
else if (display_date == DDateOut)
689
display_date = DDateOut2;
690
else if (display_date == DDateOut2)
691
display_date = DDash;
692
else if (display_date == DDash)
693
display_date = DDash2;
668
695
switch (date_format)
828
initialize_window (Screen *screen, Window window)
855
initialize_window (Screen *screen, Window window, Bool external_p)
830
857
Display *dpy = DisplayOfScreen (screen);
831
858
XWindowAttributes xgwa;
856
883
attributes.background_pixel = bg_color.pixel;
857
884
attributes.event_mask = (xgwa.your_event_mask |
858
KeyPressMask | ButtonPressMask |
859
ButtonReleaseMask | StructureNotifyMask |
885
KeyPressMask | StructureNotifyMask | ExposureMask );
861
886
attributes.do_not_propagate_mask = 0;
863
if (window != xgwa.root &&
864
window != RootWindowOfScreen (screen))
865
/* On SGIs, you get BadAccess if you try to frob the root window,
866
or a window owned by another client. Other servers allow this,
868
XChangeWindowAttributes (dpy, window, attribute_mask, &attributes);
888
/* Select ButtonPress and ButtonRelease events on the window only if no other
889
app has already selected them (only one app can select ButtonPress at a
890
time: BadAccess results.)
892
if (! (xgwa.all_event_masks & (ButtonPressMask | ButtonReleaseMask)))
893
attributes.event_mask |= (ButtonPressMask | ButtonReleaseMask);
895
XChangeWindowAttributes (dpy, window, attribute_mask, &attributes);
870
897
/* Center stuff in window correctly when first created */
887
XStoreName (dpy, window, window_title);
915
XStoreName (dpy, window, window_title);
889
917
pixmap = XCreatePixmap (dpy, window,
890
918
x_offsets [ndigits-1] + character_width + 1,
939
967
0, 0, x_offsets [ndigits-1] + character_width + 1,
940
968
character_height + 1);
942
/* XClearWindow() depends on us being able to set the background
943
color of the window, which we can't necessarily do if it is the
944
root window. So fill instead. */
945
XFillRectangle (dpy, window, window_erase_gc,
970
/* XClearWindow() depends on us being able to set the background
971
color of the window, which we can't necessarily do if it is the
972
root window. So fill instead. */
973
XFillRectangle (dpy, window, window_erase_gc, 0, 0, 32767, 32767);
1052
1079
draw_colon (Display *dpy, Drawable pixmap, Window window)
1054
Pixmap glyph = button_down ? slash : colon;
1081
Pixmap glyph = (display_date == DTime ? colon : slash);
1055
1082
XCopyPlane (dpy, glyph, pixmap, pixmap_draw_gc,
1056
1083
0, 0, character_width, character_height,
1057
1084
x_offsets [1] + character_width, 0, 1);
1059
1086
XCopyPlane (dpy, glyph, pixmap, pixmap_draw_gc,
1060
1087
0, 0, character_width, character_height,
1061
1088
x_offsets [3] + character_width, 0, 1);
1062
XStoreName (dpy, window, button_down ? hacked_version : window_title);
1089
XStoreName (dpy, window, (glyph == slash ? hacked_version : window_title));
1076
static int event_loop (Screen *, Window);
1103
static int event_loop (Screen *, Window, Bool);
1079
1106
initialize_digital (Screen *screen, Visual *visual, Colormap cmap,
1103
run_digital (Screen *screen, Window window)
1130
run_digital (Screen *screen, Window window, Bool external_p)
1105
1132
Display *dpy = DisplayOfScreen (screen);
1107
1134
int ndigits = (minutes_only ? 4 : 6);
1108
1135
XWindowAttributes xgwa;
1109
1136
XGetWindowAttributes (dpy, window, &xgwa);
1110
initialize_window (screen, window);
1137
initialize_window (screen, window, external_p);
1112
1139
if (be_a_pig > 0)
1113
1140
fill_pig_cache (dpy, window, current_frames [0]);
1118
1145
set_current_scanlines (current_frames [i], clear_frame);
1121
event_loop (screen, window); /* wait for initial mapwindow event */
1148
/* wait for initial mapwindow event */
1149
event_loop (screen, window, external_p);
1123
1151
XFillRectangle (dpy, window, window_erase_gc,
1124
1152
0, 0, x_offsets [ndigits-1] + character_width,
1132
1160
static int date = 0, was = 0;
1133
1161
int different_minute;
1162
enum date_state odate = display_date;
1137
1166
clock = fill_time_digits ();
1139
1168
different_minute = (time_digits [3] != last_time_digits [3]);
1169
if (odate != display_date)
1170
draw_colon (dpy, pixmap, window);
1141
1172
for (n = 0; n < ndigits; n++)
1142
1173
if (time_digits [n] == last_time_digits [n])
1339
1370
character_height);
1342
event_loop (screen, window);
1373
event_loop (screen, window, external_p);
1343
1374
#else /* !DRYRUN */
1344
1375
if (minutes_only)
1346
1377
time_t now = time ((time_t *) 0);
1347
1378
struct tm *tm = localtime (&now);
1348
1379
time_t target = now + (60 - tm->tm_sec);
1350
1380
#ifdef HAVE_SELECT
1353
/* If we don't have to cycle colors, we can block until
1354
either a minute has almost elapsed, or an event comes
1357
struct timeval until_minute;
1358
int cfd = ConnectionNumber (DisplayOfScreen (screen));
1365
until_minute.tv_sec = 59 - tm->tm_sec;
1366
until_minute.tv_usec = 0;
1368
if (select (cfd + 1, &set, 0, 0, &until_minute) == 0)
1371
if (event_loop (screen, window))
1383
/* If we don't have to cycle colors, we can block until
1384
either a minute has almost elapsed, or an event comes
1387
struct timeval until_minute;
1388
int cfd = ConnectionNumber (DisplayOfScreen (screen));
1395
until_minute.tv_sec = 59 - tm->tm_sec;
1396
until_minute.tv_usec = 0;
1398
if (select (cfd + 1, &set, 0, 0, &until_minute) == 0)
1401
if (event_loop (screen, window, external_p))
1377
1407
/* This is slightly sleazy: when in no-seconds mode, wake up
1382
1412
/* if event_loop returns true, we need to go and repaint stuff
1383
1413
right now, instead of waiting for the minute to elapse.
1385
if (event_loop (screen, window))
1415
if (event_loop (screen, window, external_p))
1388
1418
if (now == target-1) /* the home stretch; sync up */
1413
1443
/* if event_loop returns true, we need to go and repaint stuff
1414
1444
right now, instead of waiting for the second to elapse.
1416
if (event_loop (screen, window))
1446
if (event_loop (screen, window, external_p))
1462
event_loop (Screen *screen, Window window)
1492
event_loop (Screen *screen, Window window, Bool external_p)
1464
1494
Display *dpy = DisplayOfScreen (screen);
1465
1495
static int mapped_p = 0;
1466
int wait_for_buttonup = button_down;
1467
1496
int redraw_p = 0;
1468
1497
XSync (dpy, False);
1470
while (XPending (dpy) || !(mapped_p || root_p) ||
1471
(wait_for_buttonup && button_down))
1499
while (XPending (dpy) || !(mapped_p || external_p))
1474
1502
XNextEvent (dpy, &event);
1515
1543
case ButtonPress:
1516
button_down |= (1<<event.xbutton.button);
1517
if (! wait_for_buttonup) draw_colon (dpy, pixmap, window);
1544
display_date = DDateIn;
1546
draw_colon (dpy, pixmap, window);
1520
1548
case ButtonRelease:
1521
button_down &= ~(1<<event.xbutton.button);
1522
if (! button_down) draw_colon (dpy, pixmap, window);
1549
if (display_date == DDate) /* turn off faster if already up */
1550
display_date = DDash;
1551
else if (display_date != DTime)
1552
display_date = DDateOut;
1525
1556
case ConfigureNotify: