~ubuntu-branches/ubuntu/quantal/xdaliclock/quantal

« back to all changes in this revision

Viewing changes to X11/digital.c

  • Committer: Bazaar Package Importer
  • Author(s): Aaron Lehmann
  • Date: 2003-12-21 22:19:11 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20031221221911-257w35bqczk4i0l8
Tags: 2.20-1
New upstream version fixes Xinerama problems (Closes: #217684)

Show diffs side-by-side

added added

removed removed

Lines of Context:
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>
4
4
 *
5
5
 * Permission to use, copy, modify, distribute, and sell this software and its
15
15
# include "config.h"
16
16
#endif
17
17
 
 
18
#include <stdlib.h>
 
19
#include <string.h>
18
20
#include <stdio.h>
 
21
#include <sys/time.h>
19
22
#include <time.h>
 
23
 
20
24
#include <X11/Xlib.h>
21
25
#include <X11/Xutil.h>
22
26
#include <X11/Xos.h>
31
35
#include "usleep.h"
32
36
#include "vroot.h"
33
37
 
 
38
#ifndef _XSCREENSAVER_VROOT_H_
 
39
# error Error!  You have an old version of vroot.h!  Check -I args.
 
40
#endif /* _XSCREENSAVER_VROOT_H_ */
 
41
 
34
42
#define clock_usleep screenhack_usleep
35
43
 
36
44
#ifdef HAVE_SHAPE
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; /* #### */
 
207
 
 
208
static enum date_state { DTime, DDateIn, DDate, DDateOut, DDateOut2,
 
209
                         DDash, DDash2 }
 
210
  display_date;
200
211
 
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');
634
645
      test_hack = 0;
635
646
    }
636
 
  else if (! button_down)
 
647
  else if (display_date == DTime ||
 
648
           display_date == DDash ||
 
649
           display_date == DDash2)
637
650
    {
 
651
      if (display_date == DDash)
 
652
        display_date = DDash2;
 
653
      else if (display_date == DDash2)
 
654
        display_date = DTime;
 
655
 
638
656
      if (countdown)
639
657
        {
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;
646
664
        }
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;
667
685
 
 
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;
 
694
 
668
695
      switch (date_format)
669
696
        {
670
697
        case MMDDYY:
825
852
 
826
853
 
827
854
static void
828
 
initialize_window (Screen *screen, Window window)
 
855
initialize_window (Screen *screen, Window window, Bool external_p)
829
856
{
830
857
  Display *dpy = DisplayOfScreen (screen);
831
858
  XWindowAttributes xgwa;
855
882
  else
856
883
    attributes.background_pixel = bg_color.pixel;
857
884
  attributes.event_mask = (xgwa.your_event_mask |
858
 
                           KeyPressMask | ButtonPressMask |
859
 
                           ButtonReleaseMask | StructureNotifyMask |
860
 
                           ExposureMask );
 
885
                           KeyPressMask | StructureNotifyMask | ExposureMask );
861
886
  attributes.do_not_propagate_mask = 0;
862
887
 
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,
867
 
       however... */
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.)
 
891
   */
 
892
  if (! (xgwa.all_event_masks & (ButtonPressMask | ButtonReleaseMask)))
 
893
    attributes.event_mask |= (ButtonPressMask | ButtonReleaseMask);
 
894
 
 
895
  XChangeWindowAttributes (dpy, window, attribute_mask, &attributes);
869
896
 
870
897
  /* Center stuff in window correctly when first created */
871
898
  {
884
911
      }
885
912
  }
886
913
 
887
 
  XStoreName (dpy, window, window_title);
 
914
  if (! external_p)
 
915
    XStoreName (dpy, window, window_title);
888
916
 
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);
941
969
 
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,
946
 
                            0, 0, 32767, 32767);
 
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);
947
974
}
948
975
 
949
976
 
1051
1078
static void
1052
1079
draw_colon (Display *dpy, Drawable pixmap, Window window)
1053
1080
{
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));
1063
1090
}
1064
1091
 
1065
1092
 
1073
1100
 */
1074
1101
 
1075
1102
 
1076
 
static int event_loop (Screen *, Window);
 
1103
static int event_loop (Screen *, Window, Bool);
1077
1104
 
1078
1105
void
1079
1106
initialize_digital (Screen *screen, Visual *visual, Colormap cmap,
1100
1127
 
1101
1128
 
1102
1129
void
1103
 
run_digital (Screen *screen, Window window)
 
1130
run_digital (Screen *screen, Window window, Bool external_p)
1104
1131
{
1105
1132
  Display *dpy = DisplayOfScreen (screen);
1106
1133
  int i;
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);
1111
1138
 
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);
1119
1146
    }
