~ubuntu-branches/ubuntu/quantal/xscreensaver/quantal

« back to all changes in this revision

Viewing changes to driver/windows.c

  • Committer: Bazaar Package Importer
  • Author(s): Ted Gould
  • Date: 2008-08-28 16:15:25 UTC
  • mfrom: (1.1.6 upstream) (2.1.3 lenny)
  • Revision ID: james.westby@ubuntu.com-20080828161525-mxga521aoezxjq8h
Tags: 5.07-0ubuntu1
* Upgrade upstream version
* debian/control: Remove suggest xdaliclock as it is no longer
  included
* Remove 10_jwz-screensaver-randr-patch-3.patch as it has been merged
  upstream.
* Add 24_hacks_xsublim_enable.patch as it seems that xsublim was dropped
  from the build files.  There is nothing in the Changelog about it
  so I believe it was accidental.
* Updating the .desktop files from the XML files using gnome-screensaver's
  utility to do so.  Lots of text updates.  Also:
    * Added: abstractile.desktop
    * Added: cwaves.desktop
    * Added: m6502.desktop
    * Added: skytentacles.desktop
    * Removed: xteevee.desktop
* xscreensaver-gl-extra.files: Added skytentacles
* xscreensaver-data-extra.files: Added abstractile, cwaves and m6502
* xscreensaver-data.files: Remove partial abstractile, m6502 and cwaves

Show diffs side-by-side

added added

removed removed

Lines of Context:
226
226
}
227
227
 
228
228
 
 
229
static void
 
230
ungrab_keyboard_and_mouse (saver_info *si)
 
231
{
 
232
  ungrab_mouse (si);
 
233
  ungrab_kbd (si);
 
234
}
 
235
 
 
236
 
229
237
static Bool
230
238
grab_keyboard_and_mouse (saver_info *si, Window window, Cursor cursor,
231
239
                         int screen_no)
291
299
   */
292
300
 
293
301
  if (kstatus != GrabSuccess)   /* Do not blank without a kbd grab.   */
294
 
    return False;
 
302
    {
 
303
      /* If we didn't get both grabs, release the one we did get. */
 
304
      ungrab_keyboard_and_mouse (si);
 
305
      return False;
 
306
    }
295
307
 
296
308
  return True;                  /* Grab is good, go ahead and blank.  */
297
309
}
298
310
 
299
 
static void
300
 
ungrab_keyboard_and_mouse (saver_info *si)
301
 
{
302
 
  ungrab_mouse (si);
303
 
  ungrab_kbd (si);
304
 
}
305
 
 
306
311
 
307
312
int
308
313
move_mouse_grab (saver_info *si, Window to, Cursor cursor, int to_screen_no)
393
398
                   (char *) id);
394
399
          status = True;
395
400
        }
 
401
 
 
402
      else if (XGetWindowProperty (dpy, kids[i], XA_WM_COMMAND, 0, 128,
 
403
                                   False, XA_STRING, &type, &format, &nitems,
 
404
                                   &bytesafter, &version)
 
405
               == Success
 
406
               && type != None
 
407
               && !strcmp ((char *) version, "gnome-screensaver"))
 
408
        {
 
409
          fprintf (stderr,
 
410
                 "%s: \"%s\" is already running on display %s (window 0x%x)\n",
 
411
                   blurb(), (char *) version,
 
412
                   DisplayString (dpy), (int) kids [i]);
 
413
          status = True;
 
414
          break;
 
415
        }
396
416
    }
397
417
 
398
418
  if (kids) XFree ((char *) kids);
445
465
 
446
466
static Bool safe_XKillClient (Display *dpy, XID id);
447
467
 
448
 
#ifdef HAVE_XF86VMODE
449
 
static Bool safe_XF86VidModeGetViewPort (Display *, int, int *, int *);
450
 
