Patch for enhanced Gtk+ theme accessibility support



Hi:

Attached is a patch for GTK+ (GtkSettings, GtkStyle, GtkEntry,
GtkTextDisplay, GtkTextView) that improves support for low-vision
themes.  (See bugs 61079 and 61081) 
I attach a sample theme below, and the patch follows.

In particular, line thickness and pattern for the default draw_focus
implementation is now themeable via rc files.  Similarly, line thickness
for entry fields and textviews is now controlled via properties on
GtkEntry and GtkTextView.  

NOTE: There is an argument for making focus-line
color themeable as well, for low-vision users who find high-contrast 
painful, but I did not do that yet.  Note that gdk_color_black and
gdk_color_white are not user-controllable, so code that uses these
color literals will override themes, and theme engine code that uses 
them will have limitations in contrast-themability.

I am pretty sure that the draw_focus enhancement is the right approach;
however I think there are alternate approaches to the cursor line 
patch that may be preferable.  The implementation was chosen mostly
on the basis of being the smallest delta that would get the job done.

The patch below attaches separate properties GtkEntry and GtkTextView 
for cursor line thickness, which may be overkill.  Also, since the
cursor for GtkTextView is drawn by code in gtktextdisplay.c, it may
be wrong to call gtk_widget_style_get() on the widget being displayed,
in case it does not derive from GtkTextView and thus does not have
the cursor_line_thickness property installed.  I am open to suggestions
as to where this property should be installed... of course it could be
made a property of GtkSettings, like focus-line-thickness.

Also, in the gtktextdisplay code (which is not used by GtkEntry),
there is no special cursor_gc, instead the base or text gc-s are
reused (for the strong and weak cursor, respectively).  It may be 
that for accessibility, where the purpose of thickening the cursor 
line is for legibility, we should just modify the base and text
graphics contexts' line styles when they are initialized in
gtk_style_real_realize (), so that all 'default width' lines are 
given a specific thickness (and cap and join, though we probably 
don't need to customize these).  This would go more to the root of 
the problem, which involves avoiding thin lines when using low-vision 
themes, though I am not sure how performance would be impacted, and 
any drawing code that assumes single-width lines might behave weirdly.

Lastly, I am not saving/restoring the gc line style when re-using 
base_gc in gtktextdisplay.c, do I need to ?

- Bill

--------------------

# High-Contrast, Large Print Theme v0.1
# This is the whole basic theme, just this one gtkrc file.
# It uses components of the standard theme engine
# Written by Bill Haneman, based on Standard theme by T. Liebeck, 
# which was in turn based on lots of different gtkrc files but
# primarily the one for the metal theme.
# email: bill haneman sun com

gtk-focus-line-width = 3
gtk-focus-line-pattern = "\10\1"

style "default"
{
  font_name = "sans 18"

  GtkEntry::cursor_color    = { 0.80, 0.00, 0.00 }
  GtkEntry::cursor_line_thickness = 2  
  GtkTextView::cursor_line_thickness = 2

  fg[NORMAL]      = { 0.00, 0.00, 0.00 }
  text[NORMAL]      = { 0.00, 0.00, 0.00 }
  bg[NORMAL]      = { 1.00, 1.00, 1.00 }
  base[NORMAL]    = { 1.00, 1.00, 1.00 }

  fg[INSENSITIVE]      = { 0.6, 0.6, 0.6 }
  bg[INSENSITIVE]      = { 0.75, 0.75, 0.77 }
  base[INSENSITIVE]      = { 0.75, 0.75, 0.77 }

  fg[PRELIGHT]    = { 0.80, 0.80, 1.00 }
  text[PRELIGHT]    = { 0.80, 0.80, 1.00 }
  bg[PRELIGHT]    = { 0.00, 0.00, 0.00 }
  base[PRELIGHT]    = { 0.00, 0.00, 0.00 }

  fg[ACTIVE]      = { 0.00, 0.00, 0.00 }
  text[ACTIVE]      = { 0.00, 0.00, 0.00 }
  bg[ACTIVE]      = { 0.65, 0.65, 0.50 }
  base[ACTIVE]      = { 0.65, 0.65, 0.50 }

  fg[SELECTED]    = { 1.00, 1.00, 1.00 }
  text[SELECTED]    = { 1.00, 1.00, 1.00 }
  bg[SELECTED]    = { 0.00, 0.00, 0.00 }
  base[SELECTED]    = { 0.10, 0.20, 0.20 }

  xthickness = 3
  ythickness = 3
 
}

class "GtkWidget" style "default"

------------------------------------------------
Index: gtk/gtkentry.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkentry.c,v
retrieving revision 1.149
diff -c -r1.149 gtkentry.c
*** gtk/gtkentry.c	2001/09/19 00:49:51	1.149
--- gtk/gtkentry.c	2001/09/24 19:26:07
***************
*** 469,474 ****
--- 469,481 ----
  							       GDK_TYPE_COLOR,
  							       G_PARAM_READABLE));
  
