A patch to XScreensaver to provide lock window theming. Default theme is a metallic grey border with green on black body using the Neuropol font. For further details on the patch and theming see the following web page; http://www.swanson.ukfsn.org/xss/ Alan Swanson Version 1.1 o Update for XScreenSaver 4.22 o Optional login button implemented o Fix backgrounds for label and date fields o Use clipmask for status to prevent overwriting borders Version 1.0 o Initial release against XScreenSaver 4.15 diff -urP xscreensaver-4.22/driver/lock.c xscreensaver-4.22-lock/driver/lock.c --- xscreensaver-4.22/driver/lock.c 2005-06-04 20:50:10.000000000 +0100 +++ xscreensaver-4.22-lock/driver/lock.c 2005-06-27 18:56:15.000000000 +0100 @@ -25,6 +25,28 @@ #include "xscreensaver.h" #include "resources.h" +#include "theme.h" +#include "theme_logo.xpm" +#include "theme_frame_t.xpm" +#include "theme_frame_b.xpm" +#include "theme_frame_l.xpm" +#include "theme_frame_r.xpm" +#include "theme_frame_tl.xpm" +#include "theme_frame_tr.xpm" +#include "theme_frame_bl.xpm" +#include "theme_frame_br.xpm" + +#ifndef THEME_FONT_LOGIN +#define THEME_FONT_LOGIN THEME_FONT_LABEL +#endif +#ifndef THEME_FG_LOGIN +#define THEME_FG_LOGIN THEME_FG_LABEL +#endif +#ifndef THEME_BG_LOGIN +#define THEME_BG_LOGIN THEME_BG +#endif + + #ifndef NO_LOCKING /* (mostly) whole file */ #ifdef HAVE_SYSLOG @@ -79,7 +101,18 @@ #undef MAX #define MAX(a,b) ((a)>(b)?(a):(b)) -enum passwd_state { pw_read, pw_ok, pw_null, pw_fail, pw_cancel, pw_time }; +#undef MAX3 +#define MAX3(a,b,c) MAX(a,MAX(b,c)) + +enum passwd_state { pw_read, pw_check, pw_ok, pw_null, pw_fail, pw_cancel, pw_time }; + +struct xpm_data { + Pixmap pixmap; + Dimension width; + Dimension height; + int npixels; + unsigned long *pixels; +}; struct passwd_dialog_data { @@ -100,38 +133,38 @@ Bool show_stars_p; /* "I regret that I have but one asterisk for my country." -- Nathan Hale, 1776. */ - char *heading_label; - char *body_label; char *user_label; char *passwd_label; char *date_label; + char *login_label; char *user_string; char *passwd_string; - char *login_label; + char *status_string; - XFontStruct *heading_font; - XFontStruct *body_font; XFontStruct *label_font; XFontStruct *passwd_font; XFontStruct *date_font; - XFontStruct *button_font; + XFontStruct *login_font; + XFontStruct *status_font; Pixel foreground; Pixel background; + + Pixel label_foreground; + Pixel label_background; Pixel passwd_foreground; Pixel passwd_background; + Pixel date_foreground; + Pixel date_background; Pixel thermo_foreground; Pixel thermo_background; - Pixel shadow_top; - Pixel shadow_bottom; - Pixel button_foreground; - Pixel button_background; + Pixel login_foreground; + Pixel login_background; + Pixel denied_foreground; - Dimension logo_width; - Dimension logo_height; Dimension thermo_width; Dimension internal_border; - Dimension shadow_width; + Dimension internal_spacer; Dimension passwd_field_x, passwd_field_y; Dimension passwd_field_width, passwd_field_height; @@ -142,9 +175,20 @@ Dimension thermo_field_x, thermo_field_y; Dimension thermo_field_height; - Pixmap logo_pixmap; - int logo_npixels; - unsigned long *logo_pixels; + struct xpm_data logo; + struct xpm_data frame_t; + struct xpm_data frame_b; + struct xpm_data frame_l; + struct xpm_data frame_r; + struct xpm_data frame_tl; + struct xpm_data frame_tr; + struct xpm_data frame_bl; + struct xpm_data frame_br; + + Dimension frame_max_t; + Dimension frame_max_b; + Dimension frame_max_l; + Dimension frame_max_r; Cursor passwd_cursor; Bool login_button_down_p; @@ -196,10 +240,6 @@ pw->show_stars_p = get_boolean_resource("passwd.asterisks", "Boolean"); - pw->heading_label = get_string_resource ("passwd.heading.label", - "Dialog.Label.Label"); - pw->body_label = get_string_resource ("passwd.body.label", - "Dialog.Label.Label"); pw->user_label = get_string_resource ("passwd.user.label", "Dialog.Label.Label"); pw->passwd_label = get_string_resource ("passwd.passwd.label", @@ -207,64 +247,53 @@ pw->login_label = get_string_resource ("passwd.login.label", "Dialog.Button.Label"); - pw->date_label = get_string_resource ("dateFormat", "DateFormat"); - - if (!pw->heading_label) - pw->heading_label = strdup("ERROR: RESOURCES NOT INSTALLED CORRECTLY"); - if (!pw->body_label) - pw->body_label = strdup("ERROR: RESOURCES NOT INSTALLED CORRECTLY"); if (!pw->user_label) pw->user_label = strdup("ERROR"); if (!pw->passwd_label) pw->passwd_label = strdup("ERROR"); - if (!pw->date_label) pw->date_label = strdup("ERROR"); - if (!pw->login_label) pw->login_label = strdup ("ERROR (LOGIN)") ; - - /* Put the version number in the label. */ - { - char *s = (char *) malloc (strlen(pw->heading_label) + 20); - sprintf(s, pw->heading_label, si->version); - free (pw->heading_label); - pw->heading_label = s; - } + if (!pw->login_label) pw->login_label = strdup ("ERROR") ; pw->user_string = strdup (p && p->pw_name ? p->pw_name : "???"); pw->passwd_string = strdup(""); + pw->date_label = strdup("%H:%M"); + + pw->label_font = XLoadQueryFont (si->dpy, THEME_FONT_LABEL); + if (!pw->label_font) { + f = get_string_resource("passwd.labelFont", "Dialog.Font"); + pw->label_font = XLoadQueryFont (si->dpy, (f ? f : "fixed")); + if (!pw->label_font) pw->label_font = XLoadQueryFont (si->dpy, "fixed"); + if (f) free (f); + } - f = get_string_resource ("passwd.headingFont", "Dialog.Font"); - pw->heading_font = XLoadQueryFont (si->dpy, (f ? f : "fixed")); - if (!pw->heading_font) pw->heading_font = XLoadQueryFont (si->dpy, "fixed"); - if (f) free (f); - - f = get_string_resource ("passwd.buttonFont", "Dialog.Font"); - pw->button_font = XLoadQueryFont (si->dpy, (f ? f : "fixed")); - if (!pw->button_font) pw->button_font = XLoadQueryFont (si->dpy, "fixed"); - if (f) free (f); - - f = get_string_resource("passwd.bodyFont", "Dialog.Font"); - pw->body_font = XLoadQueryFont (si->dpy, (f ? f : "fixed")); - if (!pw->body_font) pw->body_font = XLoadQueryFont (si->dpy, "fixed"); - if (f) free (f); - - f = get_string_resource("passwd.labelFont", "Dialog.Font"); - pw->label_font = XLoadQueryFont (si->dpy, (f ? f : "fixed")); - if (!pw->label_font) pw->label_font = XLoadQueryFont (si->dpy, "fixed"); - if (f) free (f); - - f = get_string_resource("passwd.passwdFont", "Dialog.Font"); - pw->passwd_font = XLoadQueryFont (si->dpy, (f ? f : "fixed")); - if (!pw->passwd_font) pw->passwd_font = XLoadQueryFont (si->dpy, "fixed"); - if (f) free (f); - - f = get_string_resource("passwd.dateFont", "Dialog.Font"); - pw->date_font = XLoadQueryFont (si->dpy, (f ? f : "fixed")); - if (!pw->date_font) pw->date_font = XLoadQueryFont (si->dpy, "fixed"); - if (f) free (f); - - pw->foreground = get_pixel_resource ("passwd.foreground", - "Dialog.Foreground", - si->dpy, cmap); - pw->background = get_pixel_resource ("passwd.background", - "Dialog.Background", - si->dpy, cmap); + pw->passwd_font = XLoadQueryFont (si->dpy, THEME_FONT_PASSWD); + if (!pw->passwd_font) { + f = get_string_resource("passwd.passwdFont", "Dialog.Font"); + pw->passwd_font = XLoadQueryFont (si->dpy, (f ? f : "fixed")); + if (!pw->passwd_font) pw->passwd_font = XLoadQueryFont (si->dpy, "fixed"); + if (f) free (f); + } + + pw->login_font = XLoadQueryFont (si->dpy, THEME_FONT_LOGIN); + if (!pw->login_font) { + f = get_string_resource("passwd.loginFont", "Dialog.Font"); + pw->login_font = XLoadQueryFont (si->dpy, (f ? f : "fixed")); + if (!pw->login_font) pw->login_font = XLoadQueryFont (si->dpy, "fixed"); + if (f) free (f); + } + + pw->date_font = XLoadQueryFont (si->dpy, THEME_FONT_DATE); + if (!pw->date_font) { + f = get_string_resource("passwd.dateFont", "Dialog.Font"); + pw->date_font = XLoadQueryFont (si->dpy, (f ? f : "fixed")); + if (!pw->date_font) pw->date_font = XLoadQueryFont (si->dpy, "fixed"); + if (f) free (f); + } + + pw->status_font = XLoadQueryFont (si->dpy, THEME_FONT_STATUS); + if (!pw->status_font) { + pw->status_font = XLoadQueryFont (si->dpy, ("fixed")); + } + + pw->foreground = parse_pixel_resource (THEME_FG, si->dpy, cmap); + pw->background = parse_pixel_resource (THEME_BG, si->dpy, cmap); if (pw->foreground == pw->background) { @@ -273,47 +302,76 @@ pw->background = WhitePixelOfScreen (screen); } - pw->passwd_foreground = get_pixel_resource ("passwd.text.foreground", - "Dialog.Text.Foreground", - si->dpy, cmap); - pw->passwd_background = get_pixel_resource ("passwd.text.background", - "Dialog.Text.Background", - si->dpy, cmap); - pw->button_foreground = get_pixel_resource ("splash.Button.foreground", - "Dialog.Button.Foreground", - si->dpy, cmap); - pw->button_background = get_pixel_resource ("splash.Button.background", - "Dialog.Button.Background", - si->dpy, cmap); - pw->thermo_foreground = get_pixel_resource ("passwd.thermometer.foreground", - "Dialog.Thermometer.Foreground", - si->dpy, cmap); - pw->thermo_background = get_pixel_resource ("passwd.thermometer.background", - "Dialog.Thermometer.Background", - si->dpy, cmap); - pw->shadow_top = get_pixel_resource ("passwd.topShadowColor", - "Dialog.Foreground", - si->dpy, cmap); - pw->shadow_bottom = get_pixel_resource ("passwd.bottomShadowColor", - "Dialog.Background", - si->dpy, cmap); - - pw->logo_width = get_integer_resource ("passwd.logo.width", - "Dialog.Logo.Width"); - pw->logo_height = get_integer_resource ("passwd.logo.height", - "Dialog.Logo.Height"); - pw->thermo_width = get_integer_resource ("passwd.thermometer.width", - "Dialog.Thermometer.Width"); - pw->internal_border = get_integer_resource ("passwd.internalBorderWidth", - "Dialog.InternalBorderWidth"); - pw->shadow_width = get_integer_resource ("passwd.shadowThickness", - "Dialog.ShadowThickness"); - - if (pw->logo_width == 0) pw->logo_width = 150; - if (pw->logo_height == 0) pw->logo_height = 150; - if (pw->internal_border == 0) pw->internal_border = 15; - if (pw->shadow_width == 0) pw->shadow_width = 4; - if (pw->thermo_width == 0) pw->thermo_width = pw->shadow_width; + pw->label_foreground = parse_pixel_resource (THEME_FG_LABEL, si->dpy, cmap); + pw->label_background = parse_pixel_resource (THEME_BG_LABEL, si->dpy, cmap); + + pw->passwd_foreground = parse_pixel_resource (THEME_FG_PASSWD, si->dpy, cmap); + pw->passwd_background = parse_pixel_resource (THEME_BG_PASSWD, si->dpy, cmap); + + pw->date_foreground = parse_pixel_resource (THEME_FG_DATE, si->dpy, cmap); + pw->date_background = parse_pixel_resource (THEME_BG_DATE, si->dpy, cmap); + + pw->login_foreground = parse_pixel_resource (THEME_FG_LOGIN, si->dpy, cmap); + pw->login_background = parse_pixel_resource (THEME_BG_LOGIN, si->dpy, cmap); + + pw->thermo_foreground = parse_pixel_resource (THEME_FG_THERMO, si->dpy, cmap); + pw->thermo_background = parse_pixel_resource (THEME_BG_THERMO, si->dpy, cmap); + + pw->denied_foreground = parse_pixel_resource (THEME_FG_DENIED, si->dpy, cmap); + + pw->thermo_width = THEME_THERMO_WIDTH; + pw->internal_border = THEME_INTERNAL_BORDER; + pw->internal_spacer = THEME_INTERNAL_SPACER; + + { + int w, h, tmp; + + /* THEME HACK: A macro or array would tidy the following. */ + if (sscanf(*theme_logo_xpm, "%d %d %d %d", &w, &h, &tmp, &tmp) == 4) { + pw->logo.width = (int) w; + pw->logo.height = (int) h; + } + + if (sscanf(*theme_frame_t_xpm, "%d %d %d %d", &w, &h, &tmp, &tmp) == 4) { + pw->frame_t.width = (int) w; + pw->frame_t.height = (int) h; + } + if (sscanf(*theme_frame_b_xpm, "%d %d %d %d", &w, &h, &tmp, &tmp) == 4) { + pw->frame_b.width = (int) w; + pw->frame_b.height = (int) h; + } + if (sscanf(*theme_frame_l_xpm, "%d %d %d %d", &w, &h, &tmp, &tmp) == 4) { + pw->frame_l.width = (int) w; + pw->frame_l.height = (int) h; + } + if (sscanf(*theme_frame_r_xpm, "%d %d %d %d", &w, &h, &tmp, &tmp) == 4) { + pw->frame_r.width = (int) w; + pw->frame_r.height = (int) h; + } + if (sscanf(*theme_frame_tl_xpm, "%d %d %d %d", &w, &h, &tmp, &tmp) == 4) { + pw->frame_tl.width = (int) w; + pw->frame_tl.height = (int) h; + } + if (sscanf(*theme_frame_tr_xpm, "%d %d %d %d", &w, &h, &tmp, &tmp) == 4) { + pw->frame_tr.width = (int) w; + pw->frame_tr.height = (int) h; + } + if (sscanf(*theme_frame_bl_xpm, "%d %d %d %d", &w, &h, &tmp, &tmp) == 4) { + pw->frame_bl.width = (int) w; + pw->frame_bl.height = (int) h; + } + if (sscanf(*theme_frame_br_xpm, "%d %d %d %d", &w, &h, &tmp, &tmp) == 4) { + pw->frame_br.width = (int) w; + pw->frame_br.height = (int) h; + } + + /* THEME HACK: As the pixmaps may not have same dimensions and are aligned + along outside edges find the maximums. */ + pw->frame_max_t = MAX3(pw->frame_t.height, pw->frame_tl.height, pw->frame_tr.height); + pw->frame_max_b = MAX3(pw->frame_b.height, pw->frame_bl.height, pw->frame_br.height); + pw->frame_max_l = MAX3(pw->frame_l.width, pw->frame_tl.width, pw->frame_bl.width); + pw->frame_max_r = MAX3(pw->frame_r.width, pw->frame_tr.width, pw->frame_br.width); + } { int direction, ascent, descent; @@ -322,24 +380,14 @@ pw->width = 0; pw->height = 0; - /* Measure the heading_label. */ - XTextExtents (pw->heading_font, - pw->heading_label, strlen(pw->heading_label), - &direction, &ascent, &descent, &overall); - if (overall.width > pw->width) pw->width = overall.width; - pw->height += ascent + descent; - - /* Measure the body_label. */ - XTextExtents (pw->body_font, - pw->body_label, strlen(pw->body_label), - &direction, &ascent, &descent, &overall); - if (overall.width > pw->width) pw->width = overall.width; - pw->height += ascent + descent; - - { - Dimension w2 = 0, w3 = 0, button_w = 0; - Dimension h2 = 0, h3 = 0, button_h = 0; - const char *passwd_string = "MMMMMMMMMMMM"; + { + Dimension w2 = 0, w3 = 0, w4 = 0; + Dimension h2 = 0, h3 = 0, h4 = 0; + /* THEME HACK: This used to be 12 M's to allow for result strings but on + fonts like Neuropol it is just too wide. Result strings now get + overwritten by theme so it doesn't matter. */ + const char *passwd_string = "************"; + const char *date_string = "88:88"; /* Measure the user_label. */ XTextExtents (pw->label_font, @@ -359,8 +407,6 @@ XTextExtents (pw->passwd_font, pw->user_string, strlen(pw->user_string), &direction, &ascent, &descent, &overall); - overall.width += (pw->shadow_width * 4); - ascent += (pw->shadow_width * 4); if (overall.width > w3) w3 = overall.width; h3 += ascent + descent; @@ -368,58 +414,68 @@ XTextExtents (pw->passwd_font, passwd_string, strlen(passwd_string), &direction, &ascent, &descent, &overall); - overall.width += (pw->shadow_width * 4); - ascent += (pw->shadow_width * 4); if (overall.width > w3) w3 = overall.width; h3 += ascent + descent; - w2 = w2 + w3 + (pw->shadow_width * 2); - h2 = MAX (h2, h3); - - pw->login_button_width = 0; - pw->login_button_height = 0; + /* Measure the date_label. */ + XTextExtents (pw->date_font, + date_string, strlen(date_string), + &direction, &ascent, &descent, &overall); + if (overall.width > w4) w4 = overall.width; + h4 += ascent + descent; + /* Measure the login_label if enabled. */ if (pw->login_button_p) - { - pw->login_button_enabled_p = True; - - /* Measure the "New Login" button */ - XTextExtents (pw->button_font, pw->login_label, - strlen (pw->login_label), - &direction, &ascent, &descent, &overall); - button_w = overall.width; - button_h = ascent + descent; - - /* Add some horizontal padding inside the buttons. */ - button_w += ascent; - - button_w += ((ascent + descent) / 2) + (pw->shadow_width * 2); - button_h += ((ascent + descent) / 2) + (pw->shadow_width * 2); - - pw->login_button_width = button_w; - pw->login_button_height = button_h; - - w2 = MAX (w2, button_w); - h2 += button_h * 1.5; - } + { + XTextExtents (pw->login_font, + pw->login_label, strlen(pw->login_label), + &direction, &ascent, &descent, &overall); + w4 += overall.width + 4; + if (ascent + descent > h4) h4 = ascent + descent + 4; + } - if (w2 > pw->width) pw->width = w2; - pw->height += h2; + pw->width = MAX (w2 + w3, w4); + pw->height = MAX (h2, h3); + pw->height += h4; } - pw->width += (pw->internal_border * 2); - pw->height += (pw->internal_border * 4); + if (pw->logo.height > pw->height) + pw->height = pw->logo.height; - pw->width += pw->thermo_width + (pw->shadow_width * 3); + pw->width += 2 * pw->internal_border + pw->logo.width + + 3 * pw->internal_spacer + pw->thermo_width; + pw->height+= 2 * pw->internal_border; - 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; + /* THEME HACK: By default, increase size so as to draw complete pixmaps. + Can only do for one (opposing) side - top and left. */ +#if defined THEME_TOP_CENTRED || defined THEME_TOP_FIT + if (pw->width % pw->frame_t.width) + pw->width += pw->frame_t.width - pw->width % pw->frame_t.width; +#endif +#if defined THEME_LEFT_CENTRED || defined THEME_LEFT_FIT + if (pw->height % pw->frame_l.height) + pw->height += pw->frame_l.height - pw->height % pw->frame_l.height; +#endif +#ifdef THEME_BOTTOM_FIT + if (pw->width % pw->frame_b.width) + pw->width += pw->frame_b.width - pw->width % pw->frame_b.width; +#endif +#ifdef THEME_RIGHT_FIT + if (pw->height % pw->frame_r.height) + pw->height += pw->frame_r.height - pw->height % pw->frame_r.height; +#endif +#ifdef THEME_BOTTOM_CENTRED + if (pw->width % pw->frame_b.width) + pw->width += pw->frame_b.width - pw->width % pw->frame_b.width; +#endif +#ifdef THEME_RIGHT_CENTRED + if (pw->height % pw->frame_r.height) + pw->height += pw->frame_r.height - pw->height % pw->frame_r.height; +#endif - pw->width += pw->logo_width; + pw->width += pw->frame_max_l + pw->frame_max_r; + pw->height+= pw->frame_max_t + pw->frame_max_b; } attrmask |= CWOverrideRedirect; attrs.override_redirect = True; @@ -483,13 +539,63 @@ /* 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, + pw->logo.pixmap = xscreensaver_xpm (ssi->screen, /* ssi->current_visual, */ DefaultVisualOfScreen(screen), si->passwd_dialog, cmap, pw->background, - &pw->logo_pixels, &pw->logo_npixels, - 0, True); + &pw->logo.pixels, &pw->logo.npixels, + 0, theme_logo_xpm); + + /* THEME HACK: A macro or array would tidy the following. */ + pw->frame_t.pixmap = xscreensaver_xpm (ssi->screen, + DefaultVisualOfScreen(screen), + si->passwd_dialog, cmap, + pw->background, + &pw->frame_t.pixels, &pw->frame_t.npixels, + 0, theme_frame_t_xpm); + pw->frame_b.pixmap = xscreensaver_xpm (ssi->screen, + DefaultVisualOfScreen(screen), + si->passwd_dialog, cmap, + pw->background, + &pw->frame_b.pixels, &pw->frame_b.npixels, + 0, theme_frame_b_xpm); + pw->frame_l.pixmap = xscreensaver_xpm (ssi->screen, + DefaultVisualOfScreen(screen), + si->passwd_dialog, cmap, + pw->background, + &pw->frame_l.pixels, &pw->frame_l.npixels, + 0, theme_frame_l_xpm); + pw->frame_r.pixmap = xscreensaver_xpm (ssi->screen, + DefaultVisualOfScreen(screen), + si->passwd_dialog, cmap, + pw->background, + &pw->frame_r.pixels, &pw->frame_r.npixels, + 0, theme_frame_r_xpm); + pw->frame_tl.pixmap = xscreensaver_xpm (ssi->screen, + DefaultVisualOfScreen(screen), + si->passwd_dialog, cmap, + pw->background, + &pw->frame_tl.pixels, &pw->frame_tl.npixels, + 0, theme_frame_tl_xpm); + pw->frame_tr.pixmap = xscreensaver_xpm (ssi->screen, + DefaultVisualOfScreen(screen), + si->passwd_dialog, cmap, + pw->background, + &pw->frame_tr.pixels, &pw->frame_tr.npixels, + 0, theme_frame_tr_xpm); + pw->frame_bl.pixmap = xscreensaver_xpm (ssi->screen, + DefaultVisualOfScreen(screen), + si->passwd_dialog, cmap, + pw->background, + &pw->frame_bl.pixels, &pw->frame_bl.npixels, + 0, theme_frame_bl_xpm); + pw->frame_br.pixmap = xscreensaver_xpm (ssi->screen, + DefaultVisualOfScreen(screen), + si->passwd_dialog, cmap, + pw->background, + &pw->frame_br.pixels, &pw->frame_br.npixels, + 0, theme_frame_br_xpm); /* Before mapping the window, save the bits that are underneath the rectangle the window will occlude. When we lower the window, we @@ -533,6 +639,27 @@ XSync (si->dpy, False); } +static void +xpm_passwd_window (saver_info *si, GC gc, Pixmap pixmap, int dx, int dy) +{ + passwd_dialog_data *pw = si->pw_data; + + if (pixmap) { + Window root; + int x, y; + unsigned int w, h, bw, d; + + XGetGeometry (si->dpy, pixmap, &root, &x, &y, &w, &h, &bw, &d); + XSetForeground (si->dpy, gc, pw->foreground); + XSetBackground (si->dpy, gc, pw->background); + if (d == 1) + XCopyPlane (si->dpy, pixmap, si->passwd_dialog, gc, + 0, 0, w, h, dx, dy, 1); + else + XCopyArea (si->dpy, pixmap, si->passwd_dialog, gc, + 0, 0, w, h, dx, dy); + } +} static void draw_passwd_window (saver_info *si) @@ -542,66 +669,45 @@ GC gc1, gc2; int spacing, height; int x1, x2, x3, y1, y2; - int sw; + int i; 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); - + height = 2 * MAX ((pw->label_font->ascent + pw->label_font->descent), + (pw->passwd_font->ascent + pw->passwd_font->descent)) + + pw->date_font->ascent + pw->date_font->descent; + /* THEME HACK: The "spacing" is automatic padding to allow for logo size. + Frame->Border->Spacer->User->Spacer->Password->Spacer->Date->Border->Frame + */ + spacing = ((pw->height - pw->frame_max_t - 2 * pw->internal_border - + pw->frame_max_b - height)) / 3; 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)); + /* THEME HACK: Changed from original logo-thermometer-test order to + logo-text-thermometer. */ + x1 = pw->frame_max_l + pw->internal_border + pw->logo.width + pw->internal_spacer; + y1 = pw->frame_max_t + pw->internal_border; + x3 = pw->width - pw->internal_spacer - pw->internal_border - pw->frame_max_r; - - tb_height = (pw->passwd_font->ascent + pw->passwd_font->descent + - (pw->shadow_width * 4)); + tb_height = pw->passwd_font->ascent + pw->passwd_font->descent; /* the "User:" prompt */ - y1 += spacing; + y1 += spacing + tb_height; y2 = y1; - XSetForeground (si->dpy, gc1, pw->foreground); + x2 = x1 + MAX(string_width (pw->label_font, pw->user_label), + string_width (pw->label_font, pw->passwd_label)); + 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))); + XSetForeground (si->dpy, gc1, pw->label_background); + XFillRectangle (si->dpy, si->passwd_dialog, gc1, + x2 - string_width (pw->label_font, pw->user_label), + y1 - (pw->label_font->ascent + pw->label_font->descent), + string_width (pw->label_font, pw->user_label), + pw->label_font->ascent + pw->label_font->descent); + XSetForeground (si->dpy, gc1, pw->label_foreground); XDrawString (si->dpy, si->passwd_dialog, gc1, x2 - string_width (pw->label_font, pw->user_label), y1 - pw->passwd_font->descent, @@ -609,7 +715,15 @@ /* the "Password:" prompt */ - y1 += (spacing + tb_height); + y1 += spacing + tb_height; + XSetForeground (si->dpy, gc1, pw->label_background); + XFillRectangle (si->dpy, si->passwd_dialog, gc1, + x2 - string_width (pw->label_font, pw->passwd_label), + y1 - (pw->label_font->ascent + pw->label_font->descent), + string_width (pw->label_font, pw->passwd_label), + pw->label_font->ascent + pw->label_font->descent); + + XSetForeground (si->dpy, gc1, pw->label_foreground); XDrawString (si->dpy, si->passwd_dialog, gc1, x2 - string_width (pw->label_font, pw->passwd_label), y1 - pw->passwd_font->descent, @@ -623,16 +737,13 @@ 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); + x2 += pw->internal_spacer; pw->passwd_field_width = x3 - x2 - pw->internal_border; - pw->passwd_field_height = (pw->passwd_font->ascent + - pw->passwd_font->descent + - pw->shadow_width); + pw->passwd_field_height = pw->passwd_font->ascent + pw->passwd_font->descent; XFillRectangle (si->dpy, si->passwd_dialog, gc2, - x2 - pw->shadow_width, + x2, y1 - (pw->passwd_font->ascent + pw->passwd_font->descent), pw->passwd_field_width, pw->passwd_field_height); XDrawString (si->dpy, si->passwd_dialog, gc1, @@ -642,32 +753,24 @@ /* the "password" text field */ - y1 += (spacing + tb_height); + 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); + pw->passwd_field_x = x2; + pw->passwd_field_y = y1 - pw->passwd_field_height; - /* The shadow around the text fields + /* The "New Login" button */ - 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); + if (pw->login_button_p) + { + pw->login_button_width = string_width(pw->login_font, pw->login_label) + 4; + pw->login_button_height = pw->login_font->ascent + pw->login_font->descent + 4; + pw->login_button_x = pw->width - pw->login_button_width - + pw->internal_spacer - pw->thermo_width - + pw->internal_border - pw->frame_max_r; + pw->login_button_y = pw->height - pw->internal_border - + pw->frame_max_b - pw->login_button_height; + } /* The date, below the text fields */ @@ -679,122 +782,151 @@ 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)); + /* THEME HACK: Place date centred between logo and thermometer + (or login button if enabled). */ + x1 += (pw->width - pw->frame_max_l - 2 * pw->internal_border - + pw->logo.width - pw->login_button_width - pw->thermo_width - + pw->frame_max_r) / 2 - + string_width(pw->date_font, buf) / 2; + y1 = pw->height - pw->internal_border - pw->frame_max_b; + + XSetForeground (si->dpy, gc1, pw->date_background); + XFillRectangle (si->dpy, si->passwd_dialog, gc1, + x1, + y1 - (pw->date_font->ascent + pw->date_font->descent), + string_width (pw->date_font, buf), + pw->date_font->ascent + pw->date_font->descent); + XSetForeground (si->dpy, gc1, pw->date_foreground); + XDrawString (si->dpy, si->passwd_dialog, gc1, + x1, + y1 - pw->date_font->descent, + 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)); - } + x1 = pw->frame_max_l + pw->internal_border; + y1 = pw->frame_max_t + (pw->height - pw->frame_max_t - pw->frame_max_b) / 2 - + pw->logo.height / 2; + x2 = pw->logo.width; + y2 = pw->logo.height; + + if (pw->logo.pixmap) { + xpm_passwd_window (si, gc1, pw->logo.pixmap, + x1 + ((x2 - pw->logo.width) / 2), + y1 + ((y2 - pw->logo.height) / 2)); + } - /* The thermometer + /* The frame */ - 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); + /* THEME HACK: The side pixmaps are either drawn centred or repeated along + outside side of the frame. */ + if (pw->frame_t.pixmap) { +#ifdef THEME_TOP_CENTRED + xpm_passwd_window (si, gc1, pw->frame_t.pixmap, + pw->frame_max_l + + (pw->width - pw->frame_max_l - pw->frame_max_r) / 2 - + pw->frame_t.width / 2, + 0); +#else + for (i = pw->frame_max_l; i < (pw->width - pw->frame_max_r) ; i += pw->frame_t.width) { + xpm_passwd_window (si, gc1, pw->frame_t.pixmap, i, 0); + } #endif + } + if (pw->frame_b.pixmap) { +#ifdef THEME_BOTTOM_CENTRED + xpm_passwd_window (si, gc1, pw->frame_b.pixmap, + pw->frame_max_l + + (pw->width - pw->frame_max_l - pw->frame_max_r) / 2 - + pw->frame_b.width / 2, + pw->height - pw->frame_b.height); +#else + for (i = pw->frame_max_l; i < (pw->width - pw->frame_max_r) ; i += pw->frame_b.width) { + xpm_passwd_window (si, gc1, pw->frame_b.pixmap, + i, pw->height - pw->frame_b.height); + } +#endif + } + if (pw->frame_l.pixmap) { +#ifdef THEME_LEFT_CENTRED + xpm_passwd_window (si, gc1, pw->frame_l.pixmap, + 0, + pw->frame_max_t + + (pw->height - pw->frame_max_t - pw->frame_max_b) / 2 - + pw->frame_l.height / 2 ); +#else + for (i = pw->frame_max_t; i < (pw->height - pw->frame_max_b) ; i += pw->frame_l.height) { + xpm_passwd_window (si, gc1, pw->frame_l.pixmap, 0, i); + } +#endif + } + if (pw->frame_r.pixmap) { +#ifdef THEME_RIGHT_CENTRED + xpm_passwd_window (si, gc1, pw->frame_r.pixmap, + pw->width - pw->frame_r.width, + pw->frame_max_t + + (pw->height - pw->frame_max_t - pw->frame_max_b) / 2 - + pw->frame_r.height / 2 ); +#else + for (i = pw->frame_max_t; i < (pw->height - pw->frame_max_b) ; i += pw->frame_r.height) { + xpm_passwd_window (si, gc1, pw->frame_r.pixmap, + pw->width - pw->frame_r.width, i); + } +#endif + } + /* THEME HACK: Black out corners. If corner pixmap is smaller than side + pixmaps we need to clear side pixmap overwrite. Additionally if background + is not black, then undrawn parts would have that colour. */ + XSetForeground (si->dpy, gc1, BlackPixelOfScreen (pw->prompt_screen->screen)); + XFillRectangle (si->dpy, si->passwd_dialog, gc1, + 0, 0, + pw->frame_max_l, pw->frame_max_t); + XFillRectangle (si->dpy, si->passwd_dialog, gc1, + pw->width - pw->frame_max_r, 0, + pw->frame_max_l, pw->frame_max_t); + XFillRectangle (si->dpy, si->passwd_dialog, gc1, + 0, pw->height - pw->frame_max_b, + pw->frame_max_l, pw->frame_max_t); + XFillRectangle (si->dpy, si->passwd_dialog, gc1, + pw->width - pw->frame_max_r, pw->height - pw->frame_max_b, + pw->frame_max_l, pw->frame_max_t); + /* THEME HACK: The corner pixmaps are drawn to the inside corner of the + frame. */ + if (pw->frame_tl.pixmap) { + xpm_passwd_window (si, gc1, pw->frame_tl.pixmap, + pw->frame_max_l - pw->frame_tl.width, + pw->frame_max_t - pw->frame_tl.height); + } + if (pw->frame_tr.pixmap) { + xpm_passwd_window (si, gc1, pw->frame_tr.pixmap, + pw->width - pw->frame_max_l, + pw->frame_max_t - pw->frame_tl.height); + } + if (pw->frame_bl.pixmap) { + xpm_passwd_window (si, gc1, pw->frame_bl.pixmap, + pw->frame_max_l - pw->frame_bl.width, + pw->height - pw->frame_max_b); + } + if (pw->frame_br.pixmap) { + xpm_passwd_window (si, gc1, pw->frame_br.pixmap, + pw->width - pw->frame_max_r, + pw->height - pw->frame_max_b); + } - /* The shadow around the logo - */ - draw_shaded_rectangle (si->dpy, si->passwd_dialog, - pw->shadow_width * 4, - pw->shadow_width * 4, - pw->logo_width - (pw->shadow_width * 8), - pw->logo_height - (pw->shadow_width * 8), - pw->shadow_width, - pw->shadow_bottom, pw->shadow_top); - - /* The shadow around the thermometer + /* the thermometer */ - draw_shaded_rectangle (si->dpy, si->passwd_dialog, - pw->logo_width, - pw->shadow_width * 4, - pw->thermo_width + (pw->shadow_width * 2), - pw->height - (pw->shadow_width * 8), - pw->shadow_width, - pw->shadow_bottom, pw->shadow_top); + pw->thermo_field_x = pw->width - pw->thermo_width - pw->internal_border - + pw->frame_max_r; + pw->thermo_field_y = pw->frame_max_t + pw->internal_border; + pw->thermo_field_height = pw->height - pw->frame_max_t - 2 * pw->internal_border - + pw->frame_max_b; -#if 1 /* Solid border inside the thermometer. */ - XSetForeground (si->dpy, gc1, pw->foreground); + XSetForeground (si->dpy, gc1, pw->thermo_background); XDrawRectangle (si->dpy, si->passwd_dialog, gc1, pw->thermo_field_x, pw->thermo_field_y, pw->thermo_width - 1, pw->thermo_field_height - 1); -#endif - - /* The shadow around the whole window - */ - draw_shaded_rectangle (si->dpy, si->passwd_dialog, - 0, 0, pw->width, pw->height, pw->shadow_width, - pw->shadow_top, pw->shadow_bottom); XFreeGC (si->dpy, gc1); XFreeGC (si->dpy, gc2); @@ -839,7 +971,7 @@ XSetClipRectangles (si->dpy, gc1, 0, 0, rects, 1, Unsorted); XDrawString (si->dpy, si->passwd_dialog, gc1, - rects[0].x + pw->shadow_width, + rects[0].x, rects[0].y + pw->passwd_font->ascent, pw->passwd_string, strlen(pw->passwd_string)); @@ -849,25 +981,24 @@ */ if (pw->i_beam != 0) { - x = (rects[0].x + pw->shadow_width + - string_width (pw->passwd_font, pw->passwd_string)); - y = rects[0].y + pw->shadow_width; + x = rects[0].x + string_width (pw->passwd_font, pw->passwd_string); + y = rects[0].y; if (x > rects[0].x + rects[0].width - 1) x = rects[0].x + rects[0].width - 1; XDrawLine (si->dpy, si->passwd_dialog, gc1, - x, y, - x, y + pw->passwd_font->ascent + pw->passwd_font->descent-1); + x, y, x, y + pw->passwd_field_height - 1); } pw->i_beam = (pw->i_beam + 1) % 4; - /* the thermometer + /* The thermometer */ y = (pw->thermo_field_height - 2) * (1.0 - pw->ratio); if (y > 0) { + XSetForeground (si->dpy, gc2, pw->background); XFillRectangle (si->dpy, si->passwd_dialog, gc2, pw->thermo_field_x + 1, pw->thermo_field_y + 1, @@ -885,41 +1016,81 @@ */ if (pw->login_button_p) { - int x2, y2, sw; - XSetFont (si->dpy, gc1, pw->button_font->fid); XSetForeground (si->dpy, gc1, (pw->login_button_enabled_p - ? pw->passwd_foreground - : pw->shadow_bottom)); - XSetForeground (si->dpy, gc2, pw->button_background); + ? pw->login_background + : pw->login_foreground)); - XFillRectangle (si->dpy, si->passwd_dialog, gc2, + XDrawRectangle (si->dpy, si->passwd_dialog, gc1, pw->login_button_x, pw->login_button_y, - pw->login_button_width, pw->login_button_height); + pw->login_button_width - 1, pw->login_button_height - 1); + XSetFont (si->dpy, gc1, pw->login_font->fid); + XDrawString (si->dpy, si->passwd_dialog, gc1, + pw->login_button_x + 1, + pw->login_button_y + pw->login_font->ascent + 2, + pw->login_label, strlen(pw->login_label)); - sw = string_width (pw->button_font, pw->login_label); - x2 = pw->login_button_x + ((pw->login_button_width - sw) / 2); - y2 = (pw->login_button_y + - ((pw->login_button_height - - (pw->button_font->ascent + pw->button_font->descent)) - / 2) + - pw->button_font->ascent); - - XDrawString (si->dpy, si->passwd_dialog, gc1, x2, y2, - pw->login_label, strlen(pw->login_label)); - - draw_shaded_rectangle (si->dpy, si->passwd_dialog, - pw->login_button_x, pw->login_button_y, - pw->login_button_width, pw->login_button_height, - pw->shadow_width, - (pw->login_button_down_p - ? pw->shadow_bottom - : pw->shadow_top), - (pw->login_button_down_p - ? pw->shadow_top - : pw->shadow_bottom)); } + /* the status mapping + */ + /* THEME HACK: Text is cheaper than pixmaps even though they'd look + nicer being anti-aliased. */ + if (pw->state) { + XSetForeground (si->dpy, gc1, pw->foreground); + switch (pw->state) + { + case pw_check: + pw->status_string = strdup("VERIFYING"); + break; + case pw_ok: + pw->status_string = strdup("APPROVED"); + break; + case pw_fail: + XSetForeground (si->dpy, gc1, pw->denied_foreground); + pw->status_string = strdup("DENIED"); + break; + case pw_null: + case pw_cancel: + pw->status_string = strdup("CANCELLED"); + break; + case pw_time: + pw->status_string = strdup("TIMED OUT"); + break; + default: + break; + } + if (pw->status_string) { + XSetForeground (si->dpy, gc2, pw->background); + XSetFont (si->dpy, gc1, pw->status_font->fid); + XFillRectangle (si->dpy, si->passwd_dialog, gc2, + pw->frame_max_l + pw->internal_border, + pw->frame_max_t + pw->internal_border, + pw->width - pw->frame_max_l - 2 * pw->internal_border - + pw->frame_max_r, + pw->height - pw->frame_max_t - 2 * pw->internal_border - + pw->frame_max_b); + + /* THEME HACK: Clip status message to not overdraw frame. */ + rects[0].x = pw->frame_max_l; + rects[0].y = pw->frame_max_t; + rects[0].width = pw->width - pw->frame_max_l - pw->frame_max_r; + rects[0].height = pw->height - pw->frame_max_t - pw->frame_max_b; + XSetClipRectangles (si->dpy, gc1, 0, 0, rects, 1, Unsorted); + + x = (pw->width - pw->frame_max_l - pw->frame_max_r) / 2 + pw->frame_max_l - + string_width (pw->status_font, pw->status_string) / 2; + y = (pw->height - pw->frame_max_t - pw->frame_max_b) / 2 + pw->frame_max_t + + (pw->status_font->ascent) / 2; + XDrawString (si->dpy, si->passwd_dialog, gc1, + x, y, + pw->status_string, strlen(pw->status_string)); + + XSetClipMask (si->dpy, gc1, None); + free (pw->status_string); + } + } + XFreeGC (si->dpy, gc1); XFreeGC (si->dpy, gc2); XSync (si->dpy, False); @@ -986,8 +1157,6 @@ XFreeGC (si->dpy, gc); } - if (pw->heading_label) free (pw->heading_label); - if (pw->body_label) free (pw->body_label); if (pw->user_label) free (pw->user_label); if (pw->passwd_label) free (pw->passwd_label); if (pw->date_label) free (pw->date_label); @@ -995,43 +1164,132 @@ if (pw->user_string) free (pw->user_string); if (pw->passwd_string) free (pw->passwd_string); - if (pw->heading_font) XFreeFont (si->dpy, pw->heading_font); - if (pw->body_font) XFreeFont (si->dpy, pw->body_font); if (pw->label_font) XFreeFont (si->dpy, pw->label_font); if (pw->passwd_font) XFreeFont (si->dpy, pw->passwd_font); if (pw->date_font) XFreeFont (si->dpy, pw->date_font); - if (pw->button_font) XFreeFont (si->dpy, pw->button_font); + if (pw->login_font) XFreeFont (si->dpy, pw->login_font); + if (pw->status_font) XFreeFont (si->dpy, pw->status_font); if (pw->foreground != black && pw->foreground != white) XFreeColors (si->dpy, cmap, &pw->foreground, 1, 0L); if (pw->background != black && pw->background != white) XFreeColors (si->dpy, cmap, &pw->background, 1, 0L); - if (!(pw->button_foreground == black || pw->button_foreground == white)) - XFreeColors (si->dpy, cmap, &pw->button_foreground, 1, 0L); - if (!(pw->button_background == black || pw->button_background == white)) - XFreeColors (si->dpy, cmap, &pw->button_background, 1, 0L); + + if (pw->label_foreground != black && pw->label_foreground != white) + XFreeColors (si->dpy, cmap, &pw->label_foreground, 1, 0L); + if (pw->label_background != black && pw->label_background != white) + XFreeColors (si->dpy, cmap, &pw->label_background, 1, 0L); + if (pw->passwd_foreground != black && pw->passwd_foreground != white) XFreeColors (si->dpy, cmap, &pw->passwd_foreground, 1, 0L); if (pw->passwd_background != black && pw->passwd_background != white) XFreeColors (si->dpy, cmap, &pw->passwd_background, 1, 0L); + + if (pw->date_foreground != black && pw->date_foreground != white) + XFreeColors (si->dpy, cmap, &pw->date_foreground, 1, 0L); + if (pw->date_background != black && pw->date_background != white) + XFreeColors (si->dpy, cmap, &pw->date_background, 1, 0L); + + if (!(pw->login_foreground == black || pw->login_foreground == white)) + XFreeColors (si->dpy, cmap, &pw->login_foreground, 1, 0L); + if (!(pw->login_background == black || pw->login_background == white)) + XFreeColors (si->dpy, cmap, &pw->login_background, 1, 0L); + if (pw->thermo_foreground != black && pw->thermo_foreground != white) XFreeColors (si->dpy, cmap, &pw->thermo_foreground, 1, 0L); if (pw->thermo_background != black && pw->thermo_background != white) XFreeColors (si->dpy, cmap, &pw->thermo_background, 1, 0L); - if (pw->shadow_top != black && pw->shadow_top != white) - XFreeColors (si->dpy, cmap, &pw->shadow_top, 1, 0L); - if (pw->shadow_bottom != black && pw->shadow_bottom != white) - XFreeColors (si->dpy, cmap, &pw->shadow_bottom, 1, 0L); - - if (pw->logo_pixmap) - XFreePixmap (si->dpy, pw->logo_pixmap); - if (pw->logo_pixels) - { - if (pw->logo_npixels) - XFreeColors (si->dpy, cmap, pw->logo_pixels, pw->logo_npixels, 0L); - free (pw->logo_pixels); - pw->logo_pixels = 0; - pw->logo_npixels = 0; + + /* THEME HACK: A macro or array would tidy the following. */ + if (pw->logo.pixmap) + XFreePixmap (si->dpy, pw->logo.pixmap); + if (pw->logo.pixels) + { + if (pw->logo.npixels) + XFreeColors (si->dpy, cmap, pw->logo.pixels, pw->logo.npixels, 0L); + free (pw->logo.pixels); + pw->logo.pixels = 0; + pw->logo.npixels = 0; + } + if (pw->frame_t.pixmap) + XFreePixmap (si->dpy, pw->frame_t.pixmap); + if (pw->frame_t.pixels) + { + if (pw->frame_t.npixels) + XFreeColors (si->dpy, cmap, pw->frame_t.pixels, pw->frame_t.npixels, 0L); + free (pw->frame_t.pixels); + pw->frame_t.pixels = 0; + pw->frame_t.npixels = 0; + } + if (pw->frame_b.pixmap) + XFreePixmap (si->dpy, pw->frame_b.pixmap); + if (pw->frame_b.pixels) + { + if (pw->frame_b.npixels) + XFreeColors (si->dpy, cmap, pw->frame_b.pixels, pw->frame_b.npixels, 0L); + free (pw->frame_b.pixels); + pw->frame_b.pixels = 0; + pw->frame_b.npixels = 0; + } + if (pw->frame_l.pixmap) + XFreePixmap (si->dpy, pw->frame_l.pixmap); + if (pw->frame_l.pixels) + { + if (pw->frame_l.npixels) + XFreeColors (si->dpy, cmap, pw->frame_l.pixels, pw->frame_l.npixels, 0L); + free (pw->frame_l.pixels); + pw->frame_l.pixels = 0; + pw->frame_l.npixels = 0; + } + if (pw->frame_r.pixmap) + XFreePixmap (si->dpy, pw->frame_r.pixmap); + if (pw->frame_r.pixels) + { + if (pw->frame_r.npixels) + XFreeColors (si->dpy, cmap, pw->frame_r.pixels, pw->frame_r.npixels, 0L); + free (pw->frame_r.pixels); + pw->frame_r.pixels = 0; + pw->frame_r.npixels = 0; + } + if (pw->frame_tl.pixmap) + XFreePixmap (si->dpy, pw->frame_tl.pixmap); + if (pw->frame_tl.pixels) + { + if (pw->frame_tl.npixels) + XFreeColors (si->dpy, cmap, pw->frame_tl.pixels, pw->frame_tl.npixels, 0L); + free (pw->frame_tl.pixels); + pw->frame_tl.pixels = 0; + pw->frame_tl.npixels = 0; + } + if (pw->frame_tr.pixmap) + XFreePixmap (si->dpy, pw->frame_tr.pixmap); + if (pw->frame_tr.pixels) + { + if (pw->frame_tr.npixels) + XFreeColors (si->dpy, cmap, pw->frame_tr.pixels, pw->frame_tr.npixels, 0L); + free (pw->frame_tr.pixels); + pw->frame_tr.pixels = 0; + pw->frame_tr.npixels = 0; + } + if (pw->frame_bl.pixmap) + XFreePixmap (si->dpy, pw->frame_bl.pixmap); + if (pw->frame_bl.pixels) + { + if (pw->frame_bl.npixels) + XFreeColors (si->dpy, cmap, pw->frame_bl.pixels, pw->frame_bl.npixels, 0L); + free (pw->frame_bl.pixels); + pw->frame_bl.pixels = 0; + pw->frame_bl.npixels = 0; + } + if (pw->frame_br.pixmap) + XFreePixmap (si->dpy, pw->frame_br.pixmap); + if (pw->frame_br.pixels) + { + if (pw->frame_br.npixels) + XFreeColors (si->dpy, cmap, pw->frame_br.pixels, pw->frame_br.npixels, 0L); + free (pw->frame_br.pixels); + pw->frame_br.pixels = 0; + pw->frame_br.npixels = 0; } if (pw->save_under) @@ -1413,6 +1671,7 @@ pw->state = pw_null; else { + pw->state = pw_check; update_passwd_window (si, "Checking...", pw->ratio); XSync (si->dpy, False); if (passwd_valid_p (typed_passwd, p->verbose_p)) diff -urP xscreensaver-4.22/utils/logo.c xscreensaver-4.22-lock/utils/logo.c --- xscreensaver-4.22/utils/logo.c 2003-07-23 03:25:00.000000000 +0100 +++ xscreensaver-4.22-lock/utils/logo.c 2005-06-27 16:47:31.000000000 +0100 @@ -27,6 +27,11 @@ you didn't write; please don't alter its logo either. */ +/* THEME HACK: Reasonable enough, but the lock window is bloody ugly and + I cannot stand to look at it anymore. Replacing the lock window does not + prevent people knowing that it is xscreensaver running. + */ + #include "utils.h" #include "resources.h" #include "visual.h" @@ -242,3 +247,50 @@ } return p; } + + + +/* Returns a pixmap of the XPM data passed. + */ +Pixmap +xscreensaver_xpm (Screen *screen, Visual *visual, + Drawable drawable, Colormap cmap, + unsigned long background_color, + unsigned long **pixels_ret, int *npixels_ret, + Pixmap *mask_ret, + const char * const *xpm_data) +{ + Display *dpy = DisplayOfScreen (screen); + int depth = visual_depth (screen, visual); + int iw, ih; + XImage *image; + Pixmap p = 0; + unsigned char *mask = 0; + + image = parse_xpm_data (dpy, visual, cmap, depth, background_color, + xpm_data, + &iw, &ih, pixels_ret, npixels_ret, + (mask_ret ? &mask : 0)); + + if (image) + { + XGCValues gcv; + GC gc; + p = XCreatePixmap (dpy, drawable, iw, ih, depth); + gc = XCreateGC (dpy, p, 0, &gcv); + XPutImage (dpy, p, gc, image, 0, 0, 0, 0, iw, ih); + free (image->data); + image->data = 0; + XDestroyImage (image); + XFreeGC (dpy, gc); + + if (mask_ret && mask) + { + *mask_ret = (Pixmap) + XCreatePixmapFromBitmapData (dpy, drawable, (char *) mask, + iw, ih, 1L, 0L, 1); + free (mask); + } + } + return p; +} diff -urP xscreensaver-4.22/utils/resources.c xscreensaver-4.22-lock/utils/resources.c --- xscreensaver-4.22/utils/resources.c 2003-07-23 03:25:00.000000000 +0100 +++ xscreensaver-4.22-lock/utils/resources.c 2005-06-27 16:47:31.000000000 +0100 @@ -129,6 +129,52 @@ return 0.0; } +unsigned int +parse_pixel_resource (char *s, Display *dpy, Colormap cmap) +{ + XColor color; + char *s2; + Bool ok = True; + if (!s) goto DEFAULT; + + for (s2 = s + strlen(s) - 1; s2 > s; s2--) + if (*s2 == ' ' || *s2 == '\t') + *s2 = 0; + else + break; + + if (! XParseColor (dpy, cmap, s, &color)) + { + fprintf (stderr, "%s: can't parse color %s", progname, s); + ok = False; + goto DEFAULT; + } + if (! XAllocColor (dpy, cmap, &color)) + { + fprintf (stderr, "%s: couldn't allocate color %s", progname, s); + ok = False; + goto DEFAULT; + } + return color.pixel; + DEFAULT: + { + if (!ok) + fprintf (stderr, ": using black.\n"); + color.flags = DoRed|DoGreen|DoBlue; + color.red = color.green = color.blue = 0; + if (XAllocColor (dpy, cmap, &color)) + return color.pixel; + else + { + fprintf (stderr, "%s: couldn't allocate black either!\n", progname); + /* We can't use BlackPixel/WhitePixel here, because we don't know + what screen we're allocating on (only an issue when running inside + the xscreensaver daemon: for hacks, DefaultScreen is fine.) + */ + return 0; + } + } +} unsigned int get_pixel_resource (char *res_name, char *res_class, diff -urP xscreensaver-4.22/utils/resources.h xscreensaver-4.22-lock/utils/resources.h --- xscreensaver-4.22/utils/resources.h 2003-03-16 05:24:50.000000000 +0000 +++ xscreensaver-4.22-lock/utils/resources.h 2005-06-27 16:47:31.000000000 +0100 @@ -17,6 +17,7 @@ extern Bool get_boolean_resource (char*,char*); extern int get_integer_resource (char*,char*); extern double get_float_resource (char*,char*); +extern unsigned int parse_pixel_resource (char*,Display*,Colormap); extern unsigned int get_pixel_resource (char*,char*,Display*,Colormap); extern unsigned int get_minutes_resource (char*,char*); extern unsigned int get_seconds_resource (char*,char*); @@ -29,5 +30,12 @@ unsigned long **pixels_ret, int *npixels_ret, Pixmap *mask_ret, Bool big_p); +extern Pixmap +xscreensaver_xpm (Screen *screen, Visual *visual, + Drawable drawable, Colormap cmap, + unsigned long background_color, + unsigned long **pixels_ret, int *npixels_ret, + Pixmap *mask_ret, + const char * const *xpm_data); #endif /* __XSCREENSAVER_RESOURCES_H__ */