--- Begin Message ---
Package: google-gadgets
Version: 0.11.1-1.1
Severity: normal
Tags: patch
User: ubuntu-de...@lists.ubuntu.com
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;
--- End Message ---