+   gtk_widget_class_install_style_property (widget_class,
+ 					   g_param_spec_int ("cursor_line_thickness",
+ 							     _("Cursor line thickness"),
+ 							     _("Line thickness with which to draw insertion cursor"),
+ 							     0, 32, 1,
+ 							     G_PARAM_READABLE));
+ 
    signals[INSERT_TEXT] =
      gtk_signal_new ("insert_text",
  		    GTK_RUN_LAST,
***************
*** 934,949 ****
  {
    GdkColor *cursor_color;
    GdkColor red = {0, 0xffff, 0x0000, 0x0000};
    
    if (entry->cursor_gc)
      gdk_gc_unref (entry->cursor_gc);
! 
    gtk_widget_style_get (GTK_WIDGET (entry), "cursor_color",
&cursor_color, NULL);
!       entry->cursor_gc = gdk_gc_new (entry->text_area);
    if (cursor_color)
      gdk_gc_set_rgb_fg_color (entry->cursor_gc, cursor_color);
    else
      gdk_gc_set_rgb_fg_color (entry->cursor_gc, &red);
  }
  
  static void
--- 941,969 ----
  {
    GdkColor *cursor_color;
    GdkColor red = {0, 0xffff, 0x0000, 0x0000};
+   gint cursor_line_thickness = 1;
    
    if (entry->cursor_gc)
      gdk_gc_unref (entry->cursor_gc);
!   
    gtk_widget_style_get (GTK_WIDGET (entry), "cursor_color",
&cursor_color, NULL);
!   entry->cursor_gc = gdk_gc_new (entry->text_area);
    if (cursor_color)
      gdk_gc_set_rgb_fg_color (entry->cursor_gc, cursor_color);
    else
      gdk_gc_set_rgb_fg_color (entry->cursor_gc, &red);
+ 
+   gtk_widget_style_get (GTK_WIDGET (entry),
+ 			"cursor_line_thickness",
+ 			&cursor_line_thickness,
+ 			NULL);
+ 
+   if (cursor_line_thickness)
+     gdk_gc_set_line_attributes (entry->cursor_gc,
+ 				cursor_line_thickness,
+ 				GDK_LINE_SOLID,
+ 				GDK_CAP_BUTT,
+ 				GDK_JOIN_MITER);
  }
  
  static void
Index: gtk/gtksettings.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtksettings.c,v
retrieving revision 1.16
diff -c -r1.16 gtksettings.c
*** gtk/gtksettings.c	2001/08/11 20:27:36	1.16
--- gtk/gtksettings.c	2001/09/24 19:26:09
***************
*** 28,34 ****
    PROP_CURSOR_BLINK_TIME,
    PROP_SPLIT_CURSOR,
    PROP_THEME_NAME,
!   PROP_KEY_THEME_NAME
  };
  
  
--- 28,36 ----
    PROP_CURSOR_BLINK_TIME,
    PROP_SPLIT_CURSOR,
    PROP_THEME_NAME,
!   PROP_KEY_THEME_NAME,
!   PROP_FOCUS_LINE_WIDTH,
!   PROP_FOCUS_LINE_PATTERN
  };
  
  
***************
*** 188,193 ****
--- 190,211 ----
  								  G_PARAM_READWRITE),
                                               NULL);
    g_assert (result == PROP_KEY_THEME_NAME);
+   result = settings_install_property_parser (class,
+                                              g_param_spec_int
("gtk-focus-line-width",
+ 							       _("Focus-draw linewidth"),
+ 							       _("Linewidth of default focus indication box"),
+ 							       0, 8, 1,
+ 							       G_PARAM_READWRITE),
+                                              NULL);
+   g_assert (result == PROP_FOCUS_LINE_WIDTH);
+   result = settings_install_property_parser (class,
+                                              g_param_spec_string
("gtk-focus-line-pattern",
+ 								  _("Focus-draw line dashes"),
+ 								  _("Dash pattern for default focus indication"),
+ 								  "\1\1",
+ 								  G_PARAM_READWRITE),
+                                              NULL);
+   g_assert (result == PROP_FOCUS_LINE_PATTERN);
  }
  
  static void