#endif /* HAVE_XF86VMODE */
451
 
 
452
 
 
453
468
static void
454
469
kill_xsetroot_data_1 (Display *dpy, Window window,
455
470
                      Atom prop, const char *atom_name,
607
622
    fprintf (stderr,
608
623
             "%s: restoring __SWM_VROOT property on the real vroot (0x%lx).\n",
609
624
             blurb(), (unsigned long) ssi->real_vroot);
610
 
  remove_vroot_property (si->dpy, ssi->screensaver_window);
 
625
  if (ssi->screensaver_window)
 
626
    remove_vroot_property (si->dpy, ssi->screensaver_window);
611
627
  if (ssi->real_vroot)
612
628
    {
613
629
      store_vroot_property (si->dpy, ssi->real_vroot, ssi->real_vroot_value);
812
828
 
813
829
  if (si->screen_blanked_p)
814
830
    {
 
831
      int i;
 
832
      for (i = 0; i < si->nscreens; i++)
 
833
        kill_screenhack (&si->screens[i]);
815
834
      unblank_screen (si);
816
 
      kill_screenhack (si);
817
835
      XSync (si->dpy, False);
818
836
    }
819
837
 
999
1017
}
1000
1018
 
1001
1019
 
1002
 
 
1003
 
/* Returns the area of the screen which the xscreensaver window should cover.
1004
 
   Normally this is the whole screen, but if the X server's root window is
1005
 
   actually larger than the monitor's displayable area, then we want to
1006
 
   operate in the currently-visible portion of the desktop instead.
1007
 
 */
1008
 
void
1009
 
get_screen_viewport (saver_screen_info *ssi,
1010
 
                     int *x_ret, int *y_ret,
1011
 
                     int *w_ret, int *h_ret,
1012
 
                     int target_x, int target_y,
1013
 
                     Bool verbose_p)
1014
 
{
1015
 
  int w = WidthOfScreen (ssi->screen);
1016
 
  int h = HeightOfScreen (ssi->screen);
1017
 
 
1018
 
# ifdef HAVE_XF86VMODE
1019
 
  saver_info *si = ssi->global;
1020
 
  saver_preferences *p = &si->prefs;
1021
 
  int event, error;
1022
 
  int dot;
1023
 
  XF86VidModeModeLine ml;
1024
 
  int x, y;
1025
 
  Bool xinerama_p = si->xinerama_p;
1026
 
 
1027
 
#  ifndef HAVE_XINERAMA
1028
 
  /* Even if we don't have the client-side Xinerama lib, check to see if
1029
 
     the server supports Xinerama, so that we know to ignore the VidMode
1030
 
     extension -- otherwise a server crash could result.  Yay. */
1031
 
  xinerama_p = XQueryExtension (si->dpy, "XINERAMA", &error, &event, &error);
1032
 
#  endif /* !HAVE_XINERAMA */
1033
 
 
1034
 
#  ifdef HAVE_XINERAMA
1035
 
  if (xinerama_p)
1036
 
    {
1037
 
      int mouse_p = (target_x != -1 && target_y != -1);
1038
 
      int which = -1;
1039
 
      int i;
1040
 
 
1041
 
      /* If a mouse position wasn't passed in, assume we're talking about
1042
 
         this screen. */
1043
 
      if (!mouse_p)
1044
 
        {
1045
 
          target_x = ssi->x;
1046
 
          target_y = ssi->y;
1047
 
          which = ssi->number;
1048
 
        }
1049
 
 
1050
 
      /* Find the Xinerama rectangle that contains the mouse position. */
1051
 
      for (i = 0; i < si->nscreens; i++)
1052
 
        {
1053
 
          if (which == -1 &&
1054
 
              target_x >= si->screens[i].x &&
1055
 
              target_y >= si->screens[i].y &&
1056
 
              target_x <  si->screens[i].x + si->screens[i].width &&
1057
 
              target_y <  si->screens[i].y + si->screens[i].height)
1058
 
            which = i;
1059
 
        }
1060
 
      if (which == -1) which = 0;  /* didn't find it?  Use the first. */
1061
 
      *x_ret = si->screens[which].x;
1062
 
      *y_ret = si->screens[which].y;
1063
 
      *w_ret = si->screens[which].width;
1064
 
      *h_ret = si->screens[which].height;
1065
 
 
1066
 
      if (verbose_p)
1067
 
        {
1068
 
          fprintf (stderr, "%s: %d: xinerama vp: %dx%d+%d+%d",
1069
 
                   blurb(), which,
1070
 
                   si->screens[which].width, si->screens[which].height,
1071
 
                   si->screens[which].x, si->screens[which].y);
1072
 
          if (mouse_p)
1073
 
            fprintf (stderr, "; mouse at %d,%d", target_x, target_y);
1074
 
          fprintf (stderr, ".\n");
1075
 
        }
1076
 
 
1077
 
      return;
1078
 
    }
1079
 
#  endif /* HAVE_XINERAMA */
1080
 
 
1081
 
  if (!xinerama_p &&  /* Xinerama + VidMode = broken. */
1082
 
      XF86VidModeQueryExtension (si->dpy, &event, &error) &&
1083
 
      safe_XF86VidModeGetViewPort (si->dpy, ssi->number, &x, &y) &&
1084
 
      XF86VidModeGetModeLine (si->dpy, ssi->number, &dot, &ml))
1085
 
    {
1086
 
      char msg[512];
1087
 
      *x_ret = x;
1088
 
      *y_ret = y;
1089
 
      *w_ret = ml.hdisplay;
1090
 
      *h_ret = ml.vdisplay;
1091
 
 
1092
 
      if (*x_ret == 0 && *y_ret == 0 && *w_ret == w && *h_ret == h)
1093
 
        /* There is no viewport -- the screen does not scroll. */
1094
 
        return;
1095
 
 
1096
 
 
1097
 
      /* Apparently some versions of XFree86 return nonsense here!
1098
 
         I've had reports of 1024x768 viewports at -1936862040, -1953705044.
1099
 
         So, sanity-check the values and give up if they are out of range.
1100
 
       */
1101
 
      if (*x_ret <  0 || *x_ret >= w ||
1102
 
          *y_ret <  0 || *y_ret >= h ||
1103
 
          *w_ret <= 0 || *w_ret >  w ||
1104
 
          *h_ret <= 0 || *h_ret >  h)
1105
 
        {
1106
 
          static int warned_once = 0;
1107
 
          if (!warned_once)
1108
 
            {
1109
 
              fprintf (stderr, "\n"
1110
 
                  "%s: X SERVER BUG: %dx%d viewport at %d,%d is impossible.\n"
1111
 
                  "%s: The XVidMode server extension is returning nonsense.\n"
1112
 
                  "%s: Please report this bug to your X server vendor.\n\n",
1113
 
                       blurb(), *w_ret, *h_ret, *x_ret, *y_ret,
1114
 
                       blurb(), blurb());
1115
 
              warned_once = 1;
1116
 
            }
1117
 
          *x_ret = 0;
1118
 
          *y_ret = 0;
1119
 
          *w_ret = w;
1120
 
          *h_ret = h;
1121
 
          return;
1122
 
        }
1123
 
 
1124
 
      sprintf (msg, "%s: %d: vp is %dx%d+%d+%d",
1125
 
               blurb(), ssi->number,
1126
 
               *w_ret, *h_ret, *x_ret, *y_ret);
1127
 
 
1128
 
 
1129
 
      if (p->getviewport_full_of_lies_p)
1130
 
        {
1131
 
          /* XF86VidModeGetViewPort() tends to be full of lies on laptops
1132
 
             that have a docking station or external monitor that runs in
1133
 
             a different resolution than the laptop's screen:
1134
 
 
1135
 
                 http://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=81593
1136
 
                 http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=208417
1137
 
                 http://bugs.xfree86.org/show_bug.cgi?id=421
1138
 
 
1139
 
             The XFree86 developers have closed the bug. As far as I can
1140
 
             tell, their reason for this was, "this is an X server bug,
1141
 
             but it's pretty hard to fix. Therefore, we are closing it."
1142
 
 
1143
 
             So, now there's a preference item for those unfortunate users to
1144
 
             tell us not to trust a word that XF86VidModeGetViewPort() says.
1145
 
           */
1146
 
          static int warned_once = 0;
1147
 
          if (!warned_once && verbose_p)
1148
 
            {
1149
 
              warned_once = 1;
1150
 
              fprintf (stderr,
1151
 
                  "%s: %d: XF86VidModeGetViewPort() says vp is %dx%d+%d+%d;\n"
1152
 
                  "%s: %d:     assuming that is a pack of lies;\n"
1153
 
                  "%s: %d:     using %dx%d+0+0 instead.\n",
1154
 
                       blurb(), ssi->number,
1155
 
                       *w_ret, *h_ret, *x_ret, *y_ret,
1156
 
                       blurb(), ssi->number,
1157
 
                       blurb(), ssi->number, w, h);
1158
 
            }
1159
 
 
1160
 
          *x_ret = 0;
1161
 
          *y_ret = 0;
1162
 
          *w_ret = w;
1163
 
          *h_ret = h;
1164
 
          return;
1165
 
        }
1166
 
 
1167
 
 
1168
 
      /* Apparently, though the server stores the X position in increments of
1169
 
         1 pixel, it will only make changes to the *display* in some other
1170
 
         increment.  With XF86_SVGA on a Thinkpad, the display only updates
1171
 
         in multiples of 8 pixels when in 8-bit mode, and in multiples of 4
1172
 
         pixels in 16-bit mode.  I don't know what it does in 24- and 32-bit
1173
 
         mode, because I don't have enough video memory to find out.
1174
 
 
1175
 
         I consider it a bug that XF86VidModeGetViewPort() is telling me the
1176
 
         server's *target* scroll position rather than the server's *actual*
1177
 
         scroll position.  David Dawes agrees, and says they may fix this in
1178
 
         XFree86 4.0, but it's notrivial.
1179
 
 
1180
 
         He also confirms that this behavior is server-dependent, so the
1181
 
         actual scroll position cannot be reliably determined by the client.
1182
 
         So... that means the only solution is to provide a ``sandbox''
1183
 
         around the blackout window -- we make the window be up to N pixels
1184
 
         larger than the viewport on both the left and right sides.  That
1185
 
         means some part of the outer edges of each hack might not be
1186
 
         visible, but screw it.
1187
 
 
1188
 
         I'm going to guess that 16 pixels is enough, and that the Y dimension
1189
 
         doesn't have this problem.
1190
 
 
1191
 
         The drawback of doing this, of course, is that some of the screenhacks
1192
 
         will still look pretty stupid -- for example, "slidescreen" will cut
1193
 
         off the left and right edges of the grid, etc.
1194
 
      */
1195
 
#  define FUDGE 16
1196
 
      if (x > 0 && x < w - ml.hdisplay)  /* not at left edge or right edge */
1197
 
        {
1198
 
          /* Round X position down to next lower multiple of FUDGE.
1199
 
             Increase width by 2*FUDGE in case some server rounds up.
1200
 
           */
1201
 
          *x_ret = ((x - 1) / FUDGE) * FUDGE;
1202
 
          *w_ret += (FUDGE * 2);
1203
 
        }
1204
 
#  undef FUDGE
1205
 
 
1206
 
      if (*x_ret != x ||
1207
 
          *y_ret != y ||
1208
 
          *w_ret != ml.hdisplay ||
1209
 
          *h_ret != ml.vdisplay)
1210
 
        sprintf (msg + strlen(msg), "; fudged to %dx%d+%d+%d",
1211
 
                 *w_ret, *h_ret, *x_ret, *y_ret);
1212
 
 
1213
 
      if (verbose_p)
1214
 
        fprintf (stderr, "%s.\n", msg);
1215
 
 
1216
 
      return;
1217
 
    }
1218
 
 
1219
 
# endif /* HAVE_XF86VMODE */
1220
 
 
1221
 
  *x_ret = 0;
1222
 
  *y_ret = 0;
1223
 
  *w_ret = w;
1224
 
  *h_ret = h;
1225
 
}
1226
 
 
1227
 
 
1228
1020
static Bool error_handler_hit_p = False;
1229
1021
 
1230
1022
static int
1318
1110
 
1319
1111
 
1320
1112
#ifdef HAVE_XF86VMODE
1321
 
static Bool
 
1113
Bool
1322
1114
safe_XF86VidModeGetViewPort (Display *dpy, int screen, int *xP, int *yP)
1323
1115
{
1324
1116
  Bool result;
1362
1154
  XColor black;
1363
1155
  XSetWindowAttributes attrs;
1364
1156
  unsigned long attrmask;
1365
 
  int x, y, width, height;
1366
1157
  static Bool printed_visual_info = False;  /* only print the message once. */
1367
1158
  Window horked_window = 0;
1368
1159
 
1369
 
  get_screen_viewport (ssi, &x, &y, &width, &height, -1, -1,
1370
 
                       (p->verbose_p && !si->screen_blanked_p));
1371
 
 
1372
1160
  black.red = black.green = black.blue = 0;
1373
1161
 
1374
1162
  if (ssi->cmap == DefaultColormapOfScreen (ssi->screen))
1421
1209
  attrs.backing_pixel = ssi->black_pixel;
1422
1210
  attrs.border_pixel = ssi->black_pixel;
1423
1211
 
1424
 
  if (p->debug_p
1425
 
# ifdef QUAD_MODE
1426
 
      && !p->quad_p
1427
 
# endif
1428
 
      )
1429
 
    width = width / 2;
1430
 
 
1431
1212
  if (!p->verbose_p || printed_visual_info)
1432
1213
    ;
1433
1214
  else if (ssi->current_visual == DefaultVisualOfScreen (ssi->screen))
1503
1284
    {
1504
1285
      XWindowChanges changes;
1505
1286
      unsigned int changesmask = CWX|CWY|CWWidth|CWHeight|CWBorderWidth;
1506
 
      changes.x = x;
1507
 
      changes.y = y;
1508
 
      changes.width = width;
1509
 
      changes.height = height;
 
1287
      changes.x = ssi->x;
 
1288
      changes.y = ssi->y;
 
1289
      changes.width = ssi->width;
 
1290
      changes.height = ssi->height;
1510
1291
      changes.border_width = 0;
1511
1292
 
1512
1293
      if (! (safe_XConfigureWindow (si->dpy, ssi->screensaver_window,
1523
1304
    {
1524
1305
      ssi->screensaver_window =
1525
1306
        XCreateWindow (si->dpy, RootWindowOfScreen (ssi->screen),
1526
 
                       x, y, width, height,
 
1307
                       ssi->x, ssi->y, ssi->width, ssi->height,
1527
1308
                       0, ssi->current_depth, InputOutput,
1528
1309
                       ssi->current_visual, attrmask, &attrs);
1529
 
 
1530
1310
      reset_stderr (ssi);
1531
1311
 
1532
1312
      if (horked_window)
1578
1358
}
1579
1359
 
1580
1360
 
1581
 
/* Called when the RANDR (Resize and Rotate) extension tells us that the
1582
 
   size of the screen has changed while the screen was blanked.  If we
1583
 
   don't do this, then the screen saver will no longer fully fill the
1584
 
   screen, and some of the underlying desktop may be visible.
 
1361
/* Called when the RANDR (Resize and Rotate) extension tells us that
 
1362
   the size of the screen has changed while the screen was blanked.
 
1363
   Call update_screen_layout() first, then call this to synchronize
 
1364
   the size of the saver windows to the new sizes of the screens.
1585
1365
 */
1586
1366
void
1587
1367
resize_screensaver_window (saver_info *si)
1589
1369
  saver_preferences *p = &si->prefs;
1590
1370
  int i;
1591
1371
 
1592
 
  /* First update the size info in the saver_screen_info structs.
1593
 
   */
1594
 
 
1595
 
# ifdef HAVE_XINERAMA
1596
 
  if (si->xinerama_p)
1597
 
    {
1598
 
      /* As of XFree86 4.3.0, the RANDR and XINERAMA extensions cannot coexist.
1599
 
         However, maybe they will someday, so I'm guessing that the right thing
1600
 
         to do in that case will be to re-query the Xinerama rectangles after
1601
 
         a RANDR size change is received: presumably, if the resolution of one
1602
 
         or more of the monitors has changed, then the Xinerama rectangle
1603
 
         corresponding to that monitor will also have been updated.
1604
 
       */
1605
 
      int nscreens;
1606
 
      XineramaScreenInfo *xsi = XineramaQueryScreens (si->dpy, &nscreens);
1607
 
 
1608
 
      if (nscreens != si->nscreens) {
1609
 
        /* Apparently some Xinerama implementations let you use a hot-key
1610
 
           to change the number of screens in use!  This is, of course,
1611
 
           documented nowhere.  Let's try to do something marginally less
1612
 
           bad than crashing.
1613
 
         */
1614
 
        fprintf (stderr, "%s: bad craziness: xinerama screen count changed "
1615
 
                 "from %d to %d!\n", blurb(), si->nscreens, nscreens);
1616
 
        if (nscreens > si->nscreens)
1617
 
          nscreens = si->nscreens;
1618
 
      }
1619
 
 
1620
 
      if (!xsi) abort();
1621
 
      for (i = 0; i < nscreens; i++)
1622
 
        {
1623
 
          saver_screen_info *ssi = &si->screens[i];
1624
 
          if (p->verbose_p &&
1625
 
              (ssi->x      != xsi[i].x_org ||
1626
 
               ssi->y      != xsi[i].y_org ||
1627
 
               ssi->width  != xsi[i].width ||
1628
 
               ssi->height != xsi[i].height))
1629
 
            fprintf (stderr,
1630
 
                   "%s: %d: resize xinerama from %dx%d+%d+%d to %dx%d+%d+%d\n",
1631
 
                     blurb(), i,
1632
 
                     ssi->width,   ssi->height,   ssi->x,       ssi->y,
1633
 
                     xsi[i].width, xsi[i].height, xsi[i].x_org, xsi[i].y_org);
1634
 
 
1635
 
          ssi->x      = xsi[i].x_org;
1636
 
          ssi->y      = xsi[i].y_org;
1637
 
          ssi->width  = xsi[i].width;
1638
 
          ssi->height = xsi[i].height;
1639
 
        }
1640
 
      XFree (xsi);
1641
 
    }
1642
 
  else
1643
 
# endif /* HAVE_XINERAMA */
1644
 
    {
1645
 
      /* Not Xinerama -- get the real sizes of the root windows. */
1646
 
      for (i = 0; i < si->nscreens; i++)
1647
 
        {
1648
 
          saver_screen_info *ssi = &si->screens[i];
1649
 
          XWindowAttributes xgwa;
1650
 
          XGetWindowAttributes (si->dpy, RootWindowOfScreen (ssi->screen),
1651
 
                                &xgwa);
1652
 
 
1653
 
          if (p->verbose_p &&
1654
 
              (ssi->x      != xgwa.x ||
1655
 
               ssi->y      != xgwa.y ||
1656
 
               ssi->width  != xgwa.width ||
1657
 
               ssi->height != xgwa.height))
1658
 
            fprintf (stderr,
1659
 
                     "%s: %d: resize screen from %dx%d+%d+%d to %dx%d+%d+%d\n",
1660
 
                     blurb(), i,
1661
 
                     ssi->width, ssi->height, ssi->x, ssi->y,
1662
 
                     xgwa.width, xgwa.height, xgwa.x, xgwa.y);
1663
 
 
1664
 
          ssi->x      = xgwa.x;
1665
 
          ssi->y      = xgwa.y;
1666
 
          ssi->width  = xgwa.width;
1667
 
          ssi->height = xgwa.height;
1668
 
        }
1669
 
    }
1670
 
 
1671
 
  /* Next, ensure that the screensaver windows are the right size, taking
1672
 
     into account both the new size of the screen in question's root window,
1673
 
     and any viewport within that.
1674
 
   */
1675
 
 
1676
1372
  for (i = 0; i < si->nscreens; i++)
1677
1373
    {
1678
1374
      saver_screen_info *ssi = &si->screens[i];
1679
1375
      XWindowAttributes xgwa;
1680
 
      XWindowChanges changes;
1681
 
      int x, y, width, height;
1682
 
      unsigned int changesmask = CWX|CWY|CWWidth|CWHeight|CWBorderWidth;
1683
 
 
 
1376
 
 
1377
      /* Make sure a window exists -- it might not if a monitor was just
 
1378
         added for the first time.
 
1379
       */
 
1380
      if (! ssi->screensaver_window)
 
1381
        {
 
1382
          initialize_screensaver_window_1 (ssi);
 
1383
          if (p->verbose_p)
 
1384
            fprintf (stderr,
 
1385
                     "%s: %d: newly added window 0x%lx %dx%d+%d+%d\n",
 
1386
                     blurb(), i, (unsigned long) ssi->screensaver_window,
 
1387
                     ssi->width, ssi->height, ssi->x, ssi->y);
 
1388
        }
 
1389
 
 
1390
      /* Make sure the window is the right size -- it might not be if
 
1391
         the monitor changed resolution, or if a badly-behaved hack
 
1392
         screwed with it.
 
1393
       */
1684
1394
      XGetWindowAttributes (si->dpy, ssi->screensaver_window, &xgwa);
1685
 
      get_screen_viewport (ssi, &x, &y, &width, &height, -1, -1,
1686
 
                           (p->verbose_p && !si->screen_blanked_p));
1687
 
      if (xgwa.x == x &&
1688
 
          xgwa.y == y &&
1689
 
          xgwa.width  == width &&
1690
 
          xgwa.height == height)
1691
 
        continue;  /* no change! */
1692
 
 
1693
 
      changes.x = x;
1694
 
      changes.y = y;
1695
 
      changes.width  = width;
1696
 
      changes.height = height;
1697
 
      changes.border_width = 0;
1698
 
 
1699
 
      if (p->debug_p
1700
 
# ifdef QUAD_MODE
1701
 
          && !p->quad_p
1702
 
# endif
1703
 
          ) 
1704
 
        changes.width = changes.width / 2;
1705
 
 
1706
 
      if (p->verbose_p)
1707
 
        fprintf (stderr,
1708
 
                 "%s: %d: resize 0x%lx from %dx%d+%d+%d to %dx%d+%d+%d\n",
1709
 
                 blurb(), i, (unsigned long) ssi->screensaver_window,
1710
 
                 xgwa.width, xgwa.height, xgwa.x, xgwa.y,
1711
 
                 width, height, x, y);
1712
 
      if (! safe_XConfigureWindow (si->dpy, ssi->screensaver_window,
1713
 
                                   changesmask, &changes))
1714
 
        {
1715
 
          fprintf (stderr,
1716
 
    "%s: %d: someone horked our saver window (0x%lx)!  Unable to resize it!\n",
1717
 
                   blurb(), i, (unsigned long) ssi->screensaver_window);
 
1395
      if (xgwa.x      != ssi->x ||
 
1396
          xgwa.y      != ssi->y ||
 
1397
          xgwa.width  != ssi->width ||
 
1398
          xgwa.height != ssi->height)
 
1399
        {
 
1400
          XWindowChanges changes;
 
1401
          unsigned int changesmask = CWX|CWY|CWWidth|CWHeight|CWBorderWidth;
 
1402
          changes.x      = ssi->x;
 
1403
          changes.y      = ssi->y;
 
1404
          changes.width  = ssi->width;
 
1405
          changes.height = ssi->height;
 
1406
          changes.border_width = 0;
 
1407
 
 
1408
          if (p->verbose_p)
 
1409
            fprintf (stderr,
 
1410
                     "%s: %d: resize 0x%lx from %dx%d+%d+%d to %dx%d+%d+%d\n",
 
1411
                     blurb(), i, (unsigned long) ssi->screensaver_window,
 
1412
                     xgwa.width, xgwa.height, xgwa.x, xgwa.y,
 
1413
                     ssi->width, ssi->height, ssi->x, ssi->y);
 
1414
 
 
1415
          if (! safe_XConfigureWindow (si->dpy, ssi->screensaver_window,
 
1416
                                       changesmask, &changes))
 
1417
            fprintf (stderr, "%s: %d: someone horked our saver window"
 
1418
                     " (0x%lx)!  Unable to resize it!\n",
 
1419
                     blurb(), i, (unsigned long) ssi->screensaver_window);
 
1420
        }
 
1421
 
 
1422
      /* Now (if blanked) make sure that it's mapped and running a hack --
 
1423
         it might not be if we just added it.  (We also might be re-using
 
1424
         an old window that existed for a previous monitor that was
 
1425
         removed and re-added.)
 
1426
 
 
1427
         Note that spawn_screenhack() calls select_visual() which may destroy
 
1428
         and re-create the window via initialize_screensaver_window_1().
 
1429
       */
 
1430
      if (si->screen_blanked_p)
 
1431
        {
 
1432
          if (ssi->cmap)
 
1433
            XInstallColormap (si->dpy, ssi->cmap);
 
1434
          XMapRaised (si->dpy, ssi->screensaver_window);
 
1435
          if (! ssi->pid)
 
1436
            spawn_screenhack (ssi);
 
1437
 
 
1438
          /* Make sure the act of adding a screen doesn't present as 
 
1439
             pointer motion (and thus cause an unblank). */
 
1440
          {
 
1441
            Window root, child;
 
1442
            int x, y;
 
1443
            unsigned int mask;
 
1444
            XQueryPointer (si->dpy, ssi->screensaver_window, &root, &child,
 
1445
                           &ssi->poll_mouse_last_root_x,
 
1446
                           &ssi->poll_mouse_last_root_y,
 
1447
                           &x, &y, &mask);
 
1448
          }
 
1449
        }
 
1450
    }
 
1451
 
 
1452
  /* Kill off any savers running on no-longer-extant monitors.
 
1453
   */
 
1454
  for (; i < si->ssi_count; i++)
 
1455
    {
 
1456
      saver_screen_info *ssi = &si->screens[i];
 
1457
      if (ssi->pid)
 
1458
        kill_screenhack (ssi);
 
1459
      if (ssi->screensaver_window)
 
1460
        {
 
1461
          XUnmapWindow (si->dpy, ssi->screensaver_window);
 
1462
          restore_real_vroot_1 (ssi);
1718
1463
        }
1719
1464
    }
1720
1465
}
2094
1839
}
2095
1840
 
2096
1841
 
 
1842
static Visual *
 
1843
get_screen_gl_visual (saver_info *si, int real_screen_number)
 
1844
{
 
1845
  int i;
 
1846
  int nscreens = ScreenCount (si->dpy);
 
1847
 
 
1848
  if (! si->best_gl_visuals)
 
1849
    si->best_gl_visuals = (Visual **) 
 
1850
      calloc (nscreens + 1, sizeof (*si->best_gl_visuals));
 
1851
 
 
1852
  for (i = 0; i < nscreens; i++)
 
1853
    if (! si->best_gl_visuals[i])
 
1854
      si->best_gl_visuals[i] = 
 
1855
        get_best_gl_visual (si, ScreenOfDisplay (si->dpy, i));
 
1856
 
 
1857
  if (real_screen_number < 0 || real_screen_number >= nscreens) abort();
 
1858
  return si->best_gl_visuals[real_screen_number];
 
1859
}
 
1860
 
2097
1861
 
2098
1862
Bool
2099
1863
select_visual (saver_screen_info *ssi, const char *visual_name)
2100
1864
{
 
1865
  XWindowAttributes xgwa;
2101
1866
  saver_info *si = ssi->global;
2102
1867
  saver_preferences *p = &si->prefs;
2103
1868
  Bool install_cmap_p = p->install_cmap_p;
2112
1877
   */
2113
1878
  Bool always_recreate_window_p = True;
2114
1879
 
 
1880
  get_screen_gl_visual (si, 0);   /* let's probe all the GL visuals early */
 
1881
 
 
1882
  /* We make sure the existing window is actually on ssi->screen before
 
1883
     trying to use it, in case things moved around radically when monitors
 
1884
     were added or deleted.  If we don't do this we could get a BadMatch
 
1885
     even though the depths match.  I think.
 
1886
   */
 
1887
  memset (&xgwa, 0, sizeof(xgwa));
 
1888
  if (ssi->screensaver_window)
 
1889
    XGetWindowAttributes (si->dpy, ssi->screensaver_window, &xgwa);
 
1890
 
2115
1891
  if (visual_name && *visual_name)
2116
1892
    {
2117
1893
      if (!strcmp(visual_name, "default-i") ||
2133
1909
               !strcmp(visual_name, "Gl") ||
2134
1910
               !strcmp(visual_name, "GL"))
2135
1911
        {
2136
 
          new_v = ssi->best_gl_visual;
 
1912
          new_v = get_screen_gl_visual (si, ssi->real_screen_number);
2137
1913
          if (!new_v && p->verbose_p)
2138
1914
            fprintf (stderr, "%s: no GL visuals.\n", progname);
2139
1915
        }
2154
1930
 
2155
1931
  ssi->install_cmap_p = install_cmap_p;
2156
1932
 
2157
 
  if (new_v &&
2158
 
      (always_recreate_window_p ||
2159
 
       (ssi->current_visual != new_v) ||
2160
 
       (install_cmap_p != was_installed_p)))
 
1933
  if ((ssi->screen != xgwa.screen) ||
 
1934
      (new_v &&
 
1935
       (always_recreate_window_p ||
 
1936
        (ssi->current_visual != new_v) ||
 
1937
        (install_cmap_p != was_installed_p))))
2161
1938
    {
2162
1939
      Colormap old_c = ssi->cmap;
2163
1940
      Window old_w = ssi->screensaver_window;
 
1941
      if (! new_v) 
 
1942
        new_v = ssi->current_visual;
2164
1943
 
2165
1944
      if (p->verbose_p)
2166
1945
        {