Commit 4a8546fc authored by Brian Cameron's avatar Brian Cameron Committed by Brian Cameron

Add pam-error-logo item type. Add item type button to use a real GTK+

2006-04-26  Brian Cameron  <brian.cameron@sun.com>

        * gui/greeter_item_pam.c: Add pam-error-logo item type.
        * gui/greeter/greeter_item.h, gui/greeter/greeter_canvas_item.c,
          gui/greeter/greeter_geometry, gui/greeter/greeter_parser.c: Add item
          type button to use a real GTK+ button, this better supports
          accessibility.  Add "startover" string to stock, this better name
          for the "Cancel" button was recommended.
        * gui/greeter/themes/happygnome/happygnome.xml,
          gui/greeter/themes/happygnome/happygnome-list.xml,
          gui/greeter/themes/circles/circles.xml: Updated theme to use real
          GTK+ buttons.  Now says "Start Over" instead of "Cancel" on the
          button.
        * gui/greeter/greeter_events.c, gui/greeter/greeter_item.c: Code
          cleanup.
        * docs/gdm/gdm.xml: Add docs for new features and the gtk-theme
          greeter element feature added in 2.12 but after string-freeze, so
          docs couldn't be updated then.
parent 425ce74b
2006-04-26 Brian Cameron <brian.cameron@sun.com>
* gui/greeter_item_pam.c: Add pam-error-logo item type.
* gui/greeter/greeter_item.h, gui/greeter/greeter_canvas_item.c,
gui/greeter/greeter_geometry, gui/greeter/greeter_parser.c: Add item
type button to use a real GTK+ button, this better supports
accessibility. Add "startover" string to stock, this better name
for the "Cancel" button was recommended.
* gui/greeter/themes/happygnome/happygnome.xml,
gui/greeter/themes/happygnome/happygnome-list.xml,
gui/greeter/themes/circles/circles.xml: Updated theme to use real
GTK+ buttons. Now says "Start Over" instead of "Cancel" on the
button.
* gui/greeter/greeter_events.c, gui/greeter/greeter_item.c: Code
cleanup.
* docs/gdm/gdm.xml: Add docs for new features and the gtk-theme
greeter element feature added in 2.12 but after string-freeze, so
docs couldn't be updated then.
2006-04-26 Brian Cameron <brian.cameron@sun.com>
Adding per-display configuration support to GDM. Now if user has
......
......@@ -5340,6 +5340,33 @@ tar czvf &lt;theme_name&gt;.tar.gz &lt;theme_name&gt;/
<sect2 id="descofthemeformat">
<title>Detailed Description of Theme XML format</title>
<sect3 id="greetertag">
<title>greeter tag</title>
<para>
The GDM theme format is specified in XML format contained
within a &lt;greeter&gt; tag. You may specify a GTK+ theme to
be used with this theme by using the gtk-theme element in the
greeter tag as in the following example.
</para>
<screen>
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE greeter SYSTEM "greeter.dtd"&gt;
&lt;greeter gtk-theme="Crux"&gt;
[...]
&lt;/greeter&gt;
</screen>
<para>
Contained within the greeter tag can be the nodes described
in the next sections of this document. Some of these nodes are
containers (box nodes, rect item nodes) which can be used to
organize how to display the nodes that the user sees and interacts
with (such as button, pixmap and entry item nodes).
</para>
</sect3>
<sect3 id="boxnodes">
<title>Box Nodes</title>
......@@ -5401,19 +5428,24 @@ homogeneous=&quot;bool&quot;&gt;
<variablelist>
<varlistentry>
<term>entry</term>
<term>button</term>
<listitem>
<para>
Text entry field.
A button field. This field uses a GTK+ button. It is also
possible to make a "rect" item act like a button by setting
its button element to true. However it is better to use
GTK+ buttons in GDM themes since these are accessible to
users with disabilities. Also, GTK+ buttons can be
themed.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>list</term>
<term>entry</term>
<listitem>
<para>
A list widget.
Text entry field.
</para>
</listitem>
</varlistentry>
......@@ -5428,6 +5460,16 @@ homogeneous=&quot;bool&quot;&gt;
</listitem>
</varlistentry>
<varlistentry>
<term>list</term>
<listitem>
<para>
A face browser widget. Only useful if the face browser is
enabled via the configuration.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>pixmap</term>
<listitem>
......@@ -5544,6 +5586,17 @@ homogeneous=&quot;bool&quot;&gt;
</listitem>
</varlistentry>
<varlistentry>
<term>pam-error-logo</term>
<listitem>
<para>
An image that will be displayed only when a pam-error message
is being displayed. This is useful for displaying an
&quot;Attention&quot; icon, for example.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>pam-message</term>
<listitem>
......@@ -6027,6 +6080,9 @@ homogeneous=&quot;bool&quot;&gt;
<para>
<filename>session</filename>, _(&quot;_Session&quot;
</para>
<para>
<filename>startover</filename>, _(&quot;_Start Over&quot;
</para>
<para>
<filename>suspend</filename>, _(&quot;Sus_pend&quot;
</para>
......
......@@ -2869,6 +2869,22 @@ tar czvf &lt;theme_name&gt;.tar.gz &lt;theme_name&gt;/
<sect2 id="descofthemeformat">
<title>Detailed Description of Theme XML format</title>
<sect3 id="greetertag">
<title>greeter tag</title>
<para>The GDM theme format is specified in XML format contained within a &lt;greeter&gt; tag. You may specify a GTK+ theme to be used with this theme by using the gtk-theme element in the greeter tag as in the following example.</para>
<screen>
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE greeter SYSTEM "greeter.dtd"&gt;
&lt;greeter gtk-theme="Crux"&gt;
[...]
&lt;/greeter&gt;
</screen>
<para>Contained within the greeter tag can be the nodes described in the next sections of this document. Some of these nodes are containers (box nodes, rect item nodes) which can be used to organize how to display the nodes that the user sees and interacts with (such as button, pixmap and entry item nodes).</para>
</sect3>
<sect3 id="boxnodes">
<title>Nodos contenedores.</title>
......@@ -2900,16 +2916,16 @@ homogeneous="bool"&gt;
<variablelist>
<varlistentry>
<term>entry</term>
<term>button</term>
<listitem>
<para>Campo de entrada de texto.</para>
<para>A button field. This field uses a GTK+ button. It is also possible to make a "rect" item act like a button by setting its button element to true. However it is better to use GTK+ buttons in GDM themes since these are accessible to users with disabilities. Also, GTK+ buttons can be themed.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>list</term>
<term>entry</term>
<listitem>
<para>Un widget de lista</para>
<para>Campo de entrada de texto.</para>
</listitem>
</varlistentry>
......@@ -2920,6 +2936,13 @@ homogeneous="bool"&gt;
</listitem>
</varlistentry>
<varlistentry>
<term>list</term>
<listitem>
<para>A face browser widget. Only useful if the face browser is enabled via the configuration.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>pixmap</term>
<listitem>
......@@ -2995,6 +3018,13 @@ homogeneous="bool"&gt;
</listitem>
</varlistentry>
<varlistentry>
<term>pam-error-logo</term>
<listitem>
<para>An image that will be displayed only when a pam-error message is being displayed. This is useful for displaying an "Attention" icon, for example.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>pam-message</term>
<listitem>
......@@ -3233,6 +3263,7 @@ homogeneous="bool"&gt;
<para><filename>quit</filename>, _("_Salir"</para>
<para><filename>reboot</filename>, _("_Reiniciar"</para>
<para><filename>session</filename>, _("_Sesión"</para>
<para><filename>startover</filename>, _("_Start Over"</para>
<para><filename>suspend</filename>, _("Sus_pender"</para>
<para><filename>system</filename>, _("_Acciones" (Anteriormente "S_istema"</para>
<para><filename>timed-label</filename>, _("El usuario %u entrará en %t"</para>
......
......@@ -2867,6 +2867,22 @@ tar czvf &lt;theme_name&gt;.tar.gz &lt;theme_name&gt;/
<sect2 id="descofthemeformat">
<title>Докладний опис XML формату тем</title>
<sect3 id="greetertag">
<title>greeter tag</title>
<para>The GDM theme format is specified in XML format contained within a &lt;greeter&gt; tag. You may specify a GTK+ theme to be used with this theme by using the gtk-theme element in the greeter tag as in the following example.</para>
<screen>
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE greeter SYSTEM "greeter.dtd"&gt;
&lt;greeter gtk-theme="Crux"&gt;
[...]
&lt;/greeter&gt;
</screen>
<para>Contained within the greeter tag can be the nodes described in the next sections of this document. Some of these nodes are containers (box nodes, rect item nodes) which can be used to organize how to display the nodes that the user sees and interacts with (such as button, pixmap and entry item nodes).</para>
</sect3>
<sect3 id="boxnodes">
<title>Box Nodes</title>
......@@ -2898,16 +2914,16 @@ homogeneous="bool"&gt;
<variablelist>
<varlistentry>
<term>entry</term>
<term>button</term>
<listitem>
<para>Поле вводу тексту.</para>
<para>A button field. This field uses a GTK+ button. It is also possible to make a "rect" item act like a button by setting its button element to true. However it is better to use GTK+ buttons in GDM themes since these are accessible to users with disabilities. Also, GTK+ buttons can be themed.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>list</term>
<term>entry</term>
<listitem>
<para>Віджет списку.</para>
<para>Поле вводу тексту.</para>
</listitem>
</varlistentry>
......@@ -2918,6 +2934,13 @@ homogeneous="bool"&gt;
</listitem>
</varlistentry>
<varlistentry>
<term>list</term>
<listitem>
<para>A face browser widget. Only useful if the face browser is enabled via the configuration.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>pixmap</term>
<listitem>
......@@ -2993,6 +3016,13 @@ homogeneous="bool"&gt;
</listitem>
</varlistentry>
<varlistentry>
<term>pam-error-logo</term>
<listitem>
<para>An image that will be displayed only when a pam-error message is being displayed. This is useful for displaying an "Attention" icon, for example.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>pam-message</term>
<listitem>
......@@ -3231,6 +3261,7 @@ homogeneous="bool"&gt;
<para><filename>quit</filename>, _("_Quit"</para>
<para><filename>reboot</filename>, _("_Restart"</para>
<para><filename>session</filename>, _("_Session"</para>
<para><filename>startover</filename>, _("_Start Over"</para>
<para><filename>suspend</filename>, _("Sus_pend"</para>
<para><filename>system</filename>, _("_Actions" (Formerly "S_ystem"</para>
<para><filename>timed-label</filename>, _("User %u will login in %t"</para>
......
......@@ -227,12 +227,19 @@ greeter_options_handler (GreeterItemInfo *item, GtkWidget *menubar)
item, 0, gtk_get_current_event_time());
}
void
greeter_item_run_button_action_callback (GtkButton *button, const char *id)
{
greeter_item_run_action_callback (id);
}
void
greeter_item_create_canvas_item (GreeterItemInfo *item)
{
GnomeCanvasGroup *group;
GtkJustification just;
GtkWidget *entry;
GtkWidget *gtkbutton;
GtkWidget *list;
GtkWidget *swin;
double x1, y1, x2, y2;
......@@ -393,14 +400,34 @@ greeter_item_create_canvas_item (GreeterItemInfo *item)
break;
case GREETER_ITEM_TYPE_BUTTON:
gtkbutton = gtk_button_new_with_mnemonic (item->data.text.orig_text);
gtk_widget_set_name (gtkbutton, item->id);
g_signal_connect (G_OBJECT (gtkbutton), "clicked",
G_CALLBACK (greeter_item_run_button_action_callback),
item->id);
item->item = gnome_canvas_item_new (group,
GNOME_TYPE_CANVAS_WIDGET,
"widget", gtkbutton,
"x", x1,
"y", y1,
"height", (double)rect.height,
"width", (double)rect.width,
NULL);
break;
case GREETER_ITEM_TYPE_ENTRY:
entry = gtk_entry_new ();
gtk_widget_set_name (entry, "user-pw-entry");
gtk_entry_set_has_frame (GTK_ENTRY (entry), FALSE);
if (gdm_config_get_bool (GDM_KEY_ENTRY_INVISIBLE))
gtk_entry_set_invisible_char (GTK_ENTRY (entry), 0);
else if (gdm_config_get_bool (GDM_KEY_ENTRY_CIRCLES))
gtk_entry_set_invisible_char (GTK_ENTRY (entry), 0x25cf);
gtk_widget_modify_font (entry, item->data.text.fonts[GREETER_ITEM_STATE_NORMAL]);
get_gdk_color_from_rgb (&c, item->data.text.colors[GREETER_ITEM_STATE_NORMAL]);
......
......@@ -202,7 +202,7 @@ greeter_item_event_handler (GnomeCanvasItem *item,
if (info->state != old_state)
{
if (info->button)
if (info->canvasbutton)
{
if (info->state == GREETER_ITEM_STATE_NORMAL)
propagate_reset_state (info, old_state);
......
......@@ -19,6 +19,7 @@
#include "config.h"
#include <gtk/gtk.h>
#include <glib/gi18n.h>
#include <librsvg/rsvg.h>
#include "gdmcommon.h"
#include "gdmwm.h"
......@@ -559,6 +560,39 @@ greeter_item_size_request (GreeterItemInfo *item,
req->height = gdk_pixbuf_get_height (svg);
g_object_unref (svg);
}
if (item->item_type == GREETER_ITEM_TYPE_BUTTON)
{
PangoLayout *layout;
PangoFontDescription *font_desc;
int pango_width, pango_height;
int pix_width, pix_height;
GtkWidget *dummy_w = gtk_button_new ();
if (strcmp (item->id, "options_button") == 0)
layout = gtk_widget_create_pango_layout (dummy_w, _("Select Language..."));
else
layout = gtk_widget_create_pango_layout (dummy_w, item->data.text.orig_text);
pango_layout_get_size (layout, &pango_width, &pango_height);
pix_height = PANGO_PIXELS (pango_height);
pix_width = PANGO_PIXELS (pango_width);
if (strcmp (item->id, "options_button") == 0)
pix_width += pix_height * 2; /* add padding for combobox */
if (pix_width > item->parent->box_min_width)
req->width = pix_width;
else
req->width = item->parent->box_min_width;
if (pix_height > item->parent->box_min_height)
req->height = pix_height;
else
req->height = item->parent->box_min_height;
}
if (req->width > 0 && req->height > 0)
{
......
......@@ -73,7 +73,8 @@ greeter_item_info_new (GreeterItemInfo *parent,
info->show_modes = GREETER_ITEM_SHOW_EVERYWHERE;
info->button = FALSE;
info->canvasbutton = FALSE;
info->gtkbutton = FALSE;
if (GREETER_ITEM_TYPE_IS_TEXT (info))
{
......
......@@ -46,7 +46,8 @@ enum _GreeterItemType {
GREETER_ITEM_TYPE_PIXMAP,
GREETER_ITEM_TYPE_LABEL,
GREETER_ITEM_TYPE_ENTRY,
GREETER_ITEM_TYPE_LIST
GREETER_ITEM_TYPE_LIST,
GREETER_ITEM_TYPE_BUTTON
};
/* Make sure to adjust the bitfield in the structure if
......@@ -112,8 +113,12 @@ struct _GreeterItemInfo {
/* box flags */
guint box_homogeneous:1;
/* is a button (see my_button comment) */
guint button:1;
/* is a canvas rectangle that acts like a button */
/* (see the my_button comment) */
guint canvasbutton:1;
/* is a real GTK button (not the fake canvas button) */
guint gtkbutton:1;
/* geometry handling: */
guint has_requisition:1;
......
......@@ -26,6 +26,7 @@
#include "viciousui.h"
#include "greeter.h"
#include "greeter_item.h"
#include "greeter_item_pam.h"
#include "greeter_item_ulist.h"
#include "greeter_item_timed.h"
......@@ -46,6 +47,30 @@ gboolean require_quarter = FALSE;
extern gboolean greeter_probably_login_prompt;
gboolean
greeter_item_pam_error_set (gboolean display)
{
GreeterItemInfo *info;
GnomeCanvasItem *item;
info = greeter_lookup_id ("pam-error-logo");
if (info)
{
if (info->group_item != NULL)
item = GNOME_CANVAS_ITEM (info->group_item);
else
item = info->item;
if (display)
gnome_canvas_item_show (item);
else
gnome_canvas_item_hide (item);
}
return TRUE;
}
void
greeter_item_pam_set_user (const char *user)
{
......@@ -129,8 +154,10 @@ greeter_item_pam_login (GtkEntry *entry, GreeterItemInfo *info)
err_box_clear_handler = 0;
}
error_info = greeter_lookup_id ("pam-error");
if (error_info)
if (error_info) {
greeter_item_pam_error_set (FALSE);
set_text (error_info, "");
}
tmp = ve_locale_from_utf8 (str);
printf ("%c%s\n", STX, tmp);
......@@ -165,6 +192,8 @@ greeter_item_pam_setup (void)
{
GreeterItemInfo *entry_info;
greeter_item_pam_error_set (FALSE);
entry_info = greeter_lookup_id ("user-pw-entry");
if (entry_info && entry_info->item &&
GNOME_IS_CANVAS_WIDGET (entry_info->item) &&
......@@ -191,6 +220,7 @@ greeter_item_pam_setup (void)
g_signal_connect (G_OBJECT (entry), "key_press_event",
G_CALLBACK (key_press_event), NULL);
}
return TRUE;
}
......@@ -272,10 +302,11 @@ static gboolean
error_clear (gpointer data)
{
GreeterItemInfo *error_info = data;
err_box_clear_handler = 0;
set_text (error_info, "");
greeter_item_pam_error_set (FALSE);
err_box_clear_handler = 0;
return FALSE;
}
......@@ -299,12 +330,14 @@ greeter_item_pam_error (const char *message)
if (err_box_clear_handler > 0)
g_source_remove (err_box_clear_handler);
if (strlen (message) == 0)
err_box_clear_handler = 0;
else
err_box_clear_handler = g_timeout_add (30000,
error_clear,
error_info);
greeter_item_pam_error_set (TRUE);
}
}
......
......@@ -114,38 +114,6 @@ parse_id (xmlNodePtr node,
}
}
static gboolean
parse_button (xmlNodePtr node,
GreeterItemInfo *info,
GError **error)
{
xmlChar *prop;
prop = xmlGetProp (node,(const xmlChar *) "button");
if (prop)
{
if (strcmp ((char *) prop, "true") == 0)
{
info->button = TRUE;
}
else if (strcmp ((char *) prop, "false") == 0)
{
info->button = FALSE;
}
else
{
g_set_error (error,
GREETER_PARSER_ERROR,
GREETER_PARSER_ERROR_BAD_SPEC,
"bad button spec %s", prop);
xmlFree (prop);
return FALSE;
}
xmlFree (prop);
}
return TRUE;
}
/* Doesn't set the parts of rect that are not specified.
* If you want specific default values you need to fill them out
* in rect first
......@@ -333,6 +301,251 @@ parse_pos (xmlNodePtr node,
return TRUE;
}
/* We pass the same arguments as to translated text, since we'll override it
* with translation score */
static gboolean
parse_stock (xmlNodePtr node,
GreeterItemInfo *info,
char **translated_text,
gint *translation_score,
GError **error)
{
xmlChar *prop;
prop = xmlGetProp (node,(const xmlChar *) "type");
if (prop)
{
if (g_ascii_strcasecmp ((char *) prop, "language") == 0)
{
g_free (*translated_text);
*translated_text = g_strdup (_("_Language"));
}
else if (g_ascii_strcasecmp ((char *) prop, "session") == 0)
{
g_free (*translated_text);
*translated_text = g_strdup (_("_Session"));
}
else if (g_ascii_strcasecmp ((char *) prop, "system") == 0)
{
g_free (*translated_text);
*translated_text = g_strdup (_("_Actions"));
}
else if (g_ascii_strcasecmp ((char *) prop, "disconnect") == 0)
{
g_free (*translated_text);
*translated_text = g_strdup (_("D_isconnect"));
}
else if (g_ascii_strcasecmp ((char *) prop, "quit") == 0)
{
g_free (*translated_text);
*translated_text = g_strdup (_("_Quit"));
}
else if (g_ascii_strcasecmp ((char *) prop, "halt") == 0)
{
g_free (*translated_text);
*translated_text = g_strdup (_("Shut _Down"));
}
else if (g_ascii_strcasecmp ((char *) prop, "suspend") == 0)
{
g_free (*translated_text);
*translated_text = g_strdup (_("Sus_pend"));
}
else if (g_ascii_strcasecmp ((char *) prop, "reboot") == 0)
{
g_free (*translated_text);
*translated_text = g_strdup (_("_Restart"));
}
else if (g_ascii_strcasecmp ((char *) prop, "chooser") == 0)
{
g_free (*translated_text);
*translated_text = g_strdup (_("Remote Login via _XDMCP"));
}
else if (g_ascii_strcasecmp ((char *) prop, "config") == 0)
{
g_free (*translated_text);
*translated_text = g_strdup (_("Confi_gure"));
}
else if (g_ascii_strcasecmp ((char *) prop, "options") == 0)
{
g_free (*translated_text);
*translated_text = g_strdup (_("Op_tions"));
}
else if (g_ascii_strcasecmp ((char *) prop, "caps-lock-warning") == 0)
{
g_free (*translated_text);
*translated_text = g_strdup (_("Caps Lock is on."));
}
else if (g_ascii_strcasecmp ((char *) prop, "timed-label") == 0)
{
g_free (*translated_text);
*translated_text = g_strdup (_("User %u will login in %t"));
}
else if (g_ascii_strcasecmp ((char *) prop, "welcome-label") == 0)
{
/* FIXME: hack */
welcome_string_info = info;
g_free (*translated_text);
*translated_text = gdm_common_get_welcomemsg ();
}
/* FIXME: is this actually needed? */
else if (g_ascii_strcasecmp ((char *) prop, "username-label") == 0)
{
g_free (*translated_text);
*translated_text = g_strdup (_("Username:"));
}
else if (g_ascii_strcasecmp ((char *) prop, "ok") == 0)
{
g_free (*translated_text);
*translated_text = g_strdup (_("_OK"));
}
else if (g_ascii_strcasecmp ((char *) prop, "cancel") == 0)
{
g_free (*translated_text);
*translated_text = g_strdup (_("_Cancel"));
}
else if (g_ascii_strcasecmp ((char *) prop, "startover") == 0)
{
g_free (*translated_text);
*translated_text = g_strdup (_("_Start Over"));
}
else
{
g_set_error (error,
GREETER_PARSER_ERROR,
GREETER_PARSER_ERROR_BAD_SPEC,
"Bad stock label type");
xmlFree (prop);
return FALSE;
}
/* This is the very very very best "translation" */
*translation_score = -1;
xmlFree (prop);
return TRUE;
}
else
{
g_set_error (error,
GREETER_PARSER_ERROR,
GREETER_PARSER_ERROR_BAD_SPEC,
"Stock type not specified");
return FALSE;
}
}
static void
do_font_size_reduction (GreeterItemInfo *info)
{
double size_reduction = 1.0;
int i;
if (gdm_wm_screen.width <= 800 &&
gdm_wm_screen.width > 640)
size_reduction = PANGO_SCALE_SMALL;
else if (gdm_wm_screen.width <= 640)
size_reduction = PANGO_SCALE_X_SMALL;
if (size_reduction < 0.99)
{
for (i = 0; i < GREETER_ITEM_STATE_MAX; i++)
{
if (info->data.text.fonts[i] != NULL)
{
int old_size = pango_font_description_get_size (info->data.text.fonts[i]);
pango_font_description_set_size (info->data.text.fonts[i], old_size * size_reduction);
}
}
}
}
static gboolean
parse_canvasbutton (xmlNodePtr node,
GreeterItemInfo *info,
GError **error)
{
xmlChar *prop;
prop = xmlGetProp (node,(const xmlChar *) "button");
if (prop)
{
if (strcmp ((char *) prop, "true") == 0)
{
info->canvasbutton = TRUE;
}
else if (strcmp ((char *) prop, "false") == 0)
{