]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkentry.c
Don't check resize-grip-visible in default values unit test
[~andy/gtk] / gtk / gtkentry.c
index 4b0d1cade4061d931470bafaf35b95087a71642a..040d35bb45387990cfef9084fa1002a57a743386 100644 (file)
@@ -53,7 +53,6 @@
 #include "gtkseparatormenuitem.h"
 #include "gtkselection.h"
 #include "gtksettings.h"
-#include "gtksizerequest.h"
 #include "gtkspinbutton.h"
 #include "gtkstock.h"
 #include "gtktextutil.h"
@@ -237,7 +236,7 @@ typedef enum
   DISPLAY_BLANK         /* In invisible mode, nothing shown at all */
 } DisplayMode;
 
-/* GObject, GtkObject methods
+/* GObject methods
  */
 static void   gtk_entry_editable_init        (GtkEditableInterface *iface);
 static void   gtk_entry_cell_editable_init   (GtkCellEditableIface *iface);
@@ -250,11 +249,11 @@ static void   gtk_entry_get_property         (GObject          *object,
                                               GValue           *value,
                                               GParamSpec       *pspec);
 static void   gtk_entry_finalize             (GObject          *object);
-static void   gtk_entry_destroy              (GtkObject        *object);
 static void   gtk_entry_dispose              (GObject          *object);
 
 /* GtkWidget methods
  */
+static void   gtk_entry_destroy              (GtkWidget        *widget);
 static void   gtk_entry_realize              (GtkWidget        *widget);
 static void   gtk_entry_unrealize            (GtkWidget        *widget);
 static void   gtk_entry_map                  (GtkWidget        *widget);
@@ -264,11 +263,12 @@ static void   gtk_entry_size_request         (GtkWidget        *widget,
 static void   gtk_entry_size_allocate        (GtkWidget        *widget,
                                              GtkAllocation    *allocation);
 static void   gtk_entry_draw_frame           (GtkWidget        *widget,
-                                              GdkEventExpose   *event);
+                                              cairo_t          *cr);
 static void   gtk_entry_draw_progress        (GtkWidget        *widget,
-                                              GdkEventExpose   *event);
-static gint   gtk_entry_expose               (GtkWidget        *widget,
-                                             GdkEventExpose   *event);
+                                              cairo_t          *cr,
+                                              GdkWindow        *window);
+static gint   gtk_entry_draw                 (GtkWidget        *widget,
+                                              cairo_t          *cr);
 static gint   gtk_entry_button_press         (GtkWidget        *widget,
                                              GdkEventButton   *event);
 static gint   gtk_entry_button_release       (GtkWidget        *widget,
@@ -416,8 +416,10 @@ static void         gtk_entry_enter_text               (GtkEntry       *entry,
 static void         gtk_entry_set_positions            (GtkEntry       *entry,
                                                        gint            current_pos,
                                                        gint            selection_bound);
-static void         gtk_entry_draw_text                (GtkEntry       *entry);
+static void         gtk_entry_draw_text                (GtkEntry       *entry,
+                                                        cairo_t        *cr);
 static void         gtk_entry_draw_cursor              (GtkEntry       *entry,
+                                                        cairo_t        *cr,
                                                        CursorType      type);
 static PangoLayout *gtk_entry_ensure_layout            (GtkEntry       *entry,
                                                         gboolean        include_preedit);
@@ -562,24 +564,23 @@ gtk_entry_class_init (GtkEntryClass *class)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
   GtkWidgetClass *widget_class;
-  GtkObjectClass *gtk_object_class;
   GtkBindingSet *binding_set;
 
   widget_class = (GtkWidgetClass*) class;
-  gtk_object_class = (GtkObjectClass *)class;
 
   gobject_class->dispose = gtk_entry_dispose;
   gobject_class->finalize = gtk_entry_finalize;
   gobject_class->set_property = gtk_entry_set_property;
   gobject_class->get_property = gtk_entry_get_property;
 
+  widget_class->destroy = gtk_entry_destroy;
   widget_class->map = gtk_entry_map;
   widget_class->unmap = gtk_entry_unmap;
   widget_class->realize = gtk_entry_realize;
   widget_class->unrealize = gtk_entry_unrealize;
   widget_class->size_request = gtk_entry_size_request;
   widget_class->size_allocate = gtk_entry_size_allocate;
-  widget_class->expose_event = gtk_entry_expose;
+  widget_class->draw = gtk_entry_draw;
   widget_class->enter_notify_event = gtk_entry_enter_notify;
   widget_class->leave_notify_event = gtk_entry_leave_notify;
   widget_class->button_press_event = gtk_entry_button_press;
@@ -608,8 +609,6 @@ gtk_entry_class_init (GtkEntryClass *class)
 
   widget_class->popup_menu = gtk_entry_popup_menu;
 
-  gtk_object_class->destroy = gtk_entry_destroy;
-
   class->move_cursor = gtk_entry_move_cursor;
   class->insert_at_cursor = gtk_entry_insert_at_cursor;
   class->delete_from_cursor = gtk_entry_delete_from_cursor;
@@ -2423,9 +2422,9 @@ emit_changed (GtkEntry *entry)
 }
 
 static void
-gtk_entry_destroy (GtkObject *object)
+gtk_entry_destroy (GtkWidget *widget)
 {
-  GtkEntry *entry = GTK_ENTRY (object);
+  GtkEntry *entry = GTK_ENTRY (widget);
 
   entry->current_pos = entry->selection_bound = 0;
   _gtk_entry_reset_im_context (entry);
@@ -2443,7 +2442,7 @@ gtk_entry_destroy (GtkObject *object)
       entry->recompute_idle = 0;
     }
 
-  GTK_OBJECT_CLASS (gtk_entry_parent_class)->destroy (object);
+  GTK_WIDGET_CLASS (gtk_entry_parent_class)->destroy (widget);
 }
 
 static void
