+ if (pw->logo_height > pw->height)
+ pw->height = pw->logo_height;
+ else if (pw->height > pw->logo_height)
+ pw->logo_height = pw->height;
+
+ pw->logo_width = pw->logo_height;
+
+ pw->width += pw->logo_width;
+ }
+
+ attrmask |= CWOverrideRedirect; attrs.override_redirect = True;
+
+ attrmask |= CWEventMask;
+ attrs.event_mask = (ExposureMask | KeyPressMask |
+ ButtonPressMask | ButtonReleaseMask);
+
+ /* We need to remember the mouse position and restore it afterward, or
+ sometimes (perhaps only with Xinerama?) the mouse gets warped to
+ inside the bounds of the lock dialog window.
+ */
+ {
+ Window pointer_root, pointer_child;
+ int root_x, root_y, win_x, win_y;
+ unsigned int mask;
+ pw->previous_mouse_x = 0;
+ pw->previous_mouse_y = 0;
+ if (XQueryPointer (si->dpy, RootWindowOfScreen (pw->prompt_screen->screen),
+ &pointer_root, &pointer_child,
+ &root_x, &root_y, &win_x, &win_y, &mask))
+ {
+ pw->previous_mouse_x = root_x;
+ pw->previous_mouse_y = root_y;
+ if (si->prefs.verbose_p)
+ fprintf (stderr, "%s: %d: mouse is at %d,%d.\n",
+ blurb(), pw->prompt_screen->number,
+ pw->previous_mouse_x, pw->previous_mouse_y);
+ }
+ else if (si->prefs.verbose_p)
+ fprintf (stderr, "%s: %d: unable to determine mouse position?\n",
+ blurb(), pw->prompt_screen->number);
+ }
+
+ /* Figure out where on the desktop to place the window so that it will
+ actually be visible; this takes into account virtual viewports as
+ well as Xinerama. */
+ {
+ int x, y, w, h;
+ get_screen_viewport (pw->prompt_screen, &x, &y, &w, &h,
+ pw->previous_mouse_x, pw->previous_mouse_y,
+ si->prefs.verbose_p);
+ if (si->prefs.debug_p) w /= 2;
+ pw->x = x + ((w + pw->width) / 2) - pw->width;
+ pw->y = y + ((h + pw->height) / 2) - pw->height;
+ if (pw->x < x) pw->x = x;
+ if (pw->y < y) pw->y = y;
+ }
+
+ pw->border_width = get_integer_resource ("passwd.borderWidth",
+ "Dialog.BorderWidth");
+
+ si->passwd_dialog =
+ XCreateWindow (si->dpy,
+ RootWindowOfScreen(screen),
+ pw->x, pw->y, pw->width, pw->height, pw->border_width,
+ DefaultDepthOfScreen (screen), InputOutput,
+ DefaultVisualOfScreen(screen),
+ attrmask, &attrs);
+ XSetWindowBackground (si->dpy, si->passwd_dialog, pw->background);
+
+ /* We use the default visual, not ssi->visual, so that the logo pixmap's
+ visual matches that of the si->passwd_dialog window. */
+ pw->logo_pixmap = xscreensaver_logo (ssi->screen,
+ /* ssi->current_visual, */
+ DefaultVisualOfScreen(screen),
+ si->passwd_dialog, cmap,
+ pw->background,
+ &pw->logo_pixels, &pw->logo_npixels,
+ 0, True);
+
+ /* Before mapping the window, save the bits that are underneath the
+ rectangle the window will occlude. When we lower the window, we
+ restore these bits. This works, because the running screenhack
+ has already been sent SIGSTOP, so we know nothing else is drawing
+ right now! */
+ {
+ XGCValues gcv;
+ GC gc;
+ pw->save_under = XCreatePixmap (si->dpy,
+ pw->prompt_screen->screensaver_window,
+ pw->width + (pw->border_width*2) + 1,
+ pw->height + (pw->border_width*2) + 1,
+ pw->prompt_screen->current_depth);
+ gcv.function = GXcopy;
+ gc = XCreateGC (si->dpy, pw->save_under, GCFunction, &gcv);
+ XCopyArea (si->dpy, pw->prompt_screen->screensaver_window,
+ pw->save_under, gc,
+ pw->x - pw->border_width, pw->y - pw->border_width,
+ pw->width + (pw->border_width*2) + 1,
+ pw->height + (pw->border_width*2) + 1,
+ 0, 0);
+ XFreeGC (si->dpy, gc);
+ }
+
+ XMapRaised (si->dpy, si->passwd_dialog);
+ XSync (si->dpy, False);
+
+ move_mouse_grab (si, si->passwd_dialog,
+ (pw->passwd_cursor
+ ? pw->passwd_cursor
+ : pw->prompt_screen->cursor),
+ pw->prompt_screen->number);
+ undo_vp_motion (si);
+
+ si->pw_data = pw;
+
+ if (cmap)
+ XInstallColormap (si->dpy, cmap);
+ draw_passwd_window (si);
+ XSync (si->dpy, False);
+}
+
+
+static void
+draw_passwd_window (saver_info *si)
+{
+ passwd_dialog_data *pw = si->pw_data;
+ XGCValues gcv;
+ GC gc1, gc2;
+ int spacing, height;
+ int x1, x2, x3, y1, y2;
+ int sw;
+ int tb_height;
+
+ height = (pw->heading_font->ascent + pw->heading_font->descent +
+ pw->body_font->ascent + pw->body_font->descent +
+ (2 * MAX ((pw->label_font->ascent + pw->label_font->descent),
+ (pw->passwd_font->ascent + pw->passwd_font->descent +
+ (pw->shadow_width * 4)))) +
+ pw->date_font->ascent + pw->date_font->descent);
+
+ if (pw->login_button_p)
+ height += ((pw->button_font->ascent + pw->button_font->descent) * 2 +
+ 2 * pw->shadow_width);
+
+ spacing = (((pw->height
+ - ((pw->login_button_p ? 4 : 2) * pw->shadow_width)
+ - pw->internal_border - height))
+ / 8);
+
+ if (spacing < 0) spacing = 0;
+
+ gcv.foreground = pw->foreground;
+ gc1 = XCreateGC (si->dpy, si->passwd_dialog, GCForeground, &gcv);
+ gc2 = XCreateGC (si->dpy, si->passwd_dialog, GCForeground, &gcv);
+ x1 = pw->logo_width + pw->thermo_width + (pw->shadow_width * 3);
+ x3 = pw->width - (pw->shadow_width * 2);
+ y1 = (pw->shadow_width * 2) + spacing + spacing;
+
+ /* top heading
+ */
+ XSetFont (si->dpy, gc1, pw->heading_font->fid);
+ sw = string_width (pw->heading_font, pw->heading_label);
+ x2 = (x1 + ((x3 - x1 - sw) / 2));
+ y1 += spacing + pw->heading_font->ascent + pw->heading_font->descent;
+ XDrawString (si->dpy, si->passwd_dialog, gc1, x2, y1,
+ pw->heading_label, strlen(pw->heading_label));
+
+ /* text below top heading
+ */
+ XSetFont (si->dpy, gc1, pw->body_font->fid);
+ y1 += spacing + pw->body_font->ascent + pw->body_font->descent;
+ sw = string_width (pw->body_font, pw->body_label);
+ x2 = (x1 + ((x3 - x1 - sw) / 2));
+ XDrawString (si->dpy, si->passwd_dialog, gc1, x2, y1,
+ pw->body_label, strlen(pw->body_label));
+
+
+ tb_height = (pw->passwd_font->ascent + pw->passwd_font->descent +
+ (pw->shadow_width * 4));
+
+ /* the "User:" prompt
+ */
+ y1 += spacing;
+ y2 = y1;
+ XSetForeground (si->dpy, gc1, pw->foreground);
+ XSetFont (si->dpy, gc1, pw->label_font->fid);
+ y1 += (spacing + tb_height);
+ x2 = (x1 + pw->internal_border +
+ MAX(string_width (pw->label_font, pw->user_label),
+ string_width (pw->label_font, pw->passwd_label)));
+ XDrawString (si->dpy, si->passwd_dialog, gc1,
+ x2 - string_width (pw->label_font, pw->user_label),
+ y1 - pw->passwd_font->descent,
+ pw->user_label, strlen(pw->user_label));
+
+ /* the "Password:" prompt
+ */
+ y1 += (spacing + tb_height);
+ XDrawString (si->dpy, si->passwd_dialog, gc1,
+ x2 - string_width (pw->label_font, pw->passwd_label),
+ y1 - pw->passwd_font->descent,
+ pw->passwd_label, strlen(pw->passwd_label));
+
+
+ XSetForeground (si->dpy, gc2, pw->passwd_background);
+
+ /* the "user name" text field
+ */
+ y1 = y2;
+ XSetForeground (si->dpy, gc1, pw->passwd_foreground);
+ XSetFont (si->dpy, gc1, pw->passwd_font->fid);
+ y1 += (spacing + tb_height);
+ x2 += (pw->shadow_width * 4);
+
+ pw->passwd_field_width = x3 - x2 - pw->internal_border;
+ pw->passwd_field_height = (pw->passwd_font->ascent +
+ pw->passwd_font->descent +
+ pw->shadow_width);
+
+ XFillRectangle (si->dpy, si->passwd_dialog, gc2,
+ x2 - pw->shadow_width,
+ y1 - (pw->passwd_font->ascent + pw->passwd_font->descent),
+ pw->passwd_field_width, pw->passwd_field_height);
+ XDrawString (si->dpy, si->passwd_dialog, gc1,
+ x2,
+ y1 - pw->passwd_font->descent,
+ pw->user_string, strlen(pw->user_string));
+
+ /* the "password" text field
+ */
+ y1 += (spacing + tb_height);
+
+ pw->passwd_field_x = x2 - pw->shadow_width;
+ pw->passwd_field_y = y1 - (pw->passwd_font->ascent +
+ pw->passwd_font->descent);
+
+ /* The shadow around the text fields
+ */
+ y1 = y2;
+ y1 += (spacing + (pw->shadow_width * 3));
+ x1 = x2 - (pw->shadow_width * 2);
+ x2 = pw->passwd_field_width + (pw->shadow_width * 2);
+ y2 = pw->passwd_field_height + (pw->shadow_width * 2);
+
+ draw_shaded_rectangle (si->dpy, si->passwd_dialog,
+ x1, y1, x2, y2,
+ pw->shadow_width,
+ pw->shadow_bottom, pw->shadow_top);
+
+ y1 += (spacing + pw->passwd_font->ascent + pw->passwd_font->descent +
+ (pw->shadow_width * 4));
+ draw_shaded_rectangle (si->dpy, si->passwd_dialog,
+ x1, y1, x2, y2,
+ pw->shadow_width,
+ pw->shadow_bottom, pw->shadow_top);
+
+
+ /* The date, below the text fields
+ */
+ {
+ char buf[100];
+ time_t now = time ((time_t *) 0);
+ struct tm *tm = localtime (&now);
+ memset (buf, 0, sizeof(buf));
+ strftime (buf, sizeof(buf)-1, pw->date_label, tm);
+
+ XSetFont (si->dpy, gc1, pw->date_font->fid);
+ y1 += pw->shadow_width;
+ y1 += (spacing + tb_height);
+ y1 += spacing/2;
+ sw = string_width (pw->date_font, buf);
+ x2 = x1 + x2 - sw;
+ XDrawString (si->dpy, si->passwd_dialog, gc1, x2, y1, buf, strlen(buf));
+ }
+
+ /* The "New Login" button
+ */
+ if (pw->login_button_p)
+ {
+ XSetForeground (si->dpy, gc1, pw->button_foreground);
+ XSetForeground (si->dpy, gc2, pw->button_background);
+ XSetFont (si->dpy, gc1, pw->button_font->fid);
+
+ sw = string_width (pw->button_font, pw->login_label);
+
+ x2 = pw->width - pw->internal_border - (pw->shadow_width * 2);
+
+ /* right aligned button */
+ /* x1 = x2 - pw->login_button_width; */
+
+ /* centered button */
+ x1 = (pw->logo_width + pw->thermo_width + (pw->shadow_width * 3) +
+ pw->internal_border);
+ x1 = x1 + (x2 - x1 - pw->login_button_width) / 2;
+
+ y1 = (pw->height - pw->internal_border - pw->login_button_height +
+ spacing);
+ y2 = (y1 +
+ ((pw->login_button_height -
+ (pw->button_font->ascent + pw->button_font->descent))
+ / 2) +
+ pw->button_font->ascent);
+
+ pw->login_button_x = x1;
+ pw->login_button_y = y1;
+ }
+
+ /* The logo
+ */
+ x1 = pw->shadow_width * 6;
+ y1 = pw->shadow_width * 6;
+ x2 = pw->logo_width - (pw->shadow_width * 12);
+ y2 = pw->logo_height - (pw->shadow_width * 12);
+
+ if (pw->logo_pixmap)
+ {
+ Window root;
+ int x, y;
+ unsigned int w, h, bw, d;
+ XGetGeometry (si->dpy, pw->logo_pixmap, &root, &x, &y, &w, &h, &bw, &d);
+ XSetForeground (si->dpy, gc1, pw->foreground);
+ XSetBackground (si->dpy, gc1, pw->background);
+ if (d == 1)
+ XCopyPlane (si->dpy, pw->logo_pixmap, si->passwd_dialog, gc1,
+ 0, 0, w, h,
+ x1 + ((x2 - (int)w) / 2),
+ y1 + ((y2 - (int)h) / 2),
+ 1);
+ else
+ XCopyArea (si->dpy, pw->logo_pixmap, si->passwd_dialog, gc1,
+ 0, 0, w, h,
+ x1 + ((x2 - (int)w) / 2),
+ y1 + ((y2 - (int)h) / 2));
+ }
+
+ /* The thermometer
+ */
+ XSetForeground (si->dpy, gc1, pw->thermo_foreground);
+ XSetForeground (si->dpy, gc2, pw->thermo_background);
+
+ pw->thermo_field_x = pw->logo_width + pw->shadow_width;
+ pw->thermo_field_y = pw->shadow_width * 5;
+ pw->thermo_field_height = pw->height - (pw->shadow_width * 10);
+
+#if 0
+ /* Solid border inside the logo box. */
+ XSetForeground (si->dpy, gc1, pw->foreground);
+ XDrawRectangle (si->dpy, si->passwd_dialog, gc1, x1, y1, x2-1, y2-1);