Package: google-gadgets
Version: 0.11.1-1.1
Severity: normal
Tags: patch
User: [email protected]
Usertags: origin-ubuntu lucid ubuntu-patch

In Ubuntu, we've applied the attached patch to achieve the following:

  * debian/patches/14_svn_1264_gtk_events.patch: Patch from upstream SVN to
    fix events using gtk 2.18 or higher. (Upstream bug #335)

We thought you might be interested in doing the same. 


-- System Information:
Debian Release: squeeze/sid
  APT prefers karmic-updates
  APT policy: (500, 'karmic-updates'), (500, 'karmic-security'), (500, 'karmic')
Architecture: i386 (i686)

Kernel: Linux 2.6.31-17-generic (SMP w/2 CPU cores)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
--- google-gadgets-0.11.1/debian/patches/series
+++ google-gadgets-0.11.1/debian/patches/series
@@ -3,0 +4,2 @@
+14_svn_1264_gtk_events.patch
only in patch2:
unchanged:
--- google-gadgets-0.11.1.orig/debian/patches/14_svn_1264_gtk_events.patch
+++ google-gadgets-0.11.1/debian/patches/14_svn_1264_gtk_events.patch
@@ -0,0 +1,755 @@
+Description: Fix expose events with GTK+ >= 2.18
+Bug: http://code.google.com/p/google-gadgets-for-linux/issues/detail?id=335
+Origin: http://code.google.com/p/google-gadgets-for-linux/source/detail?r=1264
+
+Index: google-gadgets-0.11.1/ggadget/gtk/view_widget_binder.cc
+===================================================================
+--- google-gadgets-0.11.1.orig/ggadget/gtk/view_widget_binder.cc	2009-06-07 22:45:35.000000000 -0400
++++ google-gadgets-0.11.1/ggadget/gtk/view_widget_binder.cc	2010-01-21 09:57:46.000000000 -0500
+@@ -58,6 +58,9 @@
+ // Update input shape mask once per second.
+ static const uint64_t kUpdateMaskInterval = 1000;
+ 
++// Minimal interval between self draws.
++static const unsigned int kSelfDrawInterval = 40;
++
+ class ViewWidgetBinder::Impl : public SmallObject<> {
+  public:
+   Impl(ViewInterface *view,
+@@ -69,6 +72,8 @@
+ #if GTK_CHECK_VERSION(2,10,0)
+       input_shape_mask_(NULL),
+       last_mask_time_(0),
++      should_update_input_shape_mask_(false),
++      enable_input_shape_mask_(false),
+ #endif
+       handlers_(new gulong[kEventHandlersNum]),
+       current_drag_event_(NULL),
+@@ -76,7 +81,6 @@
+       dbl_click_(false),
+       composited_(false),
+       no_background_(no_background),
+-      enable_input_shape_mask_(false),
+       focused_(false),
+       button_pressed_(false),
+ #ifdef GRAB_POINTER_EXPLICITLY
+@@ -91,7 +95,11 @@
+       mouse_down_y_(-1),
+       mouse_down_hittest_(ViewInterface::HT_CLIENT),
+       last_width_(0),
+-      last_height_(0) {
++      last_height_(0),
++      self_draw_(false),
++      self_draw_timer_(0),
++      last_self_draw_time_(0),
++      sys_clip_region_(NULL) {
+     ASSERT(view);
+     ASSERT(host);
+     ASSERT(GTK_IS_WIDGET(widget));
+@@ -145,6 +153,16 @@
+   ~Impl() {
+     view_ = NULL;
+ 
++    if (self_draw_timer_) {
++      g_source_remove(self_draw_timer_);
++      self_draw_timer_ = 0;
++    }
++
++    if (sys_clip_region_) {
++      gdk_region_destroy(sys_clip_region_);
++      sys_clip_region_ = NULL;
++    }
++
+     for (size_t i = 0; i < kEventHandlersNum; ++i) {
+       if (handlers_[i] > 0)
+         g_signal_handler_disconnect(G_OBJECT(widget_), handlers_[i]);
+@@ -185,6 +203,148 @@
+     }
+   }
+ 
++  GdkRegion *CreateExposeRegionFromViewClipRegion() {
++    GdkRegion *region = gdk_region_new();
++    const ClipRegion *view_region = view_->GetClipRegion();
++    size_t count = view_region->GetRectangleCount();
++    if (count) {
++      Rectangle rect;
++      GdkRectangle gdk_rect;
++      for (size_t i = 0; i < count; ++i) {
++        rect = view_region->GetRectangle(i);
++        if (zoom_ != 1.0) {
++          rect.Zoom(zoom_);
++          rect.Integerize(true);
++        }
++        gdk_rect.x = static_cast<int>(rect.x);
++        gdk_rect.y = static_cast<int>(rect.y);
++        gdk_rect.width = static_cast<int>(rect.w);
++        gdk_rect.height = static_cast<int>(rect.h);
++        gdk_region_union_with_rect(region, &gdk_rect);
++      }
++    }
++    return region;
++  }
++
++  void AddGdkRectToSystemClipRegion(GdkRectangle *rect) {
++    if (!sys_clip_region_)
++      sys_clip_region_ = gdk_region_new();
++    gdk_region_union_with_rect(sys_clip_region_, rect);
++  }
++
++  void AddGdkRegionToSystemClipRegion(GdkRegion *region) {
++    if (!sys_clip_region_)
++      sys_clip_region_ = gdk_region_new();
++    gdk_region_union(sys_clip_region_, region);
++  }
++
++  void AddExtendedWindowAreaToSystemClipRegion(int width, int height) {
++    GdkRectangle gdk_rect;
++    if (width > last_width_) {
++      gdk_rect.x = last_width_;
++      gdk_rect.y = 0;
++      gdk_rect.width = width - last_width_;
++      gdk_rect.height = height;
++      AddGdkRectToSystemClipRegion(&gdk_rect);
++    }
++    if (height > last_height_) {
++      gdk_rect.x = 0;
++      gdk_rect.y = last_height_;
++      gdk_rect.width = width;
++      gdk_rect.height = height - last_height_;
++      AddGdkRectToSystemClipRegion(&gdk_rect);
++    }
++
++    last_width_ = width;
++    last_height_ = height;
++  }
++
++  void AddGdkRectToViewClipRegion(const GdkRectangle &gdk_rect) {
++    Rectangle rect(gdk_rect.x, gdk_rect.y, gdk_rect.width, gdk_rect.height);
++    rect.Zoom(1.0 / zoom_);
++    rect.Integerize(true);
++    view_->AddRectangleToClipRegion(rect);
++  }
++
++  void AddGdkRegionToViewClipRegion(GdkRegion *region) {
++    if (!gdk_region_empty(region)) {
++      GdkRectangle *rects;
++      gint n_rects;
++      gdk_region_get_rectangles(region, &rects, &n_rects);
++      for (gint i = 0; i < n_rects; ++i) {
++        AddGdkRectToViewClipRegion(rects[i]);
++      }
++      g_free(rects);
++    }
++  }
++
++#if GTK_CHECK_VERSION(2,10,0)
++  bool ShouldUpdateInputShapeMask(int width, int height) {
++    bool update_input_shape_mask = enable_input_shape_mask_ &&
++        (GetCurrentTime() - last_mask_time_ > kUpdateMaskInterval) &&
++        no_background_ && composited_;
++
++    // We need set input shape mask if there is no background.
++    if (update_input_shape_mask) {
++      if (input_shape_mask_) {
++        gint mask_width, mask_height;
++        gdk_drawable_get_size(GDK_DRAWABLE(input_shape_mask_),
++                              &mask_width, &mask_height);
++        if (mask_width != width || mask_height != height) {
++          // input shape mask needs recreate.
++          g_object_unref(G_OBJECT(input_shape_mask_));
++          input_shape_mask_ = NULL;
++        }
++      }
++
++      if (input_shape_mask_ == NULL) {
++        GdkRectangle rect;
++        rect.x = 0;
++        rect.y = 0;
++        rect.width = width;
++        rect.height = height;
++        input_shape_mask_ = gdk_pixmap_new(NULL, width, height, 1);
++
++        // Redraw whole view.
++        AddGdkRectToSystemClipRegion(&rect);
++      }
++    }
++
++    return update_input_shape_mask;
++  }
++#endif
++
++  GdkRegion *GetInvalidateRegion() {
++    gint width, height;
++    gdk_drawable_get_size(widget_->window, &width, &height);
++    view_->Layout();
++#if GTK_CHECK_VERSION(2,10,0)
++    should_update_input_shape_mask_ = ShouldUpdateInputShapeMask(width, height);
++#endif
++    AddExtendedWindowAreaToSystemClipRegion(width, height);
++    GdkRegion *region = CreateExposeRegionFromViewClipRegion();
++    if (sys_clip_region_) {
++      AddGdkRegionToViewClipRegion(sys_clip_region_);
++      gdk_region_union(region, sys_clip_region_);
++      gdk_region_destroy(sys_clip_region_);
++      sys_clip_region_ = NULL;
++    }
++    return region;
++  }
++
++  void SelfDraw() {
++    if (!widget_->window || !gdk_window_is_visible(widget_->window))
++      return;
++
++    self_draw_ = true;
++    GdkRegion *region = GetInvalidateRegion();
++    gdk_window_invalidate_region(widget_->window, region, TRUE);
++    gdk_region_destroy(region);
++    gdk_window_process_updates(widget_->window, TRUE);
++    last_self_draw_time_ = GetCurrentTime();
++    self_draw_ = false;
++  }
++
+   static gboolean ButtonPressHandler(GtkWidget *widget, GdkEventButton *event,
+                                      gpointer user_data) {
+     Impl *impl = reinterpret_cast<Impl *>(user_data);
+@@ -364,137 +524,29 @@
+     return result != EVENT_RESULT_UNHANDLED;
+   }
+ 
+-  static GdkRegion *CreateExposeRegion(const ClipRegion *view_region,
+-                                       int width, int height,
+-                                       int last_width, int last_height,
+-                                       double zoom) {
+-    GdkRegion *region = gdk_region_new();
+-    size_t count = view_region->GetRectangleCount();
+-    GdkRectangle gdk_rect;
+-    if (count) {
+-      Rectangle rect;
+-      for (size_t i = 0; i < count; ++i) {
+-        rect = view_region->GetRectangle(i);
+-        if (zoom != 1.0) {
+-          rect.Zoom(zoom);
+-          rect.Integerize(true);
+-        }
+-        gdk_rect.x = static_cast<int>(rect.x);
+-        gdk_rect.y = static_cast<int>(rect.y);
+-        gdk_rect.width = static_cast<int>(rect.w);
+-        gdk_rect.height = static_cast<int>(rect.h);
+-        gdk_region_union_with_rect(region, &gdk_rect);
+-      }
+-    }
+-    if (width > last_width) {
+-      gdk_rect.x = last_width;
+-      gdk_rect.y = 0;
+-      gdk_rect.width = width - last_width;
+-      gdk_rect.height = height;
+-      gdk_region_union_with_rect(region, &gdk_rect);
+-    }
+-    if (height > last_height) {
+-      gdk_rect.x = 0;
+-      gdk_rect.y = last_height;
+-      gdk_rect.width = width;
+-      gdk_rect.height = height - last_height;
+-      gdk_region_union_with_rect(region, &gdk_rect);
+-    }
+-    return region;
+-  }
+-
+-  static void AddGdkRectangleToViewClipRegion(ViewInterface *view,
+-                                              const GdkRectangle &gdk_rect,
+-                                              bool zoom) {
+-    Rectangle rect(gdk_rect.x, gdk_rect.y, gdk_rect.width, gdk_rect.height);
+-    rect.Zoom(1.0 / zoom);
+-    rect.Integerize(true);
+-    view->AddRectangleToClipRegion(rect);
+-  }
+-
+-  static void AddGdkRegionToViewClipRegion(ViewInterface *view,
+-                                           GdkRegion *region,
+-                                           bool zoom) {
+-    if (!gdk_region_empty(region)) {
+-      GdkRectangle *rects;
+-      gint n_rects;
+-      gdk_region_get_rectangles(region, &rects, &n_rects);
+-      for (gint i = 0; i < n_rects; ++i) {
+-        AddGdkRectangleToViewClipRegion(view, rects[i], zoom);
+-      }
+-      g_free(rects);
+-    }
+-  }
+-
+   static gboolean ExposeHandler(GtkWidget *widget, GdkEventExpose *event,
+                                 gpointer user_data) {
+     Impl *impl = reinterpret_cast<Impl *>(user_data);
+-    gint last_width = impl->last_width_;
+-    gint last_height = impl->last_height_;
+-    gint width, height;
+-    gdk_drawable_get_size(widget->window, &width, &height);
+-
+-    impl->last_width_ = width;
+-    impl->last_height_ = height;
+-
+-    impl->view_->Layout();
+-
+-    GdkRegion *region = CreateExposeRegion(
+-        impl->view_->GetClipRegion(), width, height,
+-        last_width, last_height, impl->zoom_);
+ 
+-    uint64_t current_time = GetCurrentTime();
+-#if GTK_CHECK_VERSION(2,10,0)
+-    bool update_input_shape_mask = impl->enable_input_shape_mask_ &&
+-        (current_time - impl->last_mask_time_ > kUpdateMaskInterval) &&
+-        impl->no_background_ && impl->composited_;
+-
+-    // We need set input shape mask if there is no background.
+-    if (update_input_shape_mask) {
+-      if (impl->input_shape_mask_) {
+-        gint mask_width, mask_height;
+-        gdk_drawable_get_size(GDK_DRAWABLE(impl->input_shape_mask_),
+-                              &mask_width, &mask_height);
+-        if (mask_width != width || mask_height != height) {
+-          // input shape mask needs recreate.
+-          g_object_unref(G_OBJECT(impl->input_shape_mask_));
+-          impl->input_shape_mask_ = NULL;
++    if (!impl->self_draw_) {
++      impl->AddGdkRegionToSystemClipRegion(event->region);
++      GdkRegion *invalidate_region = impl->GetInvalidateRegion();
++
++      // We can't update the region outside event->region, so update them in a
++      // new self draw request.
++      gdk_region_subtract(invalidate_region, event->region);
++      if (!gdk_region_empty(invalidate_region)) {
++        impl->AddGdkRegionToSystemClipRegion(invalidate_region);
++        if (!impl->self_draw_timer_) {
++          impl->self_draw_timer_ =
++              g_idle_add_full(GDK_PRIORITY_REDRAW, Impl::SelfDrawHandler,
++                              impl, NULL);
+         }
+       }
+-
+-      if (impl->input_shape_mask_ == NULL) {
+-        DLOG("View(%p): need (re)create input shape mask.", impl->view_);
+-        GdkRectangle rect;
+-        rect.x = 0;
+-        rect.y = 0;
+-        rect.width = width;
+-        rect.height = height;
+-        gdk_region_union_with_rect(region, &rect);
+-        impl->input_shape_mask_ = gdk_pixmap_new(NULL, width, height, 1);
+-
+-        // Redraw whole view.
+-        AddGdkRectangleToViewClipRegion(impl->view_, rect, impl->zoom_);
+-      }
++      gdk_region_destroy(invalidate_region);
+     }
+-#endif
+ 
+-    if (event->area.x == 0 && event->area.y == 0 &&
+-        event->area.width == 1 && event->area.height == 1) {
+-      //DLOG("View(%p): self queue draw.", impl->view_);
+-      if (gdk_region_empty(region)) {
+-        DLOG("View(%p) has pending queue draw, but doesn't have clip region.",
+-             impl->view_);
+-        gdk_region_destroy(region);
+-        // No need to redraw.
+-        return TRUE;
+-      }
+-      gdk_window_begin_paint_region(widget->window, region);
+-    } else {
+-      //DLOG("System requires redraw view(%p)", impl->view_);
+-      gdk_region_union(region, event->region);
+-      AddGdkRegionToViewClipRegion(impl->view_, event->region, impl->zoom_);
+-      gdk_window_begin_paint_region(widget->window, region);
+-    }
++    gdk_window_begin_paint_region(widget->window, event->region);
+ 
+     cairo_t *cr = gdk_cairo_create(widget->window);
+ 
+@@ -522,9 +574,9 @@
+ 
+ #if GTK_CHECK_VERSION(2,10,0)
+     // We need set input shape mask if there is no background.
+-    if (update_input_shape_mask && impl->input_shape_mask_) {
++    if (impl->should_update_input_shape_mask_ && impl->input_shape_mask_) {
+       cairo_t *mask_cr = gdk_cairo_create(impl->input_shape_mask_);
+-      gdk_cairo_region(mask_cr, region);
++      gdk_cairo_region(mask_cr, event->region);
+       cairo_clip(mask_cr);
+       cairo_set_operator(mask_cr, CAIRO_OPERATOR_CLEAR);
+       cairo_paint(mask_cr);
+@@ -534,16 +586,16 @@
+       cairo_destroy(mask_cr);
+       gdk_window_input_shape_combine_mask(widget->window,
+                                           impl->input_shape_mask_, 0, 0);
+-      impl->last_mask_time_ = current_time;
++      impl->last_mask_time_ = GetCurrentTime();
+     }
+ #endif
+ 
+     // Copy off-screen buffer to screen.
+     gdk_window_end_paint(widget->window);
+-    gdk_region_destroy(region);
+ 
+ #ifdef _DEBUG
+     ++impl->draw_count_;
++    uint64_t current_time = GetCurrentTime();
+     uint64_t duration = current_time - impl->last_fps_time_;
+     if (duration >= kFPSCountDuration) {
+       impl->last_fps_time_ = current_time;
+@@ -915,12 +967,21 @@
+     return FALSE;
+   }
+ 
++  static gboolean SelfDrawHandler(gpointer user_data) {
++    Impl *impl = reinterpret_cast<Impl *>(user_data);
++    impl->self_draw_timer_ = 0;
++    impl->SelfDraw();
++    return FALSE;
++  }
++
+   ViewInterface *view_;
+   ViewHostInterface *host_;
+   GtkWidget *widget_;
+ #if GTK_CHECK_VERSION(2,10,0)
+   GdkBitmap *input_shape_mask_;
+   uint64_t last_mask_time_;
++  bool should_update_input_shape_mask_;
++  bool enable_input_shape_mask_;
+ #endif
+   gulong *handlers_;
+   DragEvent *current_drag_event_;
+@@ -928,7 +989,6 @@
+   bool dbl_click_;
+   bool composited_;
+   bool no_background_;
+-  bool enable_input_shape_mask_;
+   bool focused_;
+   bool button_pressed_;
+ #ifdef GRAB_POINTER_EXPLICITLY
+@@ -946,6 +1006,11 @@
+   int last_width_;
+   int last_height_;
+ 
++  bool self_draw_;
++  guint self_draw_timer_;
++  uint64_t last_self_draw_time_;
++  GdkRegion *sys_clip_region_;
++
+   struct EventHandlerInfo {
+     const char *event;
+     void (*handler)(void);
+@@ -991,9 +1056,9 @@
+ }
+ 
+ void ViewWidgetBinder::EnableInputShapeMask(bool enable) {
++#if GTK_CHECK_VERSION(2,10,0)
+   if (impl_->enable_input_shape_mask_ != enable) {
+     impl_->enable_input_shape_mask_ = enable;
+-#if GTK_CHECK_VERSION(2,10,0)
+     if (impl_->widget_ && impl_->no_background_ &&
+         impl_->composited_ && !enable) {
+       if (impl_->widget_->window) {
+@@ -1004,6 +1069,7 @@
+         impl_->input_shape_mask_ = NULL;
+       }
+     }
++    gtk_widget_queue_draw(impl_->widget_);
+   }
+ #endif
+ }
+@@ -1013,5 +1079,34 @@
+   impl_ = NULL;
+ }
+ 
++void ViewWidgetBinder::QueueDraw() {
++  if (!impl_->self_draw_timer_) {
++    uint64_t current_time = GetCurrentTime();
++    if (current_time - impl_->last_self_draw_time_ >= kSelfDrawInterval) {
++      impl_->self_draw_timer_ =
++          g_idle_add_full(GDK_PRIORITY_REDRAW, Impl::SelfDrawHandler,
++                          impl_, NULL);
++    } else {
++      impl_->self_draw_timer_ =
++          g_timeout_add(kSelfDrawInterval -
++                        (current_time - impl_->last_self_draw_time_),
++                        Impl::SelfDrawHandler, impl_);
++    }
++  }
++}
++
++void ViewWidgetBinder::DrawImmediately() {
++  // Remove pending queue draw, as we don't need it anymore.
++  if (impl_->self_draw_timer_) {
++    g_source_remove(impl_->self_draw_timer_);
++    impl_->self_draw_timer_ = 0;
++  }
++  impl_->SelfDraw();
++}
++
++bool ViewWidgetBinder::DrawQueued() {
++  return impl_->self_draw_timer_ != 0;
++}
++
+ } // namespace gtk
+ } // namespace ggadget
+Index: google-gadgets-0.11.1/ggadget/gtk/single_view_host.cc
+===================================================================
+--- google-gadgets-0.11.1.orig/ggadget/gtk/single_view_host.cc	2009-05-24 22:18:33.000000000 -0400
++++ google-gadgets-0.11.1/ggadget/gtk/single_view_host.cc	2010-01-21 09:57:46.000000000 -0500
+@@ -47,12 +47,6 @@
+ static const int kStopMoveDragTimeout = 200;
+ static const char kMainViewWindowRole[] = "Google-Gadgets";
+ 
+-// Minimal interval between queue draws.
+-static const unsigned int kQueueDrawInterval = 40;
+-
+-// Maximum live duration of queue draw timer.
+-static const uint64_t kQueueDrawTimerDuration = 1000;
+-
+ class SingleViewHost::Impl {
+  public:
+   Impl(SingleViewHost *owner, ViewHostInterface::Type type,
+@@ -92,13 +86,9 @@
+       is_keep_above_(false),
+       move_dragging_(false),
+       enable_signals_(true),
+-      draw_queued_(false),
+-      draw_finished_(true),
+-      queue_draw_timer_(0),
+-      last_queue_draw_time_(0),
+       queue_resize_timer_(0),
+-      last_allocated_width_(0),
+-      last_allocated_height_(0),
++      fixed_width_from_view_(0),
++      fixed_height_from_view_(0),
+       feedback_handler_(NULL),
+       can_close_dialog_(false) {
+     ASSERT(owner);
+@@ -115,10 +105,6 @@
+     // To make sure that it won't be accessed anymore.
+     view_ = NULL;
+ 
+-    if (queue_draw_timer_)
+-      g_source_remove(queue_draw_timer_);
+-    queue_draw_timer_ = 0;
+-
+     if (queue_resize_timer_)
+       g_source_remove(queue_resize_timer_);
+     queue_resize_timer_ = 0;
+@@ -234,9 +220,6 @@
+     g_signal_connect(G_OBJECT(fixed_), "size-allocate",
+                      G_CALLBACK(FixedSizeAllocateHandler), this);
+ 
+-    g_signal_connect(G_OBJECT(widget_), "expose-event",
+-                     G_CALLBACK(ExposeHandler), this);
+-
+     g_signal_connect(G_OBJECT(fixed_), "set-focus-child",
+                      G_CALLBACK(FixedSetFocusChildHandler), this);
+ 
+@@ -275,6 +258,11 @@
+     int width = static_cast<int>(ceil(view_->GetWidth() * zoom));
+     int height = static_cast<int>(ceil(view_->GetHeight() * zoom));
+ 
++    // Stores the expected size of the GtkFixed widget, which will be used in
++    // FixedSizeAllocateHandler().
++    fixed_width_from_view_ = width;
++    fixed_height_from_view_ = height;
++
+     GtkRequisition req;
+     gtk_widget_set_size_request(widget_, width, height);
+     gtk_widget_size_request(window_, &req);
+@@ -293,8 +281,6 @@
+       win_width_ = req.width;
+       win_height_ = req.height;
+     }
+-
+-    DLOG("New window size: %d %d", req.width, req.height);
+   }
+ 
+   void QueueResize() {
+@@ -311,33 +297,13 @@
+       DLOG("SingleViewHost::EnableInputShapeMask(%s)",
+            enable ? "true" : "false");
+       binder_->EnableInputShapeMask(enable);
+-      QueueDraw();
+     }
+   }
+ 
+   void QueueDraw() {
+     ASSERT(GTK_IS_WIDGET(widget_));
+-    draw_finished_ = false;
+-    if (queue_draw_timer_) {
+-      draw_queued_ = true;
+-      return;
+-    }
+-
+-    uint64_t current_time = GetCurrentTime();
+-    if (current_time - last_queue_draw_time_ >= kQueueDrawInterval) {
+-      gtk_widget_queue_draw(widget_);
+-      draw_queued_ = false;
+-      last_queue_draw_time_ = current_time;
+-    } else {
+-      draw_queued_ = true;
+-    }
+-
+-    // Can't call view's GetCaption() here, because at this point, view might
+-    // not be fully initialized yet.
+-    DLOG("Install queue draw timer of view: %p", view_);
+-    queue_draw_timer_ = g_timeout_add(kQueueDrawInterval,
+-                                      QueueDrawTimeoutHandler,
+-                                      this);
++    if (binder_)
++      binder_->QueueDraw();
+   }
+ 
+   void SetResizable(ViewInterface::ResizableMode mode) {
+@@ -861,7 +827,7 @@
+ #endif
+       }
+ 
+-      if (impl->draw_queued_ || !impl->draw_finished_)
++      if (impl->binder_ && impl->binder_->DrawQueued())
+         return TRUE;
+ 
+       int button = ConvertGdkModifierToButton(event->state);
+@@ -881,7 +847,6 @@
+           double view_width = new_width / impl->resize_view_zoom_;
+           double view_height = new_height / impl->resize_view_zoom_;
+           if (impl->view_->OnSizing(&view_width, &view_height)) {
+-            DLOG("Resize view to: %lf %lf", view_width, view_height);
+             impl->view_->SetSize(view_width, view_height);
+             width = impl->view_->GetWidth() * impl->resize_view_zoom_;
+             height = impl->view_->GetHeight() * impl->resize_view_zoom_;
+@@ -891,7 +856,6 @@
+           double yzoom = new_height / impl->resize_view_height_;
+           double zoom = std::min(xzoom, yzoom);
+           zoom = Clamp(zoom, kMinimumZoom, kMaximumZoom);
+-          DLOG("Zoom view to: %lf", zoom);
+           impl->view_->GetGraphics()->SetZoom(zoom);
+           impl->view_->MarkRedraw();
+           width = impl->resize_view_width_ * zoom;
+@@ -910,9 +874,6 @@
+           int win_width = impl->resize_win_width_ + int(delta_x);
+           int win_height = impl->resize_win_height_ + int(delta_y);
+           gdk_window_move_resize(widget->window, x, y, win_width, win_height);
+-          gdk_window_process_updates(widget->window, TRUE);
+-          DLOG("Move resize window: x:%d, y:%d, w:%d, h:%d", x, y,
+-               win_width, win_height);
+         }
+ 
+         return TRUE;
+@@ -965,16 +926,12 @@
+                                        GtkAllocation *allocation,
+                                        gpointer user_data) {
+     Impl *impl = reinterpret_cast<Impl *>(user_data);
+-    DLOG("Size allocate(%d, %d)", allocation->width, allocation->height);
+     if (GTK_WIDGET_VISIBLE(impl->window_) &&
+         !impl->resize_width_mode_ && !impl->resize_height_mode_ &&
+         !impl->queue_resize_timer_ &&
+         allocation->width >= 1 && allocation->height >= 1 &&
+-        (impl->last_allocated_width_ != allocation->width ||
+-         impl->last_allocated_height_ != allocation->height)) {
+-      impl->last_allocated_width_ = allocation->width;
+-      impl->last_allocated_height_ = allocation->height;
+-
++        (impl->fixed_width_from_view_ != allocation->width ||
++         impl->fixed_height_from_view_ != allocation->height)) {
+       double old_width = impl->view_->GetWidth();
+       double old_height = impl->view_->GetHeight();
+       double old_zoom = impl->view_->GetGraphics()->GetZoom();
+@@ -984,7 +941,6 @@
+         double new_height = allocation->height / old_zoom;
+         if (impl->view_->OnSizing(&new_width, &new_height) &&
+             (new_width != old_width || new_height != old_height)) {
+-          DLOG("Resize view to: %lf %lf", new_width, new_height);
+           impl->view_->SetSize(new_width, new_height);
+         }
+       } else if (impl->resizable_mode_ == ViewInterface::RESIZABLE_ZOOM &&
+@@ -994,7 +950,6 @@
+         double new_zoom = Clamp(std::min(xzoom, yzoom),
+                                 kMinimumZoom, kMaximumZoom);
+         if (old_zoom != new_zoom) {
+-          DLOG("Zoom view to: %lf", new_zoom);
+           impl->view_->GetGraphics()->SetZoom(new_zoom);
+           impl->view_->MarkRedraw();
+         }
+@@ -1021,27 +976,6 @@
+     return FALSE;
+   }
+ 
+-  static gboolean QueueDrawTimeoutHandler(gpointer data) {
+-    Impl *impl = reinterpret_cast<Impl *>(data);
+-    uint64_t current_time = GetCurrentTime();
+-    if (impl->draw_queued_) {
+-      ASSERT(GTK_IS_WIDGET(impl->widget_));
+-      // Special hack to inform ViewWidgetBinder this queue draw request is
+-      // generated by us instead of system.
+-      gtk_widget_queue_draw_area(impl->widget_, 0, 0, 1, 1);
+-      impl->draw_queued_ = false;
+-      impl->last_queue_draw_time_ = current_time;
+-    }
+-
+-    if (current_time - impl->last_queue_draw_time_ > kQueueDrawTimerDuration) {
+-      DLOG("Remove queue draw timer of view: %p (%s)", impl->view_,
+-           impl->view_->GetCaption().c_str());
+-      impl->queue_draw_timer_ = 0;
+-      return FALSE;
+-    }
+-    return TRUE;
+-  }
+-
+   static gboolean QueueResizeTimeoutHandler(gpointer data) {
+     Impl *impl = reinterpret_cast<Impl *>(data);
+     impl->AdjustWindowSize();
+@@ -1049,14 +983,6 @@
+     return false;
+   }
+ 
+-  static gboolean ExposeHandler(GtkWidget *widget, GdkEventExpose *event,
+-                                gpointer data) {
+-    Impl *impl = reinterpret_cast<Impl *>(data);
+-    impl->draw_finished_ = true;
+-    // Make sure view widget binder can receive this event.
+-    return FALSE;
+-  }
+-
+   // Some elements may create gtk native widgets under this widget. When such
+   // a widget get focus, we must update the focus chain though the view
+   // hierachy.
+@@ -1136,14 +1062,9 @@
+   bool move_dragging_;
+   bool enable_signals_;
+ 
+-  bool draw_queued_;
+-  bool draw_finished_;
+-  guint queue_draw_timer_;
+-  uint64_t last_queue_draw_time_;
+-
+   guint queue_resize_timer_;
+-  gint last_allocated_width_;
+-  gint last_allocated_height_;
++  int fixed_width_from_view_;
++  int fixed_height_from_view_;
+ 
+   Slot1<bool, int> *feedback_handler_;
+   bool can_close_dialog_; // Only useful when a model dialog is running.
+Index: google-gadgets-0.11.1/ggadget/gtk/view_widget_binder.h
+===================================================================
+--- google-gadgets-0.11.1.orig/ggadget/gtk/view_widget_binder.h	2009-03-15 00:12:51.000000000 -0400
++++ google-gadgets-0.11.1/ggadget/gtk/view_widget_binder.h	2010-01-21 09:57:46.000000000 -0500
+@@ -54,6 +54,15 @@
+    */
+   void EnableInputShapeMask(bool enable);
+ 
++  /** Called by ViewHost to queue a redraw request. */
++  void QueueDraw();
++
++  /** Checks if a redraw request has been queued. */
++  bool DrawQueued();
++
++  /** Redraws the gadget immediately. */
++  void DrawImmediately();
++
+  private:
+   DISALLOW_EVIL_CONSTRUCTORS(ViewWidgetBinder);
+   class Impl;

Reply via email to