@@ -2646,7 +2645,6 @@ realize_icon_info (GtkWidget            *widget,
   attributes.window_type = GDK_WINDOW_CHILD;
   attributes.wclass = GDK_INPUT_OUTPUT;
   attributes.visual = gtk_widget_get_visual (widget);
-  attributes.colormap = gtk_widget_get_colormap (widget);
   attributes.event_mask = gtk_widget_get_events (widget);
   attributes.event_mask |= (GDK_EXPOSURE_MASK |
                                 GDK_BUTTON_PRESS_MASK |
@@ -2657,7 +2655,7 @@ realize_icon_info (GtkWidget            *widget,
                                 GDK_POINTER_MOTION_MASK |
                                 GDK_ENTER_NOTIFY_MASK |
                             GDK_LEAVE_NOTIFY_MASK);
-  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
 
   icon_info->window = gdk_window_new (gtk_widget_get_window (widget),
                                       &attributes,
@@ -2750,7 +2748,6 @@ gtk_entry_realize (GtkWidget *widget)
 
   attributes.wclass = GDK_INPUT_OUTPUT;
   attributes.visual = gtk_widget_get_visual (widget);
-  attributes.colormap = gtk_widget_get_colormap (widget);
   attributes.event_mask = gtk_widget_get_events (widget);
   attributes.event_mask |= (GDK_EXPOSURE_MASK |
                            GDK_BUTTON_PRESS_MASK |
@@ -2761,7 +2758,7 @@ gtk_entry_realize (GtkWidget *widget)
                            GDK_POINTER_MOTION_MASK |
                             GDK_ENTER_NOTIFY_MASK |
                            GDK_LEAVE_NOTIFY_MASK);
-  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
 
   window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
   gtk_widget_set_window (widget, window);
@@ -2985,13 +2982,12 @@ gtk_entry_get_text_area_size (GtkEntry *entry,
   gint frame_height;
   gint xborder, yborder;
 
-  gtk_size_request_get_size (GTK_SIZE_REQUEST (widget),
-                             &requisition, NULL);
+  gtk_widget_get_preferred_size (widget, &requisition, NULL);
   gtk_widget_get_allocation (widget, &allocation);
   _gtk_entry_get_borders (entry, &xborder, &yborder);
 
   if (gtk_widget_get_realized (widget))
-    gdk_drawable_get_size (gtk_widget_get_window (widget), NULL, &frame_height);
+    frame_height = gdk_window_get_height (gtk_widget_get_window (widget));
   else
     frame_height = requisition.height;
 
@@ -3040,8 +3036,7 @@ get_widget_window_size (GtkEntry *entry,
   GtkRequisition requisition;
   GtkWidget *widget = GTK_WIDGET (entry);
 
-  gtk_size_request_get_size (GTK_SIZE_REQUEST (widget),
-                             &requisition, NULL);
+  gtk_widget_get_preferred_size (widget, &requisition, NULL);
   gtk_widget_get_allocation (widget, &allocation);
 
   if (x)
@@ -3194,6 +3189,7 @@ should_prelight (GtkEntry             *entry,
 
 static void
 draw_icon (GtkWidget            *widget,
+           cairo_t              *cr,
            GtkEntryIconPosition  icon_pos)
 {
   GtkEntry *entry = GTK_ENTRY (widget);
@@ -3201,7 +3197,6 @@ draw_icon (GtkWidget            *widget,
   EntryIconInfo *icon_info = priv->icons[icon_pos];
   GdkPixbuf *pixbuf;
   gint x, y, width, height;
-  cairo_t *cr;
 
   if (!icon_info)
     return;
@@ -3211,7 +3206,8 @@ draw_icon (GtkWidget            *widget,
   if (icon_info->pixbuf == NULL)
     return;
 
-  gdk_drawable_get_size (icon_info->window, &width, &height);
+  width = gdk_window_get_width (icon_info->window);
+  height = gdk_window_get_height (icon_info->window);
 
   /* size_allocate hasn't been called yet. These are the default values.
    */
@@ -3259,10 +3255,8 @@ draw_icon (GtkWidget            *widget,
       pixbuf = temp_pixbuf;
     }
 
-  cr = gdk_cairo_create (icon_info->window);
   gdk_cairo_set_source_pixbuf (cr, pixbuf, x, y);
   cairo_paint (cr);
-  cairo_destroy (cr);
 
   g_object_unref (pixbuf);
 }
@@ -3270,7 +3264,7 @@ draw_icon (GtkWidget            *widget,
 
 static void
 gtk_entry_draw_frame (GtkWidget      *widget,
-                      GdkEventExpose *event)
+                      cairo_t        *cr)
 {
   GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (widget);
   GtkStyle *style;
@@ -3280,10 +3274,12 @@ gtk_entry_draw_frame (GtkWidget      *widget,
 
   window = gtk_widget_get_window (widget);
 
-  gdk_drawable_get_size (window, &width, &height);
+  width = gdk_window_get_width (window);
+  height = gdk_window_get_height (window);
 
   /* Fix a problem with some themes which assume that entry->text_area's
-   * width equals widget->window's width */
+   * width equals widget->window's width
+   * http://bugzilla.gnome.org/show_bug.cgi?id=466000 */
   if (GTK_IS_SPIN_BUTTON (widget))
     {
       gint xborder, yborder;
@@ -3307,12 +3303,12 @@ gtk_entry_draw_frame (GtkWidget      *widget,
   state = gtk_widget_has_focus (widget) ?
     GTK_STATE_ACTIVE : gtk_widget_get_state (widget);
 
-  gtk_paint_shadow (style, window,
+  gtk_paint_shadow (style, cr,
                     state, priv->shadow_type,
-                    &event->area, widget, "entry", x, y, width, height);
+                    widget, "entry", x, y, width, height);
 
 
-  gtk_entry_draw_progress (widget, event);
+  gtk_entry_draw_progress (widget, cr, window);
 
   if (gtk_widget_has_focus (widget) && !priv->interior_focus)
     {
@@ -3321,9 +3317,9 @@ gtk_entry_draw_frame (GtkWidget      *widget,
       width += 2 * priv->focus_width;
       height += 2 * priv->focus_width;
 
-      gtk_paint_focus (style, window,
+      gtk_paint_focus (style, cr,
                        gtk_widget_get_state (widget),
-                      &event->area, widget, "entry",
+                      widget, "entry",
                       0, 0, width, height);
     }
 }
@@ -3368,10 +3364,10 @@ get_progress_area (GtkWidget *widget,
   *x = progress_border.left;
   *y = progress_border.top;
 
-  gdk_drawable_get_size (gtk_widget_get_window (widget), width, height);
-
-  *width -= progress_border.left + progress_border.right;
-  *height -= progress_border.top + progress_border.bottom;
+  *width = gdk_window_get_width (gtk_widget_get_window (widget))
+           - progress_border.left - progress_border.right;
+  *height = gdk_window_get_height (gtk_widget_get_window (widget))
+            - progress_border.top - progress_border.bottom;
 
   if (gtk_widget_has_focus (widget) && !private->interior_focus)
     {
@@ -3414,7 +3410,8 @@ get_progress_area (GtkWidget *widget,
 
 static void
 gtk_entry_draw_progress (GtkWidget      *widget,
-                         GdkEventExpose *event)
+                         cairo_t        *cr,
+                         GdkWindow      *window)
 {
   gint x, y, width, height;
   GtkStateType state;
@@ -3424,11 +3421,11 @@ gtk_entry_draw_progress (GtkWidget      *widget,
   if ((width <= 0) || (height <= 0))
     return;
 
-  if (event->window != gtk_widget_get_window (widget))
+  if (window != gtk_widget_get_window (widget))
     {
       gint pos_x, pos_y;
 
-      gdk_window_get_position (event->window, &pos_x, &pos_y);
+      gdk_window_get_position (window, &pos_x, &pos_y);
 
       x -= pos_x;
       y -= pos_y;
@@ -3438,79 +3435,83 @@ gtk_entry_draw_progress (GtkWidget      *widget,
   if (!gtk_widget_get_sensitive (widget))
     state = GTK_STATE_INSENSITIVE;
 
-  gtk_paint_box (gtk_widget_get_style (widget), event->window,
+  gtk_paint_box (gtk_widget_get_style (widget), cr,
                  state, GTK_SHADOW_OUT,
-                 &event->area, widget, "entry-progress",
+                 widget, "entry-progress",
                  x, y,
                  width, height);
 }
 
 static gint
-gtk_entry_expose (GtkWidget      *widget,
-                 GdkEventExpose *event)
+gtk_entry_draw (GtkWidget *widget,
+               cairo_t   *cr)
 {
   GtkEntry *entry = GTK_ENTRY (widget);
   GtkStyle *style;
   GtkStateType state;
   GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry);
+  int i;
 
   style = gtk_widget_get_style (widget);
 
   state = gtk_widget_has_focus (widget) ?
     GTK_STATE_ACTIVE : gtk_widget_get_state (widget);
 
-  if (gtk_widget_get_window (widget) == event->window)
-    {
-      gtk_entry_draw_frame (widget, event);
-    }
-  else if (entry->text_area == event->window)
+  if (gtk_cairo_should_draw_window (cr, gtk_widget_get_window (widget)))
+    gtk_entry_draw_frame (widget, cr);
+
+  if (gtk_cairo_should_draw_window (cr, entry->text_area))
     {
-      gint width, height;
+      cairo_save (cr);
 
-      gdk_drawable_get_size (entry->text_area, &width, &height);
+      gtk_cairo_transform_to_window (cr, widget, entry->text_area);
 
-      gtk_paint_flat_box (style, entry->text_area,
+      gtk_paint_flat_box (style, cr,
                          state, GTK_SHADOW_NONE,
-                         &event->area, widget, "entry_bg",
-                         0, 0, width, height);
+                         widget, "entry_bg",
+                         0, 0,
+                          gdk_window_get_width (entry->text_area),
+                          gdk_window_get_height (entry->text_area));
 
-      gtk_entry_draw_progress (widget, event);
+      gtk_entry_draw_progress (widget, cr, entry->text_area);
 
       if (entry->dnd_position != -1)
-       gtk_entry_draw_cursor (GTK_ENTRY (widget), CURSOR_DND);
+       gtk_entry_draw_cursor (GTK_ENTRY (widget), cr, CURSOR_DND);
       
-      gtk_entry_draw_text (GTK_ENTRY (widget));
+      gtk_entry_draw_text (GTK_ENTRY (widget), cr);
 
       /* When no text is being displayed at all, don't show the cursor */
       if (gtk_entry_get_display_mode (entry) != DISPLAY_BLANK &&
          gtk_widget_has_focus (widget) &&
          entry->selection_bound == entry->current_pos && entry->cursor_visible) 
-        gtk_entry_draw_cursor (GTK_ENTRY (widget), CURSOR_STANDARD);
+        gtk_entry_draw_cursor (GTK_ENTRY (widget), cr, CURSOR_STANDARD);
+
+      cairo_restore (cr);
     }
-  else
+
+  for (i = 0; i < MAX_ICONS; i++)
     {
-      int i;
+      EntryIconInfo *icon_info = priv->icons[i];
 
-      for (i = 0; i < MAX_ICONS; i++)
+      if (icon_info != NULL && gtk_cairo_should_draw_window (cr, icon_info->window))
         {
-          EntryIconInfo *icon_info = priv->icons[i];
+          cairo_save (cr);
 
-          if (icon_info != NULL && event->window == icon_info->window)
-            {
-              gint width, height;
+          gtk_cairo_transform_to_window (cr, widget, icon_info->window);
 
-              gdk_drawable_get_size (icon_info->window, &width, &height);
+          gtk_paint_flat_box (style, cr,
+                              state, GTK_SHADOW_NONE,
+                              widget, "entry_bg",
+                              0, 0,
+                              gdk_window_get_width (icon_info->window),
+                              gdk_window_get_height (icon_info->window));
 
-              gtk_paint_flat_box (style, icon_info->window,
-                                  state, GTK_SHADOW_NONE,
-                                  NULL, widget, "entry_bg",
-                                  0, 0, width, height);
+          gtk_entry_draw_progress (widget, cr, icon_info->window);
+          draw_icon (widget, cr, i);
 
-              gtk_entry_draw_progress (widget, event);
-              draw_icon (widget, i);
+          cairo_restore (cr);
 
-              break;
-            }
+          break;
         }
     }
 
@@ -3844,15 +3845,12 @@ gtk_entry_button_release (GtkWidget      *widget,
 
       if (event->window == icon_info->window)
         {
-          gint width, height;
-
-          gdk_drawable_get_size (icon_info->window, &width, &height);
-
           icon_info->pressed = FALSE;
 
           if (should_prelight (entry, i) &&
               event->x >= 0 && event->y >= 0 &&
-              event->x < width && event->y < height)
+              event->x < gdk_window_get_width (icon_info->window) &&
+              event->y < gdk_window_get_height (icon_info->window))
             {
               icon_info->prelight = TRUE;
               gtk_widget_queue_draw (widget);
@@ -3967,27 +3965,23 @@ gtk_entry_motion_notify (GtkWidget      *widget,
           GtkTargetList  *target_list = gtk_target_list_new (NULL, 0);
           guint actions = entry->editable ? GDK_ACTION_COPY | GDK_ACTION_MOVE : GDK_ACTION_COPY;
           gchar *text = NULL;
-          GdkPixmap *pixmap = NULL;
+          cairo_surface_t *surface;
 
           gtk_target_list_add_text_targets (target_list, 0);
 
           text = _gtk_entry_get_selected_text (entry);
-          pixmap = _gtk_text_util_create_drag_icon (widget, text, -1);
+          surface = _gtk_text_util_create_drag_icon (widget, text, -1);
 
           context = gtk_drag_begin (widget, target_list, actions,
                                     entry->button, (GdkEvent *)event);
           
-          if (pixmap)
-            gtk_drag_set_icon_pixmap (context,
-                                      gdk_drawable_get_colormap (pixmap),
-                                      pixmap,
-                                      NULL,
-                                      -2, -2);
+          if (surface)
+            gtk_drag_set_icon_surface (context, surface);
           else
             gtk_drag_set_icon_default (context);
           
-          if (pixmap)
-            g_object_unref (pixmap);
+          if (surface)
+            cairo_surface_destroy (surface);
           g_free (text);
 
           entry->in_drag = FALSE;
@@ -3998,12 +3992,9 @@ gtk_entry_motion_notify (GtkWidget      *widget,
     }
   else
     {
-      gint height;
-      gdk_drawable_get_size (entry->text_area, NULL, &height);
-
       if (event->y < 0)
        tmp_pos = 0;
-      else if (event->y >= height)
+      else if (event->y >= gdk_window_get_height (entry->text_area))
        tmp_pos = gtk_entry_buffer_get_length (get_buffer (entry));
       else
        tmp_pos = gtk_entry_find_position (entry, event->x + entry->scroll_offset);
@@ -4059,7 +4050,7 @@ set_invisible_cursor (GdkWindow *window)
   GdkDisplay *display;
   GdkCursor *cursor;
 
-  display = gdk_drawable_get_display (window);
+  display = gdk_window_get_display (window);
   cursor = gdk_cursor_new_for_display (display, GDK_BLANK_CURSOR);
 
   gdk_window_set_cursor (window, cursor);
@@ -5587,80 +5578,79 @@ draw_text_with_color (GtkEntry *entry, cairo_t *cr, GdkColor *default_color)
 }
 
 static void
-gtk_entry_draw_text (GtkEntry *entry)
+gtk_entry_draw_text (GtkEntry *entry,
+                     cairo_t  *cr)
 {
   GtkWidget *widget = GTK_WIDGET (entry);
-  cairo_t *cr;
+  GtkStateType state;
+  GtkStyle *style;
+  GdkColor text_color, bar_text_color;
+  gint pos_x, pos_y;
+  gint width, height;
+  gint progress_x, progress_y, progress_width, progress_height;
+
 
   /* Nothing to display at all */
   if (gtk_entry_get_display_mode (entry) == DISPLAY_BLANK)
     return;
   
-  if (gtk_widget_is_drawable (widget))
-    {
-      GtkStateType state;
-      GtkStyle *style;
-      GdkColor text_color, bar_text_color;
-      gint pos_x, pos_y;
-      gint width, height;
-      gint progress_x, progress_y, progress_width, progress_height;
-
-      state = GTK_STATE_SELECTED;
-      if (!gtk_widget_get_sensitive (widget))
-        state = GTK_STATE_INSENSITIVE;
-      style = gtk_widget_get_style (widget);
-      text_color = style->text[gtk_widget_get_state (widget)];
-      bar_text_color = style->fg[state];
+  state = GTK_STATE_SELECTED;
+  if (!gtk_widget_get_sensitive (widget))
+    state = GTK_STATE_INSENSITIVE;
+  style = gtk_widget_get_style (widget);
+  text_color = style->text[gtk_widget_get_state (widget)];
+  bar_text_color = style->fg[state];
 
-      get_progress_area (widget,
-                         &progress_x, &progress_y,
-                         &progress_width, &progress_height);
+  get_progress_area (widget,
+                     &progress_x, &progress_y,
+                     &progress_width, &progress_height);
 
-      cr = gdk_cairo_create (entry->text_area);
+  /* If the color is the same, or the progress area has a zero
+   * size, then we only need to draw once. */
+  if ((text_color.pixel == bar_text_color.pixel) ||
+      ((progress_width == 0) || (progress_height == 0)))
+    {
+      draw_text_with_color (entry, cr, &text_color);
+    }
+  else
+    {
+      width = gdk_window_get_width (entry->text_area);
+      height = gdk_window_get_height (entry->text_area);
 
-      /* If the color is the same, or the progress area has a zero
-       * size, then we only need to draw once. */
-      if ((text_color.pixel == bar_text_color.pixel) ||
-          ((progress_width == 0) || (progress_height == 0)))
-        {
-          draw_text_with_color (entry, cr, &text_color);
-        }
-      else
-        {
-          gdk_drawable_get_size (entry->text_area, &width, &height);
+      cairo_save (cr);
 
-          cairo_rectangle (cr, 0, 0, width, height);
-          cairo_clip (cr);
-          cairo_save (cr);
+      cairo_rectangle (cr, 0, 0, width, height);
+      cairo_clip (cr);
+      cairo_save (cr);
 
-          cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
-          cairo_rectangle (cr, 0, 0, width, height);
+      cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
+      cairo_rectangle (cr, 0, 0, width, height);
 
-          gdk_window_get_position (entry->text_area, &pos_x, &pos_y);
-          progress_x -= pos_x;
-          progress_y -= pos_y;
+      gdk_window_get_position (entry->text_area, &pos_x, &pos_y);
+      progress_x -= pos_x;
+      progress_y -= pos_y;
 
-          cairo_rectangle (cr, progress_x, progress_y,
-                           progress_width, progress_height);
-          cairo_clip (cr);
-          cairo_set_fill_rule (cr, CAIRO_FILL_RULE_WINDING);
-      
-          draw_text_with_color (entry, cr, &text_color);
-          cairo_restore (cr);
+      cairo_rectangle (cr, progress_x, progress_y,
+                       progress_width, progress_height);
+      cairo_clip (cr);
+      cairo_set_fill_rule (cr, CAIRO_FILL_RULE_WINDING);
+  
+      draw_text_with_color (entry, cr, &text_color);
+      cairo_restore (cr);
 
-          cairo_rectangle (cr, progress_x, progress_y,
-                           progress_width, progress_height);
-          cairo_clip (cr);
+      cairo_rectangle (cr, progress_x, progress_y,
+                       progress_width, progress_height);
+      cairo_clip (cr);
 
-          draw_text_with_color (entry, cr, &bar_text_color);
-        }
+      draw_text_with_color (entry, cr, &bar_text_color);
 
-      cairo_destroy (cr);
+      cairo_restore (cr);
     }
 }
 
 static void
 draw_insertion_cursor (GtkEntry      *entry,
+                       cairo_t       *cr,
                       GdkRectangle  *cursor_location,
                       gboolean       is_primary,
                       PangoDirection direction,
@@ -5674,131 +5664,127 @@ draw_insertion_cursor (GtkEntry      *entry,
   else
     text_dir = GTK_TEXT_DIR_RTL;
 
-  gtk_draw_insertion_cursor (widget, entry->text_area, NULL,
+  gtk_draw_insertion_cursor (widget, cr,
                             cursor_location,
                             is_primary, text_dir, draw_arrow);
 }
 
 static void
 gtk_entry_draw_cursor (GtkEntry  *entry,
+                       cairo_t   *cr,
                       CursorType type)
 {
   GtkWidget *widget = GTK_WIDGET (entry);
   GdkKeymap *keymap = gdk_keymap_get_for_display (gtk_widget_get_display (GTK_WIDGET (entry)));
   PangoDirection keymap_direction = gdk_keymap_get_direction (keymap);
-  
-  if (gtk_widget_is_drawable (widget))
-    {
-      GdkRectangle cursor_location;
-      gboolean split_cursor;
-      PangoRectangle cursor_rect;
-      GtkBorder inner_border;
-      gint xoffset;
-      gint text_area_height;
-      gint cursor_index;
-      gboolean block;
-      gboolean block_at_line_end;
-      PangoLayout *layout;
-      const char *text;
-
-      _gtk_entry_effective_inner_border (entry, &inner_border);
-
-      xoffset = inner_border.left - entry->scroll_offset;
+  GdkRectangle cursor_location;
+  gboolean split_cursor;
+  PangoRectangle cursor_rect;
+  GtkBorder inner_border;
+  gint xoffset;
+  gint text_area_height;
+  gint cursor_index;
+  gboolean block;
+  gboolean block_at_line_end;
+  PangoLayout *layout;
+  const char *text;
 
-      gdk_drawable_get_size (entry->text_area, NULL, &text_area_height);
+  _gtk_entry_effective_inner_border (entry, &inner_border);
 
-      layout = gtk_entry_ensure_layout (entry, TRUE);
-      text = pango_layout_get_text (layout);
-      cursor_index = g_utf8_offset_to_pointer (text, entry->current_pos + entry->preedit_cursor) - text;
-      if (!entry->overwrite_mode)
-        block = FALSE;
-      else
-        block = _gtk_text_util_get_block_cursor_location (layout,
-                                                          cursor_index, &cursor_rect, &block_at_line_end);
+  xoffset = inner_border.left - entry->scroll_offset;
 
-      if (!block)
-        {
-          gint strong_x, weak_x;
-          PangoDirection dir1 = PANGO_DIRECTION_NEUTRAL;
-          PangoDirection dir2 = PANGO_DIRECTION_NEUTRAL;
-          gint x1 = 0;
-          gint x2 = 0;
+  text_area_height = gdk_window_get_height (entry->text_area);
 
-          gtk_entry_get_cursor_locations (entry, type, &strong_x, &weak_x);
+  layout = gtk_entry_ensure_layout (entry, TRUE);
+  text = pango_layout_get_text (layout);
+  cursor_index = g_utf8_offset_to_pointer (text, entry->current_pos + entry->preedit_cursor) - text;
+  if (!entry->overwrite_mode)
+    block = FALSE;
+  else
+    block = _gtk_text_util_get_block_cursor_location (layout,
+                                                      cursor_index, &cursor_rect, &block_at_line_end);
 
-          g_object_get (gtk_widget_get_settings (widget),
-                        "gtk-split-cursor", &split_cursor,
-                        NULL);
+  if (!block)
+    {
+      gint strong_x, weak_x;
+      PangoDirection dir1 = PANGO_DIRECTION_NEUTRAL;
+      PangoDirection dir2 = PANGO_DIRECTION_NEUTRAL;
+      gint x1 = 0;
+      gint x2 = 0;
 
-          dir1 = entry->resolved_dir;
-      
-          if (split_cursor)
-            {
-              x1 = strong_x;
+      gtk_entry_get_cursor_locations (entry, type, &strong_x, &weak_x);
 
-              if (weak_x != strong_x)
-                {
-                  dir2 = (entry->resolved_dir == PANGO_DIRECTION_LTR) ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR;
-                  x2 = weak_x;
-                }
-            }
-          else
-            {
-              if (keymap_direction == entry->resolved_dir)
-                x1 = strong_x;
-              else
-                x1 = weak_x;
-            }
+      g_object_get (gtk_widget_get_settings (widget),
+                    "gtk-split-cursor", &split_cursor,
+                    NULL);
 
-          cursor_location.x = xoffset + x1;
-          cursor_location.y = inner_border.top;
-          cursor_location.width = 0;
-          cursor_location.height = text_area_height - inner_border.top - inner_border.bottom;
+      dir1 = entry->resolved_dir;
+  
+      if (split_cursor)
+        {
+          x1 = strong_x;
 
-          draw_insertion_cursor (entry,
-                                 &cursor_location, TRUE, dir1,
-                                 dir2 != PANGO_DIRECTION_NEUTRAL);
-      
-          if (dir2 != PANGO_DIRECTION_NEUTRAL)
+          if (weak_x != strong_x)
             {
-              cursor_location.x = xoffset + x2;
-              draw_insertion_cursor (entry,
-                                     &cursor_location, FALSE, dir2,
-                                     TRUE);
+              dir2 = (entry->resolved_dir == PANGO_DIRECTION_LTR) ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR;
+              x2 = weak_x;
             }
         }
-      else /* overwrite_mode */
+      else
         {
-          GdkColor cursor_color;
-          GdkRectangle rect;
-          cairo_t *cr;
-          gint x, y;
+          if (keymap_direction == entry->resolved_dir)
+            x1 = strong_x;
+          else
+            x1 = weak_x;
+        }
 
-          get_layout_position (entry, &x, &y);
+      cursor_location.x = xoffset + x1;
+      cursor_location.y = inner_border.top;
+      cursor_location.width = 0;
+      cursor_location.height = text_area_height - inner_border.top - inner_border.bottom;
 
-          rect.x = PANGO_PIXELS (cursor_rect.x) + x;
-          rect.y = PANGO_PIXELS (cursor_rect.y) + y;
-          rect.width = PANGO_PIXELS (cursor_rect.width);
-          rect.height = PANGO_PIXELS (cursor_rect.height);
+      draw_insertion_cursor (entry, cr,
+                             &cursor_location, TRUE, dir1,
+                             dir2 != PANGO_DIRECTION_NEUTRAL);
+  
+      if (dir2 != PANGO_DIRECTION_NEUTRAL)
+        {
+          cursor_location.x = xoffset + x2;
+          draw_insertion_cursor (entry, cr,
+                                 &cursor_location, FALSE, dir2,
+                                 TRUE);
+        }
+    }
+  else /* overwrite_mode */
+    {
+      GdkColor cursor_color;
+      GdkRectangle rect;
+      gint x, y;
 
-          cr = gdk_cairo_create (entry->text_area);
+      cairo_save (cr);
 
-          _gtk_widget_get_cursor_color (widget, &cursor_color);
-          gdk_cairo_set_source_color (cr, &cursor_color);
-          gdk_cairo_rectangle (cr, &rect);
-          cairo_fill (cr);
+      get_layout_position (entry, &x, &y);
 
-          if (!block_at_line_end)
-            {
-              gdk_cairo_rectangle (cr, &rect);
-              cairo_clip (cr);
-              cairo_move_to (cr, x, y);
-              gdk_cairo_set_source_color (cr, &gtk_widget_get_style (widget)->base[gtk_widget_get_state (widget)]);
-              pango_cairo_show_layout (cr, layout);
-            }
+      rect.x = PANGO_PIXELS (cursor_rect.x) + x;
+      rect.y = PANGO_PIXELS (cursor_rect.y) + y;
+      rect.width = PANGO_PIXELS (cursor_rect.width);
+      rect.height = PANGO_PIXELS (cursor_rect.height);
+
+      _gtk_widget_get_cursor_color (widget, &cursor_color);
+      gdk_cairo_set_source_color (cr, &cursor_color);
+      gdk_cairo_rectangle (cr, &rect);
+      cairo_fill (cr);
 
-          cairo_destroy (cr);
+      if (!block_at_line_end)
+        {
+          gdk_cairo_rectangle (cr, &rect);
+          cairo_clip (cr);
+          cairo_move_to (cr, x, y);
+          gdk_cairo_set_source_color (cr, &gtk_widget_get_style (widget)->base[gtk_widget_get_state (widget)]);
+          pango_cairo_show_layout (cr, layout);
         }
+
+      cairo_restore (cr);
     }
 }
 
@@ -5977,7 +5963,7 @@ gtk_entry_adjust_scroll (GtkEntry *entry)
 
   _gtk_entry_effective_inner_border (entry, &inner_border);
 
-  gdk_drawable_get_size (entry->text_area, &text_area_width, NULL);
+  text_area_width = gdk_window_get_width (entry->text_area);
   text_area_width -= inner_border.left + inner_border.right;
   if (text_area_width < 0)
     text_area_width = 0;
@@ -6747,7 +6733,7 @@ gtk_entry_set_buffer (GtkEntry       *entry,
  * @entry: a #GtkEntry
  *
  * Returns the #GdkWindow which contains the text. This function is
- * useful when drawing something to the entry in an expose-event
+ * useful when drawing something to the entry in a draw
  * callback because it enables the callback to distinguish between
  * the text window and entry's icon windows.
  *
@@ -8177,7 +8163,7 @@ gtk_entry_get_current_icon_drag_source (GtkEntry *entry)
  *
  * Returns the #GdkWindow which contains the entry's icon at
  * @icon_pos. This function is useful when drawing something to the
- * entry in an expose-event callback because it enables the callback
+ * entry in a draw callback because it enables the callback
  * to distinguish between the text window and entry's icon windows.
  *
  * See also gtk_entry_get_text_window().
@@ -8503,9 +8489,9 @@ popup_position_func (GtkMenu   *menu,
   gtk_menu_set_monitor (menu, monitor_num);
 
   gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
-  gtk_size_request_get_size (GTK_SIZE_REQUEST (entry->popup_menu),
-                             &menu_req, NULL);
-  gdk_drawable_get_size (entry->text_area, NULL, &height);
+  gtk_widget_get_preferred_size (entry->popup_menu,
+                                 &menu_req, NULL);
+  height = gdk_window_get_height (entry->text_area);
   gtk_entry_get_cursor_locations (entry, CURSOR_STANDARD, &strong_x, NULL);
   _gtk_entry_effective_inner_border (entry, &inner_border);