1120
1147
 
1121
 
  event_loop (screen, window); /* wait for initial mapwindow event */
 
1148
  /* wait for initial mapwindow event */
 
1149
  event_loop (screen, window, external_p);
1122
1150
 
1123
1151
  XFillRectangle (dpy, window, window_erase_gc,
1124
1152
                  0, 0, x_offsets [ndigits-1] + character_width,
1131
1159
      long clock;
1132
1160
      static int date = 0, was = 0;
1133
1161
      int different_minute;
 
1162
      enum date_state odate = display_date;
1134
1163
 
1135
1164
    repaint_now:
1136
1165
 
1137
1166
      clock = fill_time_digits ();
1138
1167
 
1139
1168
      different_minute = (time_digits [3] != last_time_digits [3]);
 
1169
      if (odate != display_date)
 
1170
        draw_colon (dpy, pixmap, window);
1140
1171
 
1141
1172
      for (n = 0; n < ndigits; n++)
1142
1173
        if (time_digits [n] == last_time_digits [n])
1339
1370
                      character_height);
1340
1371
 
1341
1372
#ifdef DRYRUN
1342
 
      event_loop (screen, window);
 
1373
      event_loop (screen, window, external_p);
1343
1374
#else /* !DRYRUN */
1344
1375
    if (minutes_only)
1345
1376
      {
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);
1349
 
 
1350
1380
#ifdef HAVE_SELECT
1351
 
        if (! do_cycle)
1352
 
          {
1353
 
            /* If we don't have to cycle colors, we can block until
1354
 
               either a minute has almost elapsed, or an event comes
1355
 
               in.  */
1356
 
            fd_set set;
1357
 
            struct timeval until_minute;
1358
 
            int cfd = ConnectionNumber (DisplayOfScreen (screen));
1359
 
 
1360
 
            FD_ZERO (&set);
1361
 
 
1362
 
            for (;;)
1363
 
              {
1364
 
                FD_SET (cfd, &set);
1365
 
                until_minute.tv_sec = 59 - tm->tm_sec;
1366
 
                until_minute.tv_usec = 0;
1367
 
 
1368
 
                if (select (cfd + 1, &set, 0, 0, &until_minute) == 0)
1369
 
                  break;
1370
 
 
1371
 
                if (event_loop (screen, window))
1372
 
                  goto repaint_now;
1373
 
              }
1374
 
          }
 
1381
   if (! do_cycle)
 
1382
     {
 
1383
       /* If we don't have to cycle colors, we can block until
 
1384
          either a minute has almost elapsed, or an event comes
 
1385
          in.  */
 
1386
       fd_set set;
 
1387
       struct timeval until_minute;
 
1388
       int cfd = ConnectionNumber (DisplayOfScreen (screen));
 
1389
 
 
1390
       FD_ZERO (&set);
 
1391
 
 
1392
       for (;;)
 
1393
         {
 
1394
       FD_SET (cfd, &set);
 
1395
       until_minute.tv_sec = 59 - tm->tm_sec;
 
1396
       until_minute.tv_usec = 0;
 
1397
 
 
1398
       if (select (cfd + 1, &set, 0, 0, &until_minute) == 0)
 
1399
         break;
 
1400
 
 
1401
       if (event_loop (screen, window, external_p))
 
1402
         goto repaint_now;
 
1403
         }
 
1404
     }
1375
1405
#endif
1376
1406
 
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.
1384
1414
               */
1385
 
            if (event_loop (screen, window))
 
1415
            if (event_loop (screen, window, external_p))
1386
1416
              break;
1387
1417
 
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.
1415
1445
             */
1416
 
            if (event_loop (screen, window))
 
1446
            if (event_loop (screen, window, external_p))
1417
1447
              break;
1418
1448
          }
1419
1449
      }
1459
1489
}
1460
1490
 
1461
1491
static int
1462
 
event_loop (Screen *screen, Window window)
 
1492
event_loop (Screen *screen, Window window, Bool external_p)
1463
1493
{
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);
1469
 
  /* #### */
1470
 
  while (XPending (dpy) || !(mapped_p || root_p) ||
1471
 
         (wait_for_buttonup && button_down))
 
1498
 
 
1499
  while (XPending (dpy) || !(mapped_p || external_p))
1472
1500
    {
1473
1501
      XEvent event;
1474
1502
      XNextEvent (dpy, &event);
1513
1541
          }
1514
1542
          break;
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;
1518
1545
          redraw_p = 1;
 
1546
          draw_colon (dpy, pixmap, window);
1519
1547
          break;
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;
 
1553
 
1523
1554
          redraw_p = 1;
1524
1555
          break;
1525
1556
        case ConfigureNotify: