Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 294124 | Differences between
and this patch

Collapse All | Expand All

(-)ggadget/gtk/view_widget_binder.cc (-130 / +225 lines)
Lines 58-63 Link Here
58
// Update input shape mask once per second.
58
// Update input shape mask once per second.
59
static const uint64_t kUpdateMaskInterval = 1000;
59
static const uint64_t kUpdateMaskInterval = 1000;
60
60
61
// Minimal interval between self draws.
62
static const unsigned int kSelfDrawInterval = 40;
63
61
class ViewWidgetBinder::Impl : public SmallObject<> {
64
class ViewWidgetBinder::Impl : public SmallObject<> {
62
 public:
65
 public:
63
  Impl(ViewInterface *view,
66
  Impl(ViewInterface *view,
Lines 69-74 Link Here
69
#if GTK_CHECK_VERSION(2,10,0)
72
#if GTK_CHECK_VERSION(2,10,0)
70
      input_shape_mask_(NULL),
73
      input_shape_mask_(NULL),
71
      last_mask_time_(0),
74
      last_mask_time_(0),
75
      should_update_input_shape_mask_(false),
76
      enable_input_shape_mask_(false),
72
#endif
77
#endif
73
      handlers_(new gulong[kEventHandlersNum]),
78
      handlers_(new gulong[kEventHandlersNum]),
74
      current_drag_event_(NULL),
79
      current_drag_event_(NULL),
Lines 76-82 Link Here
76
      dbl_click_(false),
81
      dbl_click_(false),
77
      composited_(false),
82
      composited_(false),
78
      no_background_(no_background),
83
      no_background_(no_background),
79
      enable_input_shape_mask_(false),
80
      focused_(false),
84
      focused_(false),
81
      button_pressed_(false),
85
      button_pressed_(false),
82
#ifdef GRAB_POINTER_EXPLICITLY
86
#ifdef GRAB_POINTER_EXPLICITLY
Lines 91-97 Link Here
91
      mouse_down_y_(-1),
95
      mouse_down_y_(-1),
92
      mouse_down_hittest_(ViewInterface::HT_CLIENT),
96
      mouse_down_hittest_(ViewInterface::HT_CLIENT),
93
      last_width_(0),
97
      last_width_(0),
94
      last_height_(0) {
98
      last_height_(0),
99
      self_draw_(false),
100
      self_draw_timer_(0),
101
      last_self_draw_time_(0),
102
      sys_clip_region_(NULL) {
95
    ASSERT(view);
103
    ASSERT(view);
96
    ASSERT(host);
104
    ASSERT(host);
97
    ASSERT(GTK_IS_WIDGET(widget));
105
    ASSERT(GTK_IS_WIDGET(widget));
Lines 145-150 Link Here
145
  ~Impl() {
153
  ~Impl() {
146
    view_ = NULL;
154
    view_ = NULL;
147
155
156
    if (self_draw_timer_) {
157
      g_source_remove(self_draw_timer_);
158
      self_draw_timer_ = 0;
159
    }
160
161
    if (sys_clip_region_) {
162
      gdk_region_destroy(sys_clip_region_);
163
      sys_clip_region_ = NULL;
164
    }
165
148
    for (size_t i = 0; i < kEventHandlersNum; ++i) {
166
    for (size_t i = 0; i < kEventHandlersNum; ++i) {
149
      if (handlers_[i] > 0)
167
      if (handlers_[i] > 0)
150
        g_signal_handler_disconnect(G_OBJECT(widget_), handlers_[i]);
168
        g_signal_handler_disconnect(G_OBJECT(widget_), handlers_[i]);
Lines 185-190 Link Here
185
    }
203
    }
186
  }
204
  }
187
205
206
  GdkRegion *CreateExposeRegionFromViewClipRegion() {
207
    GdkRegion *region = gdk_region_new();
208
    const ClipRegion *view_region = view_->GetClipRegion();
209
    size_t count = view_region->GetRectangleCount();
210
    if (count) {
211
      Rectangle rect;
212
      GdkRectangle gdk_rect;
213
      for (size_t i = 0; i < count; ++i) {
214
        rect = view_region->GetRectangle(i);
215
        if (zoom_ != 1.0) {
216
          rect.Zoom(zoom_);
217
          rect.Integerize(true);
218
        }
219
        gdk_rect.x = static_cast<int>(rect.x);
220
        gdk_rect.y = static_cast<int>(rect.y);
221
        gdk_rect.width = static_cast<int>(rect.w);
222
        gdk_rect.height = static_cast<int>(rect.h);
223
        gdk_region_union_with_rect(region, &gdk_rect);
224
      }
225
    }
226
    return region;
227
  }
228
229
  void AddGdkRectToSystemClipRegion(GdkRectangle *rect) {
230
    if (!sys_clip_region_)
231
      sys_clip_region_ = gdk_region_new();
232
    gdk_region_union_with_rect(sys_clip_region_, rect);
233
  }
234
235
  void AddGdkRegionToSystemClipRegion(GdkRegion *region) {
236
    if (!sys_clip_region_)
237
      sys_clip_region_ = gdk_region_new();
238
    gdk_region_union(sys_clip_region_, region);
239
  }
240
241
  void AddExtendedWindowAreaToSystemClipRegion(int width, int height) {
242
    GdkRectangle gdk_rect;
243
    if (width > last_width_) {
244
      gdk_rect.x = last_width_;
245
      gdk_rect.y = 0;
246
      gdk_rect.width = width - last_width_;
247
      gdk_rect.height = height;
248
      AddGdkRectToSystemClipRegion(&gdk_rect);
249
    }
250
    if (height > last_height_) {
251
      gdk_rect.x = 0;
252
      gdk_rect.y = last_height_;
253
      gdk_rect.width = width;
254
      gdk_rect.height = height - last_height_;
255
      AddGdkRectToSystemClipRegion(&gdk_rect);
256
    }
257
258
    last_width_ = width;
259
    last_height_ = height;
260
  }
261
262
  void AddGdkRectToViewClipRegion(const GdkRectangle &gdk_rect) {
263
    Rectangle rect(gdk_rect.x, gdk_rect.y, gdk_rect.width, gdk_rect.height);
264
    rect.Zoom(1.0 / zoom_);
265
    rect.Integerize(true);
266
    view_->AddRectangleToClipRegion(rect);
267
  }
268
269
  void AddGdkRegionToViewClipRegion(GdkRegion *region) {
270
    if (!gdk_region_empty(region)) {
271
      GdkRectangle *rects;
272
      gint n_rects;
273
      gdk_region_get_rectangles(region, &rects, &n_rects);
274
      for (gint i = 0; i < n_rects; ++i) {
275
        AddGdkRectToViewClipRegion(rects[i]);
276
      }
277
      g_free(rects);
278
    }
279
  }
280
281
#if GTK_CHECK_VERSION(2,10,0)
282
  bool ShouldUpdateInputShapeMask(int width, int height) {
283
    bool update_input_shape_mask = enable_input_shape_mask_ &&
284
        (GetCurrentTime() - last_mask_time_ > kUpdateMaskInterval) &&
285
        no_background_ && composited_;
286
287
    // We need set input shape mask if there is no background.
288
    if (update_input_shape_mask) {
289
      if (input_shape_mask_) {
290
        gint mask_width, mask_height;
291
        gdk_drawable_get_size(GDK_DRAWABLE(input_shape_mask_),
292
                              &mask_width, &mask_height);
293
        if (mask_width != width || mask_height != height) {
294
          // input shape mask needs recreate.
295
          g_object_unref(G_OBJECT(input_shape_mask_));
296
          input_shape_mask_ = NULL;
297
        }
298
      }
299
300
      if (input_shape_mask_ == NULL) {
301
        GdkRectangle rect;
302
        rect.x = 0;
303
        rect.y = 0;
304
        rect.width = width;
305
        rect.height = height;
306
        input_shape_mask_ = gdk_pixmap_new(NULL, width, height, 1);
307
308
        // Redraw whole view.
309
        AddGdkRectToSystemClipRegion(&rect);
310
      }
311
    }
312
313
    return update_input_shape_mask;
314
  }
315
#endif
316
317
  GdkRegion *GetInvalidateRegion() {
318
    gint width, height;
319
    gdk_drawable_get_size(widget_->window, &width, &height);
320
    view_->Layout();
321
#if GTK_CHECK_VERSION(2,10,0)
322
    should_update_input_shape_mask_ = ShouldUpdateInputShapeMask(width, height);
323
#endif
324
    AddExtendedWindowAreaToSystemClipRegion(width, height);
325
    GdkRegion *region = CreateExposeRegionFromViewClipRegion();
326
    if (sys_clip_region_) {
327
      AddGdkRegionToViewClipRegion(sys_clip_region_);
328
      gdk_region_union(region, sys_clip_region_);
329
      gdk_region_destroy(sys_clip_region_);
330
      sys_clip_region_ = NULL;
331
    }
332
    return region;
333
  }
334
335
  void SelfDraw() {
336
    if (!widget_->window || !gdk_window_is_visible(widget_->window))
337
      return;
338
339
    self_draw_ = true;
340
    GdkRegion *region = GetInvalidateRegion();
341
    gdk_window_invalidate_region(widget_->window, region, TRUE);
342
    gdk_region_destroy(region);
343
    gdk_window_process_updates(widget_->window, TRUE);
344
    last_self_draw_time_ = GetCurrentTime();
345
    self_draw_ = false;
346
  }
347
188
  static gboolean ButtonPressHandler(GtkWidget *widget, GdkEventButton *event,
348
  static gboolean ButtonPressHandler(GtkWidget *widget, GdkEventButton *event,
189
                                     gpointer user_data) {
349
                                     gpointer user_data) {
190
    Impl *impl = reinterpret_cast<Impl *>(user_data);
350
    Impl *impl = reinterpret_cast<Impl *>(user_data);
Lines 364-500 Link Here
364
    return result != EVENT_RESULT_UNHANDLED;
524
    return result != EVENT_RESULT_UNHANDLED;
365
  }
525
  }
366
526
367
  static GdkRegion *CreateExposeRegion(const ClipRegion *view_region,
368
                                       int width, int height,
369
                                       int last_width, int last_height,
370
                                       double zoom) {
371
    GdkRegion *region = gdk_region_new();
372
    size_t count = view_region->GetRectangleCount();
373
    GdkRectangle gdk_rect;
374
    if (count) {
375
      Rectangle rect;
376
      for (size_t i = 0; i < count; ++i) {
377
        rect = view_region->GetRectangle(i);
378
        if (zoom != 1.0) {
379
          rect.Zoom(zoom);
380
          rect.Integerize(true);
381
        }
382
        gdk_rect.x = static_cast<int>(rect.x);
383
        gdk_rect.y = static_cast<int>(rect.y);
384
        gdk_rect.width = static_cast<int>(rect.w);
385
        gdk_rect.height = static_cast<int>(rect.h);
386
        gdk_region_union_with_rect(region, &gdk_rect);
387
      }
388
    }
389
    if (width > last_width) {
390
      gdk_rect.x = last_width;
391
      gdk_rect.y = 0;
392
      gdk_rect.width = width - last_width;
393
      gdk_rect.height = height;
394
      gdk_region_union_with_rect(region, &gdk_rect);
395
    }
396
    if (height > last_height) {
397
      gdk_rect.x = 0;
398
      gdk_rect.y = last_height;
399
      gdk_rect.width = width;
400
      gdk_rect.height = height - last_height;
401
      gdk_region_union_with_rect(region, &gdk_rect);
402
    }
403
    return region;
404
  }
405
406
  static void AddGdkRectangleToViewClipRegion(ViewInterface *view,
407
                                              const GdkRectangle &gdk_rect,
408
                                              bool zoom) {
409
    Rectangle rect(gdk_rect.x, gdk_rect.y, gdk_rect.width, gdk_rect.height);
410
    rect.Zoom(1.0 / zoom);
411
    rect.Integerize(true);
412
    view->AddRectangleToClipRegion(rect);
413
  }
414
415
  static void AddGdkRegionToViewClipRegion(ViewInterface *view,
416
                                           GdkRegion *region,
417
                                           bool zoom) {
418
    if (!gdk_region_empty(region)) {
419
      GdkRectangle *rects;
420
      gint n_rects;
421
      gdk_region_get_rectangles(region, &rects, &n_rects);
422
      for (gint i = 0; i < n_rects; ++i) {
423
        AddGdkRectangleToViewClipRegion(view, rects[i], zoom);
424
      }
425
      g_free(rects);
426
    }
427
  }
428
429
  static gboolean ExposeHandler(GtkWidget *widget, GdkEventExpose *event,
527
  static gboolean ExposeHandler(GtkWidget *widget, GdkEventExpose *event,
430
                                gpointer user_data) {
528
                                gpointer user_data) {
431
    Impl *impl = reinterpret_cast<Impl *>(user_data);
529
    Impl *impl = reinterpret_cast<Impl *>(user_data);
432
    gint last_width = impl->last_width_;
433
    gint last_height = impl->last_height_;
434
    gint width, height;
435
    gdk_drawable_get_size(widget->window, &width, &height);
436
530
437
    impl->last_width_ = width;
531
    if (!impl->self_draw_) {
438
    impl->last_height_ = height;
532
      impl->AddGdkRegionToSystemClipRegion(event->region);
533
      GdkRegion *invalidate_region = impl->GetInvalidateRegion();
439
534
440
    impl->view_->Layout();
535
      // We can't update the region outside event->region, so update them in a
441
536
      // new self draw request.
442
    GdkRegion *region = CreateExposeRegion(
537
      gdk_region_subtract(invalidate_region, event->region);
443
        impl->view_->GetClipRegion(), width, height,
538
      if (!gdk_region_empty(invalidate_region)) {
444
        last_width, last_height, impl->zoom_);
539
        impl->AddGdkRegionToSystemClipRegion(invalidate_region);
445
540
        if (!impl->self_draw_timer_) {
446
    uint64_t current_time = GetCurrentTime();
541
          impl->self_draw_timer_ =
447
#if GTK_CHECK_VERSION(2,10,0)
542
              g_idle_add_full(GDK_PRIORITY_REDRAW, Impl::SelfDrawHandler,
448
    bool update_input_shape_mask = impl->enable_input_shape_mask_ &&
543
                              impl, NULL);
449
        (current_time - impl->last_mask_time_ > kUpdateMaskInterval) &&
450
        impl->no_background_ && impl->composited_;
451
452
    // We need set input shape mask if there is no background.
453
    if (update_input_shape_mask) {
454
      if (impl->input_shape_mask_) {
455
        gint mask_width, mask_height;
456
        gdk_drawable_get_size(GDK_DRAWABLE(impl->input_shape_mask_),
457
                              &mask_width, &mask_height);
458
        if (mask_width != width || mask_height != height) {
459
          // input shape mask needs recreate.
460
          g_object_unref(G_OBJECT(impl->input_shape_mask_));
461
          impl->input_shape_mask_ = NULL;
462
        }
544
        }
463
      }
545
      }
464
546
      gdk_region_destroy(invalidate_region);
465
      if (impl->input_shape_mask_ == NULL) {
466
        DLOG("View(%p): need (re)create input shape mask.", impl->view_);
467
        GdkRectangle rect;
468
        rect.x = 0;
469
        rect.y = 0;
470
        rect.width = width;
471
        rect.height = height;
472
        gdk_region_union_with_rect(region, &rect);
473
        impl->input_shape_mask_ = gdk_pixmap_new(NULL, width, height, 1);
474
475
        // Redraw whole view.
476
        AddGdkRectangleToViewClipRegion(impl->view_, rect, impl->zoom_);
477
      }
478
    }
547
    }
479
#endif
480
548
481
    if (event->area.x == 0 && event->area.y == 0 &&
549
    gdk_window_begin_paint_region(widget->window, event->region);
482
        event->area.width == 1 && event->area.height == 1) {
483
      //DLOG("View(%p): self queue draw.", impl->view_);
484
      if (gdk_region_empty(region)) {
485
        DLOG("View(%p) has pending queue draw, but doesn't have clip region.",
486
             impl->view_);
487
        gdk_region_destroy(region);
488
        // No need to redraw.
489
        return TRUE;
490
      }
491
      gdk_window_begin_paint_region(widget->window, region);
492
    } else {
493
      //DLOG("System requires redraw view(%p)", impl->view_);
494
      gdk_region_union(region, event->region);
495
      AddGdkRegionToViewClipRegion(impl->view_, event->region, impl->zoom_);
496
      gdk_window_begin_paint_region(widget->window, region);
497
    }
498
550
499
    cairo_t *cr = gdk_cairo_create(widget->window);
551
    cairo_t *cr = gdk_cairo_create(widget->window);
500
552
Lines 522-530 Link Here
522
574
523
#if GTK_CHECK_VERSION(2,10,0)
575
#if GTK_CHECK_VERSION(2,10,0)
524
    // We need set input shape mask if there is no background.
576
    // We need set input shape mask if there is no background.
525
    if (update_input_shape_mask && impl->input_shape_mask_) {
577
    if (impl->should_update_input_shape_mask_ && impl->input_shape_mask_) {
526
      cairo_t *mask_cr = gdk_cairo_create(impl->input_shape_mask_);
578
      cairo_t *mask_cr = gdk_cairo_create(impl->input_shape_mask_);
527
      gdk_cairo_region(mask_cr, region);
579
      gdk_cairo_region(mask_cr, event->region);
528
      cairo_clip(mask_cr);
580
      cairo_clip(mask_cr);
529
      cairo_set_operator(mask_cr, CAIRO_OPERATOR_CLEAR);
581
      cairo_set_operator(mask_cr, CAIRO_OPERATOR_CLEAR);
530
      cairo_paint(mask_cr);
582
      cairo_paint(mask_cr);
Lines 534-549 Link Here
534
      cairo_destroy(mask_cr);
586
      cairo_destroy(mask_cr);
535
      gdk_window_input_shape_combine_mask(widget->window,
587
      gdk_window_input_shape_combine_mask(widget->window,
536
                                          impl->input_shape_mask_, 0, 0);
588
                                          impl->input_shape_mask_, 0, 0);
537
      impl->last_mask_time_ = current_time;
589
      impl->last_mask_time_ = GetCurrentTime();
538
    }
590
    }
539
#endif
591
#endif
540
592
541
    // Copy off-screen buffer to screen.
593
    // Copy off-screen buffer to screen.
542
    gdk_window_end_paint(widget->window);
594
    gdk_window_end_paint(widget->window);
543
    gdk_region_destroy(region);
544
595
545
#ifdef _DEBUG
596
#ifdef _DEBUG
546
    ++impl->draw_count_;
597
    ++impl->draw_count_;
598
    uint64_t current_time = GetCurrentTime();
547
    uint64_t duration = current_time - impl->last_fps_time_;
599
    uint64_t duration = current_time - impl->last_fps_time_;
548
    if (duration >= kFPSCountDuration) {
600
    if (duration >= kFPSCountDuration) {
549
      impl->last_fps_time_ = current_time;
601
      impl->last_fps_time_ = current_time;
Lines 915-926 Link Here
915
    return FALSE;
967
    return FALSE;
916
  }
968
  }
917
969
970
  static gboolean SelfDrawHandler(gpointer user_data) {
971
    Impl *impl = reinterpret_cast<Impl *>(user_data);
972
    impl->self_draw_timer_ = 0;
973
    impl->SelfDraw();
974
    return FALSE;
975
  }
976
918
  ViewInterface *view_;
977
  ViewInterface *view_;
919
  ViewHostInterface *host_;
978
  ViewHostInterface *host_;
920
  GtkWidget *widget_;
979
  GtkWidget *widget_;
921
#if GTK_CHECK_VERSION(2,10,0)
980
#if GTK_CHECK_VERSION(2,10,0)
922
  GdkBitmap *input_shape_mask_;
981
  GdkBitmap *input_shape_mask_;
923
  uint64_t last_mask_time_;
982
  uint64_t last_mask_time_;
983
  bool should_update_input_shape_mask_;
984
  bool enable_input_shape_mask_;
924
#endif
985
#endif
925
  gulong *handlers_;
986
  gulong *handlers_;
926
  DragEvent *current_drag_event_;
987
  DragEvent *current_drag_event_;
Lines 928-934 Link Here
928
  bool dbl_click_;
989
  bool dbl_click_;
929
  bool composited_;
990
  bool composited_;
930
  bool no_background_;
991
  bool no_background_;
931
  bool enable_input_shape_mask_;
932
  bool focused_;
992
  bool focused_;
933
  bool button_pressed_;
993
  bool button_pressed_;
934
#ifdef GRAB_POINTER_EXPLICITLY
994
#ifdef GRAB_POINTER_EXPLICITLY
Lines 946-951 Link Here
946
  int last_width_;
1006
  int last_width_;
947
  int last_height_;
1007
  int last_height_;
948
1008
1009
  bool self_draw_;
1010
  guint self_draw_timer_;
1011
  uint64_t last_self_draw_time_;
1012
  GdkRegion *sys_clip_region_;
1013
949
  struct EventHandlerInfo {
1014
  struct EventHandlerInfo {
950
    const char *event;
1015
    const char *event;
951
    void (*handler)(void);
1016
    void (*handler)(void);
Lines 991-999 Link Here
991
}
1056
}
992
1057
993
void ViewWidgetBinder::EnableInputShapeMask(bool enable) {
1058
void ViewWidgetBinder::EnableInputShapeMask(bool enable) {
1059
#if GTK_CHECK_VERSION(2,10,0)
994
  if (impl_->enable_input_shape_mask_ != enable) {
1060
  if (impl_->enable_input_shape_mask_ != enable) {
995
    impl_->enable_input_shape_mask_ = enable;
1061
    impl_->enable_input_shape_mask_ = enable;
996
#if GTK_CHECK_VERSION(2,10,0)
997
    if (impl_->widget_ && impl_->no_background_ &&
1062
    if (impl_->widget_ && impl_->no_background_ &&
998
        impl_->composited_ && !enable) {
1063
        impl_->composited_ && !enable) {
999
      if (impl_->widget_->window) {
1064
      if (impl_->widget_->window) {
Lines 1004-1009 Link Here
1004
        impl_->input_shape_mask_ = NULL;
1069
        impl_->input_shape_mask_ = NULL;
1005
      }
1070
      }
1006
    }
1071
    }
1072
    gtk_widget_queue_draw(impl_->widget_);
1007
  }
1073
  }
1008
#endif
1074
#endif
1009
}
1075
}
Lines 1013-1017 Link Here
1013
  impl_ = NULL;
1079
  impl_ = NULL;
1014
}
1080
}
1015
1081
1082
void ViewWidgetBinder::QueueDraw() {
1083
  if (!impl_->self_draw_timer_) {
1084
    uint64_t current_time = GetCurrentTime();
1085
    if (current_time - impl_->last_self_draw_time_ >= kSelfDrawInterval) {
1086
      impl_->self_draw_timer_ =
1087
          g_idle_add_full(GDK_PRIORITY_REDRAW, Impl::SelfDrawHandler,
1088
                          impl_, NULL);
1089
    } else {
1090
      impl_->self_draw_timer_ =
1091
          g_timeout_add(kSelfDrawInterval -
1092
                        (current_time - impl_->last_self_draw_time_),
1093
                        Impl::SelfDrawHandler, impl_);
1094
    }
1095
  }
1096
}
1097
1098
void ViewWidgetBinder::DrawImmediately() {
1099
  // Remove pending queue draw, as we don't need it anymore.
1100
  if (impl_->self_draw_timer_) {
1101
    g_source_remove(impl_->self_draw_timer_);
1102
    impl_->self_draw_timer_ = 0;
1103
  }
1104
  impl_->SelfDraw();
1105
}
1106
1107
bool ViewWidgetBinder::DrawQueued() {
1108
  return impl_->self_draw_timer_ != 0;
1109
}
1110
1016
} // namespace gtk
1111
} // namespace gtk
1017
} // namespace ggadget
1112
} // namespace ggadget
(-)ggadget/gtk/single_view_host.cc (-93 / +14 lines)
Lines 47-58 Link Here
47
static const int kStopMoveDragTimeout = 200;
47
static const int kStopMoveDragTimeout = 200;
48
static const char kMainViewWindowRole[] = "Google-Gadgets";
48
static const char kMainViewWindowRole[] = "Google-Gadgets";
49
49
50
// Minimal interval between queue draws.
51
static const unsigned int kQueueDrawInterval = 40;
52
53
// Maximum live duration of queue draw timer.
54
static const uint64_t kQueueDrawTimerDuration = 1000;
55
56
class SingleViewHost::Impl {
50
class SingleViewHost::Impl {
57
 public:
51
 public:
58
  Impl(SingleViewHost *owner, ViewHostInterface::Type type,
52
  Impl(SingleViewHost *owner, ViewHostInterface::Type type,
Lines 92-104 Link Here
92
      is_keep_above_(false),
86
      is_keep_above_(false),
93
      move_dragging_(false),
87
      move_dragging_(false),
94
      enable_signals_(true),
88
      enable_signals_(true),
95
      draw_queued_(false),
96
      draw_finished_(true),
97
      queue_draw_timer_(0),
98
      last_queue_draw_time_(0),
99
      queue_resize_timer_(0),
89
      queue_resize_timer_(0),
100
      last_allocated_width_(0),
90
      fixed_width_from_view_(0),
101
      last_allocated_height_(0),
91
      fixed_height_from_view_(0),
102
      feedback_handler_(NULL),
92
      feedback_handler_(NULL),
103
      can_close_dialog_(false) {
93
      can_close_dialog_(false) {
104
    ASSERT(owner);
94
    ASSERT(owner);
Lines 115-124 Link Here
115
    // To make sure that it won't be accessed anymore.
105
    // To make sure that it won't be accessed anymore.
116
    view_ = NULL;
106
    view_ = NULL;
117
107
118
    if (queue_draw_timer_)
119
      g_source_remove(queue_draw_timer_);
120
    queue_draw_timer_ = 0;
121
122
    if (queue_resize_timer_)
108
    if (queue_resize_timer_)
123
      g_source_remove(queue_resize_timer_);
109
      g_source_remove(queue_resize_timer_);
124
    queue_resize_timer_ = 0;
110
    queue_resize_timer_ = 0;
Lines 234-242 Link Here
234
    g_signal_connect(G_OBJECT(fixed_), "size-allocate",
220
    g_signal_connect(G_OBJECT(fixed_), "size-allocate",
235
                     G_CALLBACK(FixedSizeAllocateHandler), this);
221
                     G_CALLBACK(FixedSizeAllocateHandler), this);
236
222
237
    g_signal_connect(G_OBJECT(widget_), "expose-event",
238
                     G_CALLBACK(ExposeHandler), this);
239
240
    g_signal_connect(G_OBJECT(fixed_), "set-focus-child",
223
    g_signal_connect(G_OBJECT(fixed_), "set-focus-child",
241
                     G_CALLBACK(FixedSetFocusChildHandler), this);
224
                     G_CALLBACK(FixedSetFocusChildHandler), this);
242
225
Lines 275-280 Link Here
275
    int width = static_cast<int>(ceil(view_->GetWidth() * zoom));
258
    int width = static_cast<int>(ceil(view_->GetWidth() * zoom));
276
    int height = static_cast<int>(ceil(view_->GetHeight() * zoom));
259
    int height = static_cast<int>(ceil(view_->GetHeight() * zoom));
277
260
261
    // Stores the expected size of the GtkFixed widget, which will be used in
262
    // FixedSizeAllocateHandler().
263
    fixed_width_from_view_ = width;
264
    fixed_height_from_view_ = height;
265
278
    GtkRequisition req;
266
    GtkRequisition req;
279
    gtk_widget_set_size_request(widget_, width, height);
267
    gtk_widget_set_size_request(widget_, width, height);
280
    gtk_widget_size_request(window_, &req);
268
    gtk_widget_size_request(window_, &req);
Lines 293-300 Link Here
293
      win_width_ = req.width;
281
      win_width_ = req.width;
294
      win_height_ = req.height;
282
      win_height_ = req.height;
295
    }
283
    }
296
297
    DLOG("New window size: %d %d", req.width, req.height);
298
  }
284
  }
299
285
300
  void QueueResize() {
286
  void QueueResize() {
Lines 311-343 Link Here
311
      DLOG("SingleViewHost::EnableInputShapeMask(%s)",
297
      DLOG("SingleViewHost::EnableInputShapeMask(%s)",
312
           enable ? "true" : "false");
298
           enable ? "true" : "false");
313
      binder_->EnableInputShapeMask(enable);
299
      binder_->EnableInputShapeMask(enable);
314
      QueueDraw();
315
    }
300
    }
316
  }
301
  }
317
302
318
  void QueueDraw() {
303
  void QueueDraw() {
319
    ASSERT(GTK_IS_WIDGET(widget_));
304
    ASSERT(GTK_IS_WIDGET(widget_));
320
    draw_finished_ = false;
305
    if (binder_)
321
    if (queue_draw_timer_) {
306
      binder_->QueueDraw();
322
      draw_queued_ = true;
323
      return;
324
    }
325
326
    uint64_t current_time = GetCurrentTime();
327
    if (current_time - last_queue_draw_time_ >= kQueueDrawInterval) {
328
      gtk_widget_queue_draw(widget_);
329
      draw_queued_ = false;
330
      last_queue_draw_time_ = current_time;
331
    } else {
332
      draw_queued_ = true;
333
    }
334
335
    // Can't call view's GetCaption() here, because at this point, view might
336
    // not be fully initialized yet.
337
    DLOG("Install queue draw timer of view: %p", view_);
338
    queue_draw_timer_ = g_timeout_add(kQueueDrawInterval,
339
                                      QueueDrawTimeoutHandler,
340
                                      this);
341
  }
307
  }
342
308
343
  void SetResizable(ViewInterface::ResizableMode mode) {
309
  void SetResizable(ViewInterface::ResizableMode mode) {
Lines 861-867 Link Here
861
#endif
827
#endif
862
      }
828
      }
863
829
864
      if (impl->draw_queued_ || !impl->draw_finished_)
830
      if (impl->binder_ && impl->binder_->DrawQueued())
865
        return TRUE;
831
        return TRUE;
866
832
867
      int button = ConvertGdkModifierToButton(event->state);
833
      int button = ConvertGdkModifierToButton(event->state);
Lines 881-887 Link Here
881
          double view_width = new_width / impl->resize_view_zoom_;
847
          double view_width = new_width / impl->resize_view_zoom_;
882
          double view_height = new_height / impl->resize_view_zoom_;
848
          double view_height = new_height / impl->resize_view_zoom_;
883
          if (impl->view_->OnSizing(&view_width, &view_height)) {
849
          if (impl->view_->OnSizing(&view_width, &view_height)) {
884
            DLOG("Resize view to: %lf %lf", view_width, view_height);
885
            impl->view_->SetSize(view_width, view_height);
850
            impl->view_->SetSize(view_width, view_height);
886
            width = impl->view_->GetWidth() * impl->resize_view_zoom_;
851
            width = impl->view_->GetWidth() * impl->resize_view_zoom_;
887
            height = impl->view_->GetHeight() * impl->resize_view_zoom_;
852
            height = impl->view_->GetHeight() * impl->resize_view_zoom_;
Lines 891-897 Link Here
891
          double yzoom = new_height / impl->resize_view_height_;
856
          double yzoom = new_height / impl->resize_view_height_;
892
          double zoom = std::min(xzoom, yzoom);
857
          double zoom = std::min(xzoom, yzoom);
893
          zoom = Clamp(zoom, kMinimumZoom, kMaximumZoom);
858
          zoom = Clamp(zoom, kMinimumZoom, kMaximumZoom);
894
          DLOG("Zoom view to: %lf", zoom);
895
          impl->view_->GetGraphics()->SetZoom(zoom);
859
          impl->view_->GetGraphics()->SetZoom(zoom);
896
          impl->view_->MarkRedraw();
860
          impl->view_->MarkRedraw();
897
          width = impl->resize_view_width_ * zoom;
861
          width = impl->resize_view_width_ * zoom;
Lines 910-918 Link Here
910
          int win_width = impl->resize_win_width_ + int(delta_x);
874
          int win_width = impl->resize_win_width_ + int(delta_x);
911
          int win_height = impl->resize_win_height_ + int(delta_y);
875
          int win_height = impl->resize_win_height_ + int(delta_y);
912
          gdk_window_move_resize(widget->window, x, y, win_width, win_height);
876
          gdk_window_move_resize(widget->window, x, y, win_width, win_height);
913
          gdk_window_process_updates(widget->window, TRUE);
914
          DLOG("Move resize window: x:%d, y:%d, w:%d, h:%d", x, y,
915
               win_width, win_height);
916
        }
877
        }
917
878
918
        return TRUE;
879
        return TRUE;
Lines 965-980 Link Here
965
                                       GtkAllocation *allocation,
926
                                       GtkAllocation *allocation,
966
                                       gpointer user_data) {
927
                                       gpointer user_data) {
967
    Impl *impl = reinterpret_cast<Impl *>(user_data);
928
    Impl *impl = reinterpret_cast<Impl *>(user_data);
968
    DLOG("Size allocate(%d, %d)", allocation->width, allocation->height);
969
    if (GTK_WIDGET_VISIBLE(impl->window_) &&
929
    if (GTK_WIDGET_VISIBLE(impl->window_) &&
970
        !impl->resize_width_mode_ && !impl->resize_height_mode_ &&
930
        !impl->resize_width_mode_ && !impl->resize_height_mode_ &&
971
        !impl->queue_resize_timer_ &&
931
        !impl->queue_resize_timer_ &&
972
        allocation->width >= 1 && allocation->height >= 1 &&
932
        allocation->width >= 1 && allocation->height >= 1 &&
973
        (impl->last_allocated_width_ != allocation->width ||
933
        (impl->fixed_width_from_view_ != allocation->width ||
974
         impl->last_allocated_height_ != allocation->height)) {
934
         impl->fixed_height_from_view_ != allocation->height)) {
975
      impl->last_allocated_width_ = allocation->width;
976
      impl->last_allocated_height_ = allocation->height;
977
978
      double old_width = impl->view_->GetWidth();
935
      double old_width = impl->view_->GetWidth();
979
      double old_height = impl->view_->GetHeight();
936
      double old_height = impl->view_->GetHeight();
980
      double old_zoom = impl->view_->GetGraphics()->GetZoom();
937
      double old_zoom = impl->view_->GetGraphics()->GetZoom();
Lines 984-990 Link Here
984
        double new_height = allocation->height / old_zoom;
941
        double new_height = allocation->height / old_zoom;
985
        if (impl->view_->OnSizing(&new_width, &new_height) &&
942
        if (impl->view_->OnSizing(&new_width, &new_height) &&
986
            (new_width != old_width || new_height != old_height)) {
943
            (new_width != old_width || new_height != old_height)) {
987
          DLOG("Resize view to: %lf %lf", new_width, new_height);
988
          impl->view_->SetSize(new_width, new_height);
944
          impl->view_->SetSize(new_width, new_height);
989
        }
945
        }
990
      } else if (impl->resizable_mode_ == ViewInterface::RESIZABLE_ZOOM &&
946
      } else if (impl->resizable_mode_ == ViewInterface::RESIZABLE_ZOOM &&
Lines 994-1000 Link Here
994
        double new_zoom = Clamp(std::min(xzoom, yzoom),
950
        double new_zoom = Clamp(std::min(xzoom, yzoom),
995
                                kMinimumZoom, kMaximumZoom);
951
                                kMinimumZoom, kMaximumZoom);
996
        if (old_zoom != new_zoom) {
952
        if (old_zoom != new_zoom) {
997
          DLOG("Zoom view to: %lf", new_zoom);
998
          impl->view_->GetGraphics()->SetZoom(new_zoom);
953
          impl->view_->GetGraphics()->SetZoom(new_zoom);
999
          impl->view_->MarkRedraw();
954
          impl->view_->MarkRedraw();
1000
        }
955
        }
Lines 1021-1047 Link Here
1021
    return FALSE;
976
    return FALSE;
1022
  }
977
  }
1023
978
1024
  static gboolean QueueDrawTimeoutHandler(gpointer data) {
1025
    Impl *impl = reinterpret_cast<Impl *>(data);
1026
    uint64_t current_time = GetCurrentTime();
1027
    if (impl->draw_queued_) {
1028
      ASSERT(GTK_IS_WIDGET(impl->widget_));
1029
      // Special hack to inform ViewWidgetBinder this queue draw request is
1030
      // generated by us instead of system.
1031
      gtk_widget_queue_draw_area(impl->widget_, 0, 0, 1, 1);
1032
      impl->draw_queued_ = false;
1033
      impl->last_queue_draw_time_ = current_time;
1034
    }
1035
1036
    if (current_time - impl->last_queue_draw_time_ > kQueueDrawTimerDuration) {
1037
      DLOG("Remove queue draw timer of view: %p (%s)", impl->view_,
1038
           impl->view_->GetCaption().c_str());
1039
      impl->queue_draw_timer_ = 0;
1040
      return FALSE;
1041
    }
1042
    return TRUE;
1043
  }
1044
1045
  static gboolean QueueResizeTimeoutHandler(gpointer data) {
979
  static gboolean QueueResizeTimeoutHandler(gpointer data) {
1046
    Impl *impl = reinterpret_cast<Impl *>(data);
980
    Impl *impl = reinterpret_cast<Impl *>(data);
1047
    impl->AdjustWindowSize();
981
    impl->AdjustWindowSize();
Lines 1049-1062 Link Here
1049
    return false;
983
    return false;
1050
  }
984
  }
1051
985
1052
  static gboolean ExposeHandler(GtkWidget *widget, GdkEventExpose *event,
1053
                                gpointer data) {
1054
    Impl *impl = reinterpret_cast<Impl *>(data);
1055
    impl->draw_finished_ = true;
1056
    // Make sure view widget binder can receive this event.
1057
    return FALSE;
1058
  }
1059
1060
  // Some elements may create gtk native widgets under this widget. When such
986
  // Some elements may create gtk native widgets under this widget. When such
1061
  // a widget get focus, we must update the focus chain though the view
987
  // a widget get focus, we must update the focus chain though the view
1062
  // hierachy.
988
  // hierachy.
Lines 1136-1149 Link Here
1136
  bool move_dragging_;
1062
  bool move_dragging_;
1137
  bool enable_signals_;
1063
  bool enable_signals_;
1138
1064
1139
  bool draw_queued_;
1140
  bool draw_finished_;
1141
  guint queue_draw_timer_;
1142
  uint64_t last_queue_draw_time_;
1143
1144
  guint queue_resize_timer_;
1065
  guint queue_resize_timer_;
1145
  gint last_allocated_width_;
1066
  int fixed_width_from_view_;
1146
  gint last_allocated_height_;
1067
  int fixed_height_from_view_;
1147
1068
1148
  Slot1<bool, int> *feedback_handler_;
1069
  Slot1<bool, int> *feedback_handler_;
1149
  bool can_close_dialog_; // Only useful when a model dialog is running.
1070
  bool can_close_dialog_; // Only useful when a model dialog is running.
(-)ggadget/gtk/view_widget_binder.h (+9 lines)
Lines 54-59 Link Here
54
   */
54
   */
55
  void EnableInputShapeMask(bool enable);
55
  void EnableInputShapeMask(bool enable);
56
56
57
  /** Called by ViewHost to queue a redraw request. */
58
  void QueueDraw();
59
60
  /** Checks if a redraw request has been queued. */
61
  bool DrawQueued();
62
63
  /** Redraws the gadget immediately. */
64
  void DrawImmediately();
65
57
 private:
66
 private:
58
  DISALLOW_EVIL_CONSTRUCTORS(ViewWidgetBinder);
67
  DISALLOW_EVIL_CONSTRUCTORS(ViewWidgetBinder);
59
  class Impl;
68
  class Impl;

Return to bug 294124