Index: gtk/gtkstyle.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkstyle.c,v
retrieving revision 1.80
diff -c -r1.80 gtkstyle.c
*** gtk/gtkstyle.c	2001/09/18 20:06:46	1.80
--- gtk/gtkstyle.c	2001/09/24 19:26:13
***************
*** 3774,3791 ****
  			gint           height)
  {
    GdkPoint points[5];
    
    sanitize_size (window, &width, &height);
    
    if (area)
      gdk_gc_set_clip_rectangle (style->black_gc, area);
  
!   gdk_gc_set_line_attributes (style->black_gc, 1,
GDK_LINE_ON_OFF_DASH, 0, 0);
  
    if (detail && !strcmp (detail, "add-mode"))
      gdk_gc_set_dashes (style->black_gc, 0, "\4\4", 2);
    else
!     gdk_gc_set_dashes (style->black_gc, 0, "\1\1", 2);
  
    points[0].x = x;
    points[0].y = y;
--- 3774,3801 ----
  			gint           height)
  {
    GdkPoint points[5];
+   gint8    *dash_list;
+   gint     line_width = 2;
+   GValue   value = { 0, };
+ 
+   g_object_get (gtk_settings_get_default (),
+ 		"gtk-focus-line-width",
+ 		&line_width,
+ 		"gtk-focus-line-pattern",
+ 		(gchar *)&dash_list,
+ 		NULL);
    
    sanitize_size (window, &width, &height);
    
    if (area)
      gdk_gc_set_clip_rectangle (style->black_gc, area);
  
!   gdk_gc_set_line_attributes (style->black_gc, line_width,
GDK_LINE_ON_OFF_DASH, 0, 0);
  
    if (detail && !strcmp (detail, "add-mode"))
      gdk_gc_set_dashes (style->black_gc, 0, "\4\4", 2);
    else
!     gdk_gc_set_dashes (style->black_gc, 0, dash_list, strlen
(dash_list));
  
    points[0].x = x;
    points[0].y = y;
Index: gtk/gtktextdisplay.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtktextdisplay.c,v
retrieving revision 1.29
diff -c -r1.29 gtktextdisplay.c
*** gtk/gtktextdisplay.c	2001/09/19 00:49:52	1.29
--- gtk/gtktextdisplay.c	2001/09/24 19:26:14
***************
*** 485,491 ****
  render_para (GdkDrawable        *drawable,
               GtkTextRenderState *render_state,
               GtkTextLineDisplay *line_display,
!              /* Top-left corner of paragraph including all margins */
               int                 x,
               int                 y,
               int                 selection_start_index,
--- 485,491 ----
  render_para (GdkDrawable        *drawable,
               GtkTextRenderState *render_state,
               GtkTextLineDisplay *line_display,
!              /* Top-left corner of paragraph including all margin */
               int                 x,
               int                 y,
               int                 selection_start_index,
***************
*** 733,738 ****
--- 733,739 ----
    GtkTextRenderState *render_state;
    GtkTextIter selection_start, selection_end;
    gboolean have_selection = FALSE;
+   gint cursor_line_thickness = 1;
    GSList *line_list;
    GSList *tmp_list;
    
***************
*** 823,828 ****
--- 824,834 ----
            /* We paint the cursors last, because they overlap another
chunk
           and need to appear on top. */
  
+ 	  gtk_widget_style_get (widget,
+ 				"cursor_line_thickness",
+ 				&cursor_line_thickness,
+ 				NULL);
+ 	      
            cursor_list = line_display->cursors;
            while (cursor_list)
              {
***************
*** 835,840 ****
--- 841,854 ----
                  gc = widget->style->text_gc[GTK_STATE_NORMAL];
  
                gdk_gc_set_clip_rectangle (gc, &clip);
+ 	      
+ 	      if (cursor_line_thickness)
+ 	        gdk_gc_set_line_attributes (gc,
+ 					    cursor_line_thickness,
+ 					    GDK_LINE_SOLID,
+ 					    GDK_CAP_BUTT,
+ 					    GDK_JOIN_MITER);
+ 
                gdk_draw_line (drawable, gc,
                               line_display->x_offset + cursor->x -
x_offset,
                               current_y + line_display->top_margin +
cursor->y,
Index: gtk/gtktextview.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtktextview.c,v
retrieving revision 1.112
diff -c -r1.112 gtktextview.c
*** gtk/gtktextview.c	2001/09/22 00:08:18	1.112
--- gtk/gtktextview.c	2001/09/24 19:26:18
***************
*** 129,134 ****
--- 129,135 ----
    PROP_INDENT,
    PROP_TABS,
    PROP_CURSOR_VISIBLE,
+   PROP_CURSOR_THICKNESS,
    LAST_PROP
  };
  
***************
*** 618,624 ****
  							 TRUE,
  							 G_PARAM_READWRITE));
  
!   
    /*
     * Signals
     */
--- 619,630 ----
  							 TRUE,
  							 G_PARAM_READWRITE));
  
!   gtk_widget_class_install_style_property (gobject_class,
! 					   g_param_spec_int ("cursor_line_thickness",
! 							     _("Cursor line thickness"),
! 							     _("Line thickness with which to draw insertion cursor"),
! 							     0, 32, 1,
! 							     G_PARAM_READABLE));
    /*
     * Signals
     */




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]