Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(178)

Side by Side Diff: views/widget/widget_gtk.cc

Issue 6881107: Rework the way Widget::Init works: (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « views/widget/widget_gtk.h ('k') | views/widget/widget_win.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "views/widget/widget_gtk.h" 5 #include "views/widget/widget_gtk.h"
6 6
7 #include <gdk/gdk.h> 7 #include <gdk/gdk.h>
8 #include <gdk/gdkx.h> 8 #include <gdk/gdkx.h>
9 #include <X11/extensions/shape.h> 9 #include <X11/extensions/shape.h>
10 #include <X11/Xatom.h> 10 #include <X11/Xatom.h>
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after
276 return drag_widget; 276 return drag_widget;
277 } 277 }
278 278
279 // static 279 // static
280 GtkWidget* WidgetGtk::null_parent_ = NULL; 280 GtkWidget* WidgetGtk::null_parent_ = NULL;
281 bool WidgetGtk::debug_paint_enabled_ = false; 281 bool WidgetGtk::debug_paint_enabled_ = false;
282 282
283 //////////////////////////////////////////////////////////////////////////////// 283 ////////////////////////////////////////////////////////////////////////////////
284 // WidgetGtk, public: 284 // WidgetGtk, public:
285 285
286 WidgetGtk::WidgetGtk(Type type) 286 WidgetGtk::WidgetGtk()
287 : is_window_(false), 287 : is_window_(false),
288 ALLOW_THIS_IN_INITIALIZER_LIST(delegate_(this)), 288 ALLOW_THIS_IN_INITIALIZER_LIST(delegate_(this)),
289 type_(type),
290 widget_(NULL), 289 widget_(NULL),
291 window_contents_(NULL), 290 window_contents_(NULL),
291 child_(false),
292 ALLOW_THIS_IN_INITIALIZER_LIST(close_widget_factory_(this)), 292 ALLOW_THIS_IN_INITIALIZER_LIST(close_widget_factory_(this)),
293 delete_on_destroy_(true), 293 delete_on_destroy_(true),
294 transparent_(false), 294 transparent_(false),
295 ignore_events_(false), 295 ignore_events_(false),
296 ignore_drag_leave_(false), 296 ignore_drag_leave_(false),
297 opacity_(255), 297 opacity_(255),
298 drag_data_(NULL), 298 drag_data_(NULL),
299 is_active_(false), 299 is_active_(false),
300 transient_to_parent_(false), 300 transient_to_parent_(false),
301 got_initial_focus_in_(false), 301 got_initial_focus_in_(false),
(...skipping 17 matching lines...) Expand all
319 loop->AddObserver(DropObserver::GetInstance()); 319 loop->AddObserver(DropObserver::GetInstance());
320 } 320 }
321 } 321 }
322 322
323 WidgetGtk::~WidgetGtk() { 323 WidgetGtk::~WidgetGtk() {
324 // We need to delete the input method before calling DestroyRootView(), 324 // We need to delete the input method before calling DestroyRootView(),
325 // because it'll set focus_manager_ to NULL. 325 // because it'll set focus_manager_ to NULL.
326 input_method_.reset(); 326 input_method_.reset();
327 DestroyRootView(); 327 DestroyRootView();
328 DCHECK(delete_on_destroy_ || widget_ == NULL); 328 DCHECK(delete_on_destroy_ || widget_ == NULL);
329 if (type_ != TYPE_CHILD)
330 ActiveWindowWatcherX::RemoveObserver(this);
331 } 329 }
332 330
333 GtkWindow* WidgetGtk::GetTransientParent() const { 331 GtkWindow* WidgetGtk::GetTransientParent() const {
334 return (type_ != TYPE_CHILD && widget_) ? 332 return (!child_ && widget_) ?
335 gtk_window_get_transient_for(GTK_WINDOW(widget_)) : NULL; 333 gtk_window_get_transient_for(GTK_WINDOW(widget_)) : NULL;
336 } 334 }
337 335
338 bool WidgetGtk::MakeTransparent() { 336 bool WidgetGtk::MakeTransparent() {
339 // Transparency can only be enabled only if we haven't realized the widget. 337 // Transparency can only be enabled only if we haven't realized the widget.
340 DCHECK(!widget_); 338 DCHECK(!widget_);
341 339
342 if (!gdk_screen_is_composited(gdk_screen_get_default())) { 340 if (!gdk_screen_is_composited(gdk_screen_get_default())) {
343 // Transparency is only supported for compositing window managers. 341 // Transparency is only supported for compositing window managers.
344 // NOTE: there's a race during ChromeOS startup such that X might think 342 // NOTE: there's a race during ChromeOS startup such that X might think
(...skipping 14 matching lines...) Expand all
359 void WidgetGtk::EnableDoubleBuffer(bool enabled) { 357 void WidgetGtk::EnableDoubleBuffer(bool enabled) {
360 is_double_buffered_ = enabled; 358 is_double_buffered_ = enabled;
361 if (window_contents_) { 359 if (window_contents_) {
362 if (is_double_buffered_) 360 if (is_double_buffered_)
363 GTK_WIDGET_SET_FLAGS(window_contents_, GTK_DOUBLE_BUFFERED); 361 GTK_WIDGET_SET_FLAGS(window_contents_, GTK_DOUBLE_BUFFERED);
364 else 362 else
365 GTK_WIDGET_UNSET_FLAGS(window_contents_, GTK_DOUBLE_BUFFERED); 363 GTK_WIDGET_UNSET_FLAGS(window_contents_, GTK_DOUBLE_BUFFERED);
366 } 364 }
367 } 365 }
368 366
369 bool WidgetGtk::MakeIgnoreEvents() {
370 // Transparency can only be enabled for windows/popups and only if we haven't
371 // realized the widget.
372 DCHECK(!widget_ && type_ != TYPE_CHILD);
373
374 ignore_events_ = true;
375 return true;
376 }
377
378 void WidgetGtk::AddChild(GtkWidget* child) { 367 void WidgetGtk::AddChild(GtkWidget* child) {
379 gtk_container_add(GTK_CONTAINER(window_contents_), child); 368 gtk_container_add(GTK_CONTAINER(window_contents_), child);
380 } 369 }
381 370
382 void WidgetGtk::RemoveChild(GtkWidget* child) { 371 void WidgetGtk::RemoveChild(GtkWidget* child) {
383 // We can be called after the contents widget has been destroyed, e.g. any 372 // We can be called after the contents widget has been destroyed, e.g. any
384 // NativeViewHost not removed from the view hierarchy before the window is 373 // NativeViewHost not removed from the view hierarchy before the window is
385 // closed. 374 // closed.
386 if (GTK_IS_CONTAINER(window_contents_)) { 375 if (GTK_IS_CONTAINER(window_contents_)) {
387 gtk_container_remove(GTK_CONTAINER(window_contents_), child); 376 gtk_container_remove(GTK_CONTAINER(window_contents_), child);
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
483 472
484 //////////////////////////////////////////////////////////////////////////////// 473 ////////////////////////////////////////////////////////////////////////////////
485 // WidgetGtk, ActiveWindowWatcherX::Observer implementation: 474 // WidgetGtk, ActiveWindowWatcherX::Observer implementation:
486 475
487 void WidgetGtk::ActiveWindowChanged(GdkWindow* active_window) { 476 void WidgetGtk::ActiveWindowChanged(GdkWindow* active_window) {
488 if (!GetNativeView()) 477 if (!GetNativeView())
489 return; 478 return;
490 479
491 bool was_active = IsActive(); 480 bool was_active = IsActive();
492 is_active_ = (active_window == GTK_WIDGET(GetNativeView())->window); 481 is_active_ = (active_window == GTK_WIDGET(GetNativeView())->window);
493 if (!is_active_ && active_window && type_ != TYPE_CHILD) { 482 if (!is_active_ && active_window && !child_) {
494 // We're not active, but the force the window to be rendered as active if 483 // We're not active, but the force the window to be rendered as active if
495 // a child window is transient to us. 484 // a child window is transient to us.
496 gpointer data = NULL; 485 gpointer data = NULL;
497 gdk_window_get_user_data(active_window, &data); 486 gdk_window_get_user_data(active_window, &data);
498 GtkWidget* widget = reinterpret_cast<GtkWidget*>(data); 487 GtkWidget* widget = reinterpret_cast<GtkWidget*>(data);
499 is_active_ = 488 is_active_ =
500 (widget && GTK_IS_WINDOW(widget) && 489 (widget && GTK_IS_WINDOW(widget) &&
501 gtk_window_get_transient_for(GTK_WINDOW(widget)) == GTK_WINDOW( 490 gtk_window_get_transient_for(GTK_WINDOW(widget)) == GTK_WINDOW(
502 widget_)); 491 widget_));
503 } 492 }
504 if (was_active != IsActive()) { 493 if (was_active != IsActive()) {
505 IsActiveChanged(); 494 IsActiveChanged();
506 GetRootView()->SchedulePaint(); 495 GetRootView()->SchedulePaint();
507 } 496 }
508 } 497 }
509 498
510 //////////////////////////////////////////////////////////////////////////////// 499 ////////////////////////////////////////////////////////////////////////////////
511 // WidgetGtk, Widget implementation: 500 // WidgetGtk, Widget implementation:
512 501
513 void WidgetGtk::InitWithWidget(Widget* parent,
514 const gfx::Rect& bounds) {
515 WidgetGtk* parent_gtk = static_cast<WidgetGtk*>(parent);
516 GtkWidget* native_parent = NULL;
517 if (parent != NULL) {
518 if (type_ != TYPE_CHILD) {
519 // window's parent has to be window.
520 native_parent = parent_gtk->GetNativeView();
521 } else {
522 native_parent = parent_gtk->window_contents();
523 }
524 }
525 Init(native_parent, bounds);
526 }
527
528 void WidgetGtk::Init(GtkWidget* parent,
529 const gfx::Rect& bounds) {
530 Widget::Init(parent, bounds);
531 if (type_ != TYPE_CHILD)
532 ActiveWindowWatcherX::AddObserver(this);
533
534 // Make container here.
535 CreateGtkWidget(parent, bounds);
536 delegate_->OnNativeWidgetCreated();
537
538 // Creates input method for toplevel widget after calling
539 // delegate_->OnNativeWidgetCreated(), to make sure that focus manager is
540 // already created at this point.
541 // TODO(suzhe): Always enable input method when we start to use
542 // RenderWidgetHostViewViews in normal ChromeOS.
543 #if defined(TOUCH_UI) && defined(HAVE_IBUS)
544 if (type_ != TYPE_CHILD) {
545 input_method_.reset(new InputMethodIBus(this));
546 #else
547 if (type_ != TYPE_CHILD && NativeTextfieldViews::IsTextfieldViewsEnabled()) {
548 input_method_.reset(new InputMethodGtk(this));
549 #endif
550 input_method_->Init(GetWidget());
551 }
552
553 if (opacity_ != 255)
554 SetOpacity(opacity_);
555
556 // Make sure we receive our motion events.
557
558 // In general we register most events on the parent of all widgets. At a
559 // minimum we need painting to happen on the parent (otherwise painting
560 // doesn't work at all), and similarly we need mouse release events on the
561 // parent as windows don't get mouse releases.
562 gtk_widget_add_events(window_contents_,
563 GDK_ENTER_NOTIFY_MASK |
564 GDK_LEAVE_NOTIFY_MASK |
565 GDK_BUTTON_PRESS_MASK |
566 GDK_BUTTON_RELEASE_MASK |
567 GDK_POINTER_MOTION_MASK |
568 GDK_KEY_PRESS_MASK |
569 GDK_KEY_RELEASE_MASK);
570
571 g_signal_connect_after(G_OBJECT(window_contents_), "size_request",
572 G_CALLBACK(&OnSizeRequestThunk), this);
573 g_signal_connect_after(G_OBJECT(window_contents_), "size_allocate",
574 G_CALLBACK(&OnSizeAllocateThunk), this);
575 gtk_widget_set_app_paintable(window_contents_, true);
576 g_signal_connect(window_contents_, "expose_event",
577 G_CALLBACK(&OnPaintThunk), this);
578 g_signal_connect(window_contents_, "enter_notify_event",
579 G_CALLBACK(&OnEnterNotifyThunk), this);
580 g_signal_connect(window_contents_, "leave_notify_event",
581 G_CALLBACK(&OnLeaveNotifyThunk), this);
582 g_signal_connect(window_contents_, "motion_notify_event",
583 G_CALLBACK(&OnMotionNotifyThunk), this);
584 g_signal_connect(window_contents_, "button_press_event",
585 G_CALLBACK(&OnButtonPressThunk), this);
586 g_signal_connect(window_contents_, "button_release_event",
587 G_CALLBACK(&OnButtonReleaseThunk), this);
588 g_signal_connect(window_contents_, "grab_broken_event",
589 G_CALLBACK(&OnGrabBrokeEventThunk), this);
590 g_signal_connect(window_contents_, "grab_notify",
591 G_CALLBACK(&OnGrabNotifyThunk), this);
592 g_signal_connect(window_contents_, "scroll_event",
593 G_CALLBACK(&OnScrollThunk), this);
594 g_signal_connect(window_contents_, "visibility_notify_event",
595 G_CALLBACK(&OnVisibilityNotifyThunk), this);
596
597 // In order to receive notification when the window is no longer the front
598 // window, we need to install these on the widget.
599 // NOTE: this doesn't work with focus follows mouse.
600 g_signal_connect(widget_, "focus_in_event",
601 G_CALLBACK(&OnFocusInThunk), this);
602 g_signal_connect(widget_, "focus_out_event",
603 G_CALLBACK(&OnFocusOutThunk), this);
604 g_signal_connect(widget_, "destroy",
605 G_CALLBACK(&OnDestroyThunk), this);
606 g_signal_connect(widget_, "show",
607 G_CALLBACK(&OnShowThunk), this);
608 g_signal_connect(widget_, "map",
609 G_CALLBACK(&OnMapThunk), this);
610 g_signal_connect(widget_, "hide",
611 G_CALLBACK(&OnHideThunk), this);
612
613 // Views/FocusManager (re)sets the focus to the root window,
614 // so we need to connect signal handlers to the gtk window.
615 // See views::Views::Focus and views::FocusManager::ClearNativeFocus
616 // for more details.
617 g_signal_connect(widget_, "key_press_event",
618 G_CALLBACK(&OnEventKeyThunk), this);
619 g_signal_connect(widget_, "key_release_event",
620 G_CALLBACK(&OnEventKeyThunk), this);
621
622 // Drag and drop.
623 gtk_drag_dest_set(window_contents_, static_cast<GtkDestDefaults>(0),
624 NULL, 0, GDK_ACTION_COPY);
625 g_signal_connect(window_contents_, "drag_motion",
626 G_CALLBACK(&OnDragMotionThunk), this);
627 g_signal_connect(window_contents_, "drag_data_received",
628 G_CALLBACK(&OnDragDataReceivedThunk), this);
629 g_signal_connect(window_contents_, "drag_drop",
630 G_CALLBACK(&OnDragDropThunk), this);
631 g_signal_connect(window_contents_, "drag_leave",
632 G_CALLBACK(&OnDragLeaveThunk), this);
633 g_signal_connect(window_contents_, "drag_data_get",
634 G_CALLBACK(&OnDragDataGetThunk), this);
635 g_signal_connect(window_contents_, "drag_end",
636 G_CALLBACK(&OnDragEndThunk), this);
637 g_signal_connect(window_contents_, "drag_failed",
638 G_CALLBACK(&OnDragFailedThunk), this);
639
640 tooltip_manager_.reset(new TooltipManagerGtk(this));
641
642 // Register for tooltips.
643 g_object_set(G_OBJECT(window_contents_), "has-tooltip", TRUE, NULL);
644 g_signal_connect(window_contents_, "query_tooltip",
645 G_CALLBACK(&OnQueryTooltipThunk), this);
646
647 if (type_ == TYPE_CHILD) {
648 if (parent) {
649 SetBounds(bounds);
650 }
651 } else {
652 if (bounds.width() > 0 && bounds.height() > 0)
653 gtk_window_resize(GTK_WINDOW(widget_), bounds.width(), bounds.height());
654 gtk_window_move(GTK_WINDOW(widget_), bounds.x(), bounds.y());
655 }
656 }
657
658 gfx::NativeView WidgetGtk::GetNativeView() const { 502 gfx::NativeView WidgetGtk::GetNativeView() const {
659 return widget_; 503 return widget_;
660 } 504 }
661 505
662 bool WidgetGtk::GetAccelerator(int cmd_id, ui::Accelerator* accelerator) { 506 bool WidgetGtk::GetAccelerator(int cmd_id, ui::Accelerator* accelerator) {
663 NOTIMPLEMENTED(); 507 NOTIMPLEMENTED();
664 return false; 508 return false;
665 } 509 }
666 510
667 Window* WidgetGtk::GetWindow() { 511 Window* WidgetGtk::GetWindow() {
(...skipping 16 matching lines...) Expand all
684 bool send_native_event) { 528 bool send_native_event) {
685 // Send the notification to the delegate. 529 // Send the notification to the delegate.
686 if (ViewsDelegate::views_delegate) 530 if (ViewsDelegate::views_delegate)
687 ViewsDelegate::views_delegate->NotifyAccessibilityEvent(view, event_type); 531 ViewsDelegate::views_delegate->NotifyAccessibilityEvent(view, event_type);
688 532
689 // In the future if we add native GTK accessibility support, the 533 // In the future if we add native GTK accessibility support, the
690 // notification should be sent here. 534 // notification should be sent here.
691 } 535 }
692 536
693 void WidgetGtk::ClearNativeFocus() { 537 void WidgetGtk::ClearNativeFocus() {
694 DCHECK(type_ != TYPE_CHILD); 538 DCHECK(!child_);
695 if (!GetNativeView()) { 539 if (!GetNativeView()) {
696 NOTREACHED(); 540 NOTREACHED();
697 return; 541 return;
698 } 542 }
699 gtk_window_set_focus(GTK_WINDOW(GetNativeView()), NULL); 543 gtk_window_set_focus(GTK_WINDOW(GetNativeView()), NULL);
700 } 544 }
701 545
702 bool WidgetGtk::HandleKeyboardEvent(const KeyEvent& key) { 546 bool WidgetGtk::HandleKeyboardEvent(const KeyEvent& key) {
703 if (!GetFocusManager()) 547 if (!GetFocusManager())
704 return false; 548 return false;
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
767 RemoveExposeHandlerIfExists(child); 611 RemoveExposeHandlerIfExists(child);
768 gulong id = g_signal_connect_after(child, "expose-event", 612 gulong id = g_signal_connect_after(child, "expose-event",
769 G_CALLBACK(&ChildExposeHandler), NULL); 613 G_CALLBACK(&ChildExposeHandler), NULL);
770 g_object_set_data(G_OBJECT(child), kExposeHandlerIdKey, 614 g_object_set_data(G_OBJECT(child), kExposeHandlerIdKey,
771 reinterpret_cast<void*>(id)); 615 reinterpret_cast<void*>(id));
772 } 616 }
773 617
774 //////////////////////////////////////////////////////////////////////////////// 618 ////////////////////////////////////////////////////////////////////////////////
775 // WidgetGtk, NativeWidget implementation: 619 // WidgetGtk, NativeWidget implementation:
776 620
777 void WidgetGtk::SetCreateParams(const CreateParams& params) { 621 void WidgetGtk::InitNativeWidget(const CreateParams& params) {
778 DCHECK(!GetNativeView()); 622 SetCreateParams(params);
779 623
780 // Set non-style attributes. 624 CreateParams modified_params = params;
781 set_delete_on_destroy(params.delete_on_destroy); 625 gfx::NativeView parent = params.parent;
626 if (params.parent_widget) {
627 WidgetGtk* parent_gtk =
628 static_cast<WidgetGtk*>(params.parent_widget->native_widget());
629 modified_params.parent = child_ ? parent_gtk->window_contents()
630 : params.parent_widget->GetNativeView();
631 }
782 632
783 if (params.transparent) 633 if (!child_)
784 MakeTransparent(); 634 ActiveWindowWatcherX::AddObserver(this);
785 if (!params.accept_events)
786 MakeIgnoreEvents();
787 635
788 if (params.type == CreateParams::TYPE_MENU) { 636 // Make container here.
789 GdkEvent* event = gtk_get_current_event(); 637 CreateGtkWidget(modified_params);
790 if (event) { 638 delegate_->OnNativeWidgetCreated();
791 is_mouse_button_pressed_ = event->type == GDK_BUTTON_PRESS || 639
792 event->type == GDK_2BUTTON_PRESS || 640 // Creates input method for toplevel widget after calling
793 event->type == GDK_3BUTTON_PRESS; 641 // delegate_->OnNativeWidgetCreated(), to make sure that focus manager is
794 gdk_event_free(event); 642 // already created at this point.
795 } 643 // TODO(suzhe): Always enable input method when we start to use
644 // RenderWidgetHostViewViews in normal ChromeOS.
645 #if defined(TOUCH_UI) && defined(HAVE_IBUS)
646 if (!child_) {
647 input_method_.reset(new InputMethodIBus(this));
648 #else
649 if (!child_ && NativeTextfieldViews::IsTextfieldViewsEnabled()) {
650 input_method_.reset(new InputMethodGtk(this));
651 #endif
652 input_method_->Init(GetWidget());
653 }
654
655 if (opacity_ != 255)
656 SetOpacity(opacity_);
657
658 // Make sure we receive our motion events.
659
660 // In general we register most events on the parent of all widgets. At a
661 // minimum we need painting to happen on the parent (otherwise painting
662 // doesn't work at all), and similarly we need mouse release events on the
663 // parent as windows don't get mouse releases.
664 gtk_widget_add_events(window_contents_,
665 GDK_ENTER_NOTIFY_MASK |
666 GDK_LEAVE_NOTIFY_MASK |
667 GDK_BUTTON_PRESS_MASK |
668 GDK_BUTTON_RELEASE_MASK |
669 GDK_POINTER_MOTION_MASK |
670 GDK_KEY_PRESS_MASK |
671 GDK_KEY_RELEASE_MASK);
672
673 g_signal_connect_after(G_OBJECT(window_contents_), "size_request",
674 G_CALLBACK(&OnSizeRequestThunk), this);
675 g_signal_connect_after(G_OBJECT(window_contents_), "size_allocate",
676 G_CALLBACK(&OnSizeAllocateThunk), this);
677 gtk_widget_set_app_paintable(window_contents_, true);
678 g_signal_connect(window_contents_, "expose_event",
679 G_CALLBACK(&OnPaintThunk), this);
680 g_signal_connect(window_contents_, "enter_notify_event",
681 G_CALLBACK(&OnEnterNotifyThunk), this);
682 g_signal_connect(window_contents_, "leave_notify_event",
683 G_CALLBACK(&OnLeaveNotifyThunk), this);
684 g_signal_connect(window_contents_, "motion_notify_event",
685 G_CALLBACK(&OnMotionNotifyThunk), this);
686 g_signal_connect(window_contents_, "button_press_event",
687 G_CALLBACK(&OnButtonPressThunk), this);
688 g_signal_connect(window_contents_, "button_release_event",
689 G_CALLBACK(&OnButtonReleaseThunk), this);
690 g_signal_connect(window_contents_, "grab_broken_event",
691 G_CALLBACK(&OnGrabBrokeEventThunk), this);
692 g_signal_connect(window_contents_, "grab_notify",
693 G_CALLBACK(&OnGrabNotifyThunk), this);
694 g_signal_connect(window_contents_, "scroll_event",
695 G_CALLBACK(&OnScrollThunk), this);
696 g_signal_connect(window_contents_, "visibility_notify_event",
697 G_CALLBACK(&OnVisibilityNotifyThunk), this);
698
699 // In order to receive notification when the window is no longer the front
700 // window, we need to install these on the widget.
701 // NOTE: this doesn't work with focus follows mouse.
702 g_signal_connect(widget_, "focus_in_event",
703 G_CALLBACK(&OnFocusInThunk), this);
704 g_signal_connect(widget_, "focus_out_event",
705 G_CALLBACK(&OnFocusOutThunk), this);
706 g_signal_connect(widget_, "destroy",
707 G_CALLBACK(&OnDestroyThunk), this);
708 g_signal_connect(widget_, "show",
709 G_CALLBACK(&OnShowThunk), this);
710 g_signal_connect(widget_, "map",
711 G_CALLBACK(&OnMapThunk), this);
712 g_signal_connect(widget_, "hide",
713 G_CALLBACK(&OnHideThunk), this);
714
715 // Views/FocusManager (re)sets the focus to the root window,
716 // so we need to connect signal handlers to the gtk window.
717 // See views::Views::Focus and views::FocusManager::ClearNativeFocus
718 // for more details.
719 g_signal_connect(widget_, "key_press_event",
720 G_CALLBACK(&OnEventKeyThunk), this);
721 g_signal_connect(widget_, "key_release_event",
722 G_CALLBACK(&OnEventKeyThunk), this);
723
724 // Drag and drop.
725 gtk_drag_dest_set(window_contents_, static_cast<GtkDestDefaults>(0),
726 NULL, 0, GDK_ACTION_COPY);
727 g_signal_connect(window_contents_, "drag_motion",
728 G_CALLBACK(&OnDragMotionThunk), this);
729 g_signal_connect(window_contents_, "drag_data_received",
730 G_CALLBACK(&OnDragDataReceivedThunk), this);
731 g_signal_connect(window_contents_, "drag_drop",
732 G_CALLBACK(&OnDragDropThunk), this);
733 g_signal_connect(window_contents_, "drag_leave",
734 G_CALLBACK(&OnDragLeaveThunk), this);
735 g_signal_connect(window_contents_, "drag_data_get",
736 G_CALLBACK(&OnDragDataGetThunk), this);
737 g_signal_connect(window_contents_, "drag_end",
738 G_CALLBACK(&OnDragEndThunk), this);
739 g_signal_connect(window_contents_, "drag_failed",
740 G_CALLBACK(&OnDragFailedThunk), this);
741
742 tooltip_manager_.reset(new TooltipManagerGtk(this));
743
744 // Register for tooltips.
745 g_object_set(G_OBJECT(window_contents_), "has-tooltip", TRUE, NULL);
746 g_signal_connect(window_contents_, "query_tooltip",
747 G_CALLBACK(&OnQueryTooltipThunk), this);
748
749 if (child_) {
750 if (parent)
751 SetBounds(params.bounds);
752 } else {
753 if (params.bounds.width() > 0 && params.bounds.height() > 0)
754 gtk_window_resize(GTK_WINDOW(widget_), params.bounds.width(),
755 params.bounds.height());
756 gtk_window_move(GTK_WINDOW(widget_), params.bounds.x(), params.bounds.y());
796 } 757 }
797 } 758 }
798 759
799 Widget* WidgetGtk::GetWidget() { 760 Widget* WidgetGtk::GetWidget() {
800 return this; 761 return this;
801 } 762 }
802 763
803 void WidgetGtk::SetNativeWindowProperty(const char* name, void* value) { 764 void WidgetGtk::SetNativeWindowProperty(const char* name, void* value) {
804 g_object_set_data(G_OBJECT(widget_), name, value); 765 g_object_set_data(G_OBJECT(widget_), name, value);
805 } 766 }
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
863 gtk_window_get_size(GTK_WINDOW(widget_), &w, &h); 824 gtk_window_get_size(GTK_WINDOW(widget_), &w, &h);
864 } else { 825 } else {
865 GetWidgetPositionOnScreen(widget_, &x, &y); 826 GetWidgetPositionOnScreen(widget_, &x, &y);
866 w = widget_->allocation.width; 827 w = widget_->allocation.width;
867 h = widget_->allocation.height; 828 h = widget_->allocation.height;
868 } 829 }
869 return gfx::Rect(x, y, w, h); 830 return gfx::Rect(x, y, w, h);
870 } 831 }
871 832
872 void WidgetGtk::SetBounds(const gfx::Rect& bounds) { 833 void WidgetGtk::SetBounds(const gfx::Rect& bounds) {
873 if (type_ == TYPE_CHILD) { 834 if (child_) {
874 GtkWidget* parent = gtk_widget_get_parent(widget_); 835 GtkWidget* parent = gtk_widget_get_parent(widget_);
875 if (GTK_IS_VIEWS_FIXED(parent)) { 836 if (GTK_IS_VIEWS_FIXED(parent)) {
876 WidgetGtk* parent_widget = static_cast<WidgetGtk*>( 837 WidgetGtk* parent_widget = static_cast<WidgetGtk*>(
877 NativeWidget::GetNativeWidgetForNativeView(parent)); 838 NativeWidget::GetNativeWidgetForNativeView(parent));
878 parent_widget->PositionChild(widget_, bounds.x(), bounds.y(), 839 parent_widget->PositionChild(widget_, bounds.x(), bounds.y(),
879 bounds.width(), bounds.height()); 840 bounds.width(), bounds.height());
880 } else { 841 } else {
881 DCHECK(GTK_IS_FIXED(parent)) 842 DCHECK(GTK_IS_FIXED(parent))
882 << "Parent of WidgetGtk has to be Fixed or ViewsFixed"; 843 << "Parent of WidgetGtk has to be Fixed or ViewsFixed";
883 // Just request the size if the parent is not WidgetGtk but plain 844 // Just request the size if the parent is not WidgetGtk but plain
(...skipping 17 matching lines...) Expand all
901 // TODO: this may need to set an initial size if not showing. 862 // TODO: this may need to set an initial size if not showing.
902 // TODO: need to constrain based on screen size. 863 // TODO: need to constrain based on screen size.
903 if (!bounds.IsEmpty()) { 864 if (!bounds.IsEmpty()) {
904 gtk_window_resize(gtk_window, bounds.width(), bounds.height()); 865 gtk_window_resize(gtk_window, bounds.width(), bounds.height());
905 } 866 }
906 gtk_window_move(gtk_window, bounds.x(), bounds.y()); 867 gtk_window_move(gtk_window, bounds.x(), bounds.y());
907 } 868 }
908 } 869 }
909 870
910 void WidgetGtk::SetSize(const gfx::Size& size) { 871 void WidgetGtk::SetSize(const gfx::Size& size) {
911 if (type_ == TYPE_CHILD) { 872 if (child_) {
912 GtkWidget* parent = gtk_widget_get_parent(widget_); 873 GtkWidget* parent = gtk_widget_get_parent(widget_);
913 if (GTK_IS_VIEWS_FIXED(parent)) { 874 if (GTK_IS_VIEWS_FIXED(parent)) {
914 gtk_views_fixed_set_widget_size(widget_, size.width(), size.height()); 875 gtk_views_fixed_set_widget_size(widget_, size.width(), size.height());
915 } else { 876 } else {
916 DCHECK(GTK_IS_FIXED(parent)) 877 DCHECK(GTK_IS_FIXED(parent))
917 << "Parent of WidgetGtk has to be Fixed or ViewsFixed"; 878 << "Parent of WidgetGtk has to be Fixed or ViewsFixed";
918 gtk_widget_set_size_request(widget_, size.width(), size.height()); 879 gtk_widget_set_size_request(widget_, size.width(), size.height());
919 } 880 }
920 } else { 881 } else {
921 if (GTK_WIDGET_MAPPED(widget_)) 882 if (GTK_WIDGET_MAPPED(widget_))
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
977 void WidgetGtk::SetOpacity(unsigned char opacity) { 938 void WidgetGtk::SetOpacity(unsigned char opacity) {
978 opacity_ = opacity; 939 opacity_ = opacity;
979 if (widget_) { 940 if (widget_) {
980 // We can only set the opacity when the widget has been realized. 941 // We can only set the opacity when the widget has been realized.
981 gdk_window_set_opacity(widget_->window, static_cast<gdouble>(opacity) / 942 gdk_window_set_opacity(widget_->window, static_cast<gdouble>(opacity) /
982 static_cast<gdouble>(255)); 943 static_cast<gdouble>(255));
983 } 944 }
984 } 945 }
985 946
986 void WidgetGtk::SetAlwaysOnTop(bool on_top) { 947 void WidgetGtk::SetAlwaysOnTop(bool on_top) {
987 DCHECK(type_ != TYPE_CHILD); 948 DCHECK(!child_);
988 always_on_top_ = on_top; 949 always_on_top_ = on_top;
989 if (widget_) 950 if (widget_)
990 gtk_window_set_keep_above(GTK_WINDOW(widget_), on_top); 951 gtk_window_set_keep_above(GTK_WINDOW(widget_), on_top);
991 } 952 }
992 953
993 bool WidgetGtk::IsVisible() const { 954 bool WidgetGtk::IsVisible() const {
994 return GTK_WIDGET_VISIBLE(widget_); 955 return GTK_WIDGET_VISIBLE(widget_);
995 } 956 }
996 957
997 bool WidgetGtk::IsActive() const { 958 bool WidgetGtk::IsActive() const {
998 DCHECK(type_ != TYPE_CHILD); 959 DCHECK(!child_);
999 return is_active_; 960 return is_active_;
1000 } 961 }
1001 962
1002 bool WidgetGtk::IsAccessibleWidget() const { 963 bool WidgetGtk::IsAccessibleWidget() const {
1003 return false; 964 return false;
1004 } 965 }
1005 966
1006 bool WidgetGtk::ContainsNativeView(gfx::NativeView native_view) const { 967 bool WidgetGtk::ContainsNativeView(gfx::NativeView native_view) const {
1007 // TODO(port) See implementation in WidgetWin::ContainsNativeView. 968 // TODO(port) See implementation in WidgetWin::ContainsNativeView.
1008 NOTREACHED() << "WidgetGtk::ContainsNativeView is not implemented."; 969 NOTREACHED() << "WidgetGtk::ContainsNativeView is not implemented.";
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1041 } 1002 }
1042 1003
1043 //////////////////////////////////////////////////////////////////////////////// 1004 ////////////////////////////////////////////////////////////////////////////////
1044 // WidgetGtk, protected: 1005 // WidgetGtk, protected:
1045 1006
1046 void WidgetGtk::OnSizeRequest(GtkWidget* widget, GtkRequisition* requisition) { 1007 void WidgetGtk::OnSizeRequest(GtkWidget* widget, GtkRequisition* requisition) {
1047 // Do only return the preferred size for child windows. GtkWindow interprets 1008 // Do only return the preferred size for child windows. GtkWindow interprets
1048 // the requisition as a minimum size for top level windows, returning a 1009 // the requisition as a minimum size for top level windows, returning a
1049 // preferred size for these would prevents us from setting smaller window 1010 // preferred size for these would prevents us from setting smaller window
1050 // sizes. 1011 // sizes.
1051 if (type_ == TYPE_CHILD) { 1012 if (child_) {
1052 gfx::Size size(GetRootView()->GetPreferredSize()); 1013 gfx::Size size(GetRootView()->GetPreferredSize());
1053 requisition->width = size.width(); 1014 requisition->width = size.width();
1054 requisition->height = size.height(); 1015 requisition->height = size.height();
1055 } 1016 }
1056 } 1017 }
1057 1018
1058 void WidgetGtk::OnSizeAllocate(GtkWidget* widget, GtkAllocation* allocation) { 1019 void WidgetGtk::OnSizeAllocate(GtkWidget* widget, GtkAllocation* allocation) {
1059 // See comment next to size_ as to why we do this. Also note, it's tempting 1020 // See comment next to size_ as to why we do this. Also note, it's tempting
1060 // to put this in the static method so subclasses don't need to worry about 1021 // to put this in the static method so subclasses don't need to worry about
1061 // it, but if a subclasses needs to set a shape then they need to always 1022 // it, but if a subclasses needs to set a shape then they need to always
1062 // reset the shape in this method regardless of whether the size changed. 1023 // reset the shape in this method regardless of whether the size changed.
1063 gfx::Size new_size(allocation->width, allocation->height); 1024 gfx::Size new_size(allocation->width, allocation->height);
1064 if (new_size == size_) 1025 if (new_size == size_)
1065 return; 1026 return;
1066 size_ = new_size; 1027 size_ = new_size;
1067 delegate_->OnSizeChanged(size_); 1028 delegate_->OnSizeChanged(size_);
1068 } 1029 }
1069 1030
1070 gboolean WidgetGtk::OnPaint(GtkWidget* widget, GdkEventExpose* event) { 1031 gboolean WidgetGtk::OnPaint(GtkWidget* widget, GdkEventExpose* event) {
1071 if (transparent_ && type_ == TYPE_CHILD) { 1032 if (transparent_ && child_) {
1072 // Clear the background before drawing any view and native components. 1033 // Clear the background before drawing any view and native components.
1073 DrawTransparentBackground(widget, event); 1034 DrawTransparentBackground(widget, event);
1074 if (!CompositePainter::IsComposited(widget_) && 1035 if (!CompositePainter::IsComposited(widget_) &&
1075 gdk_screen_is_composited(gdk_screen_get_default())) { 1036 gdk_screen_is_composited(gdk_screen_get_default())) {
1076 // Let the parent draw the content only after something is drawn on 1037 // Let the parent draw the content only after something is drawn on
1077 // the widget. 1038 // the widget.
1078 CompositePainter::SetComposited(widget_); 1039 CompositePainter::SetComposited(widget_);
1079 } 1040 }
1080 } 1041 }
1081 1042
(...skipping 12 matching lines...) Expand all
1094 } 1055 }
1095 1056
1096 gfx::CanvasSkiaPaint canvas(event); 1057 gfx::CanvasSkiaPaint canvas(event);
1097 if (!canvas.is_empty()) { 1058 if (!canvas.is_empty()) {
1098 canvas.set_composite_alpha(is_transparent()); 1059 canvas.set_composite_alpha(is_transparent());
1099 delegate_->OnNativeWidgetPaint(&canvas); 1060 delegate_->OnNativeWidgetPaint(&canvas);
1100 } 1061 }
1101 1062
1102 if (!painted_) { 1063 if (!painted_) {
1103 painted_ = true; 1064 painted_ = true;
1104 if (type_ != TYPE_CHILD) 1065 if (!child_)
1105 UpdateFreezeUpdatesProperty(GTK_WINDOW(widget_), false /* remove */); 1066 UpdateFreezeUpdatesProperty(GTK_WINDOW(widget_), false /* remove */);
1106 } 1067 }
1107 return false; // False indicates other widgets should get the event as well. 1068 return false; // False indicates other widgets should get the event as well.
1108 } 1069 }
1109 1070
1110 void WidgetGtk::OnDragDataGet(GtkWidget* widget, 1071 void WidgetGtk::OnDragDataGet(GtkWidget* widget,
1111 GdkDragContext* context, 1072 GdkDragContext* context,
1112 GtkSelectionData* data, 1073 GtkSelectionData* data,
1113 guint info, 1074 guint info,
1114 guint time) { 1075 guint time) {
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
1255 return delegate_->OnMouseEvent(mouse_event); 1216 return delegate_->OnMouseEvent(mouse_event);
1256 } 1217 }
1257 1218
1258 gboolean WidgetGtk::OnFocusIn(GtkWidget* widget, GdkEventFocus* event) { 1219 gboolean WidgetGtk::OnFocusIn(GtkWidget* widget, GdkEventFocus* event) {
1259 if (has_focus_) 1220 if (has_focus_)
1260 return false; // This is the second focus-in event in a row, ignore it. 1221 return false; // This is the second focus-in event in a row, ignore it.
1261 has_focus_ = true; 1222 has_focus_ = true;
1262 1223
1263 should_handle_menu_key_release_ = false; 1224 should_handle_menu_key_release_ = false;
1264 1225
1265 if (type_ == TYPE_CHILD) 1226 if (child_)
1266 return false; 1227 return false;
1267 1228
1268 // Only top-level Widget should have an InputMethod instance. 1229 // Only top-level Widget should have an InputMethod instance.
1269 if (input_method_.get()) 1230 if (input_method_.get())
1270 input_method_->OnFocus(); 1231 input_method_->OnFocus();
1271 1232
1272 // See description of got_initial_focus_in_ for details on this. 1233 // See description of got_initial_focus_in_ for details on this.
1273 if (!got_initial_focus_in_) { 1234 if (!got_initial_focus_in_) {
1274 got_initial_focus_in_ = true; 1235 got_initial_focus_in_ = true;
1275 SetInitialFocus(); 1236 SetInitialFocus();
1276 } 1237 }
1277 return false; 1238 return false;
1278 } 1239 }
1279 1240
1280 gboolean WidgetGtk::OnFocusOut(GtkWidget* widget, GdkEventFocus* event) { 1241 gboolean WidgetGtk::OnFocusOut(GtkWidget* widget, GdkEventFocus* event) {
1281 if (!has_focus_) 1242 if (!has_focus_)
1282 return false; // This is the second focus-out event in a row, ignore it. 1243 return false; // This is the second focus-out event in a row, ignore it.
1283 has_focus_ = false; 1244 has_focus_ = false;
1284 1245
1285 if (type_ == TYPE_CHILD) 1246 if (child_)
1286 return false; 1247 return false;
1287 1248
1288 // Only top-level Widget should have an InputMethod instance. 1249 // Only top-level Widget should have an InputMethod instance.
1289 if (input_method_.get()) 1250 if (input_method_.get())
1290 input_method_->OnBlur(); 1251 input_method_->OnBlur();
1291 return false; 1252 return false;
1292 } 1253 }
1293 1254
1294 gboolean WidgetGtk::OnEventKey(GtkWidget* widget, GdkEventKey* event) { 1255 gboolean WidgetGtk::OnEventKey(GtkWidget* widget, GdkEventKey* event) {
1295 KeyEvent key(reinterpret_cast<NativeEvent>(event)); 1256 KeyEvent key(reinterpret_cast<NativeEvent>(event));
(...skipping 25 matching lines...) Expand all
1321 } 1282 }
1322 1283
1323 void WidgetGtk::OnGrabNotify(GtkWidget* widget, gboolean was_grabbed) { 1284 void WidgetGtk::OnGrabNotify(GtkWidget* widget, gboolean was_grabbed) {
1324 if (!window_contents_) 1285 if (!window_contents_)
1325 return; // Grab broke after window destroyed, don't try processing it. 1286 return; // Grab broke after window destroyed, don't try processing it.
1326 gtk_grab_remove(window_contents_); 1287 gtk_grab_remove(window_contents_);
1327 HandleGtkGrabBroke(); 1288 HandleGtkGrabBroke();
1328 } 1289 }
1329 1290
1330 void WidgetGtk::OnDestroy(GtkWidget* object) { 1291 void WidgetGtk::OnDestroy(GtkWidget* object) {
1292 if (!child_)
1293 ActiveWindowWatcherX::RemoveObserver(this);
1331 // Note that this handler is hooked to GtkObject::destroy. 1294 // Note that this handler is hooked to GtkObject::destroy.
1332 // NULL out pointers here since we might still be in an observerer list 1295 // NULL out pointers here since we might still be in an observerer list
1333 // until delstion happens. 1296 // until delstion happens.
1334 widget_ = window_contents_ = NULL; 1297 widget_ = window_contents_ = NULL;
1335 if (delete_on_destroy_) { 1298 if (delete_on_destroy_) {
1336 // Delays the deletion of this WidgetGtk as we want its children to have 1299 // Delays the deletion of this WidgetGtk as we want its children to have
1337 // access to it when destroyed. 1300 // access to it when destroyed.
1338 MessageLoop::current()->DeleteSoon(FROM_HERE, this); 1301 MessageLoop::current()->DeleteSoon(FROM_HERE, this);
1339 } 1302 }
1340 } 1303 }
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1407 // always consumes the key event and send it back to us later by calling 1370 // always consumes the key event and send it back to us later by calling
1408 // HandleKeyboardEvent() directly, if it's not handled by webkit. 1371 // HandleKeyboardEvent() directly, if it's not handled by webkit.
1409 if (!handled) 1372 if (!handled)
1410 handled = HandleKeyboardEvent(key); 1373 handled = HandleKeyboardEvent(key);
1411 1374
1412 // Dispatch the key event for bindings processing. 1375 // Dispatch the key event for bindings processing.
1413 if (!handled && event && GTK_IS_WINDOW(widget_)) 1376 if (!handled && event && GTK_IS_WINDOW(widget_))
1414 gtk_bindings_activate_event(GTK_OBJECT(widget_), event); 1377 gtk_bindings_activate_event(GTK_OBJECT(widget_), event);
1415 } 1378 }
1416 1379
1380 void WidgetGtk::SetCreateParams(const CreateParams& params) {
1381 DCHECK(!GetNativeView());
1382
1383 delete_on_destroy_ = params.delete_on_destroy;
1384 child_ = params.child;
1385
1386 if (params.transparent)
1387 MakeTransparent();
1388 if (!params.accept_events && !child_)
1389 ignore_events_ = true;
1390
1391 if (params.type == CreateParams::TYPE_MENU) {
1392 GdkEvent* event = gtk_get_current_event();
1393 if (event) {
1394 is_mouse_button_pressed_ = event->type == GDK_BUTTON_PRESS ||
1395 event->type == GDK_2BUTTON_PRESS ||
1396 event->type == GDK_3BUTTON_PRESS;
1397 gdk_event_free(event);
1398 }
1399 }
1400 }
1401
1417 gboolean WidgetGtk::OnWindowPaint(GtkWidget* widget, GdkEventExpose* event) { 1402 gboolean WidgetGtk::OnWindowPaint(GtkWidget* widget, GdkEventExpose* event) {
1418 // Clear the background to be totally transparent. We don't need to 1403 // Clear the background to be totally transparent. We don't need to
1419 // paint the root view here as that is done by OnPaint. 1404 // paint the root view here as that is done by OnPaint.
1420 DCHECK(transparent_); 1405 DCHECK(transparent_);
1421 DrawTransparentBackground(widget, event); 1406 DrawTransparentBackground(widget, event);
1422 // The Keyboard layout view has a renderer that covers the entire 1407 // The Keyboard layout view has a renderer that covers the entire
1423 // window, which prevents OnPaint from being called on window_contents_, 1408 // window, which prevents OnPaint from being called on window_contents_,
1424 // so we need to remove the FREEZE_UPDATES property here. 1409 // so we need to remove the FREEZE_UPDATES property here.
1425 if (!painted_) { 1410 if (!painted_) {
1426 painted_ = true; 1411 painted_ = true;
1427 UpdateFreezeUpdatesProperty(GTK_WINDOW(widget_), false /* remove */); 1412 UpdateFreezeUpdatesProperty(GTK_WINDOW(widget_), false /* remove */);
1428 } 1413 }
1429 return false; 1414 return false;
1430 } 1415 }
1431 1416
1432 void WidgetGtk::OnChildExpose(GtkWidget* child) { 1417 void WidgetGtk::OnChildExpose(GtkWidget* child) {
1433 DCHECK(type_ != TYPE_CHILD); 1418 DCHECK(!child_);
1434 if (!painted_) { 1419 if (!painted_) {
1435 painted_ = true; 1420 painted_ = true;
1436 UpdateFreezeUpdatesProperty(GTK_WINDOW(widget_), false /* remove */); 1421 UpdateFreezeUpdatesProperty(GTK_WINDOW(widget_), false /* remove */);
1437 } 1422 }
1438 RemoveExposeHandlerIfExists(child); 1423 RemoveExposeHandlerIfExists(child);
1439 } 1424 }
1440 1425
1441 // static 1426 // static
1442 gboolean WidgetGtk::ChildExposeHandler(GtkWidget* widget, 1427 gboolean WidgetGtk::ChildExposeHandler(GtkWidget* widget,
1443 GdkEventExpose* event) { 1428 GdkEventExpose* event) {
(...skipping 13 matching lines...) Expand all
1457 while (parent) { 1442 while (parent) {
1458 WidgetGtk* widget_gtk = static_cast<WidgetGtk*>( 1443 WidgetGtk* widget_gtk = static_cast<WidgetGtk*>(
1459 NativeWidget::GetNativeWidgetForNativeView(parent)); 1444 NativeWidget::GetNativeWidgetForNativeView(parent));
1460 if (widget_gtk && widget_gtk->is_window_) 1445 if (widget_gtk && widget_gtk->is_window_)
1461 return static_cast<WindowGtk*>(widget_gtk); 1446 return static_cast<WindowGtk*>(widget_gtk);
1462 parent = gtk_widget_get_parent(parent); 1447 parent = gtk_widget_get_parent(parent);
1463 } 1448 }
1464 return NULL; 1449 return NULL;
1465 } 1450 }
1466 1451
1467 void WidgetGtk::CreateGtkWidget(GtkWidget* parent, const gfx::Rect& bounds) { 1452 void WidgetGtk::CreateGtkWidget(const CreateParams& params) {
1468 // We turn off double buffering for two reasons: 1453 // We turn off double buffering for two reasons:
1469 // 1. We draw to a canvas then composite to the screen, which means we're 1454 // 1. We draw to a canvas then composite to the screen, which means we're
1470 // doing our own double buffering already. 1455 // doing our own double buffering already.
1471 // 2. GTKs double buffering clips to the dirty region. RootView occasionally 1456 // 2. GTKs double buffering clips to the dirty region. RootView occasionally
1472 // needs to expand the paint region (see RootView::OnPaint). This means 1457 // needs to expand the paint region (see RootView::OnPaint). This means
1473 // that if we use GTK's double buffering and we tried to expand the dirty 1458 // that if we use GTK's double buffering and we tried to expand the dirty
1474 // region, it wouldn't get painted. 1459 // region, it wouldn't get painted.
1475 if (type_ == TYPE_CHILD) { 1460 if (child_) {
1476 window_contents_ = widget_ = gtk_views_fixed_new(); 1461 window_contents_ = widget_ = gtk_views_fixed_new();
1477 gtk_widget_set_name(widget_, "views-gtkwidget-child-fixed"); 1462 gtk_widget_set_name(widget_, "views-gtkwidget-child-fixed");
1478 if (!is_double_buffered_) 1463 if (!is_double_buffered_)
1479 GTK_WIDGET_UNSET_FLAGS(widget_, GTK_DOUBLE_BUFFERED); 1464 GTK_WIDGET_UNSET_FLAGS(widget_, GTK_DOUBLE_BUFFERED);
1480 gtk_fixed_set_has_window(GTK_FIXED(widget_), true); 1465 gtk_fixed_set_has_window(GTK_FIXED(widget_), true);
1481 if (!parent && !null_parent_) { 1466 if (!params.parent && !null_parent_) {
1482 GtkWidget* popup = gtk_window_new(GTK_WINDOW_POPUP); 1467 GtkWidget* popup = gtk_window_new(GTK_WINDOW_POPUP);
1483 null_parent_ = gtk_fixed_new(); 1468 null_parent_ = gtk_fixed_new();
1484 gtk_widget_set_name(widget_, "views-gtkwidget-null-parent"); 1469 gtk_widget_set_name(widget_, "views-gtkwidget-null-parent");
1485 gtk_container_add(GTK_CONTAINER(popup), null_parent_); 1470 gtk_container_add(GTK_CONTAINER(popup), null_parent_);
1486 gtk_widget_realize(null_parent_); 1471 gtk_widget_realize(null_parent_);
1487 } 1472 }
1488 if (transparent_) { 1473 if (transparent_) {
1489 // transparency has to be configured before widget is realized. 1474 // transparency has to be configured before widget is realized.
1490 DCHECK(parent) << "Transparent widget must have parent when initialized"; 1475 DCHECK(params.parent) <<
1491 ConfigureWidgetForTransparentBackground(parent); 1476 "Transparent widget must have parent when initialized";
1477 ConfigureWidgetForTransparentBackground(params.parent);
1492 } 1478 }
1493 gtk_container_add(GTK_CONTAINER(parent ? parent : null_parent_), widget_); 1479 gtk_container_add(
1480 GTK_CONTAINER(params.parent ? params.parent : null_parent_), widget_);
1494 gtk_widget_realize(widget_); 1481 gtk_widget_realize(widget_);
1495 if (transparent_) { 1482 if (transparent_) {
1496 // The widget has to be realized to set composited flag. 1483 // The widget has to be realized to set composited flag.
1497 // I tried "realize" signal to set this flag, but it did not work 1484 // I tried "realize" signal to set this flag, but it did not work
1498 // when the top level is popup. 1485 // when the top level is popup.
1499 DCHECK(GTK_WIDGET_REALIZED(widget_)); 1486 DCHECK(GTK_WIDGET_REALIZED(widget_));
1500 gdk_window_set_composited(widget_->window, true); 1487 gdk_window_set_composited(widget_->window, true);
1501 } 1488 }
1502 if (parent && !bounds.size().IsEmpty()) { 1489 if (params.parent && !params.bounds.size().IsEmpty()) {
1503 // Make sure that an widget is given it's initial size before 1490 // Make sure that an widget is given it's initial size before
1504 // we're done initializing, to take care of some potential 1491 // we're done initializing, to take care of some potential
1505 // corner cases when programmatically arranging hierarchies as 1492 // corner cases when programmatically arranging hierarchies as
1506 // seen in 1493 // seen in
1507 // http://code.google.com/p/chromium-os/issues/detail?id=5987 1494 // http://code.google.com/p/chromium-os/issues/detail?id=5987
1508 1495
1509 // This can't be done without a parent present, or stale data 1496 // This can't be done without a parent present, or stale data
1510 // might show up on the screen as seen in 1497 // might show up on the screen as seen in
1511 // http://code.google.com/p/chromium/issues/detail?id=53870 1498 // http://code.google.com/p/chromium/issues/detail?id=53870
1512 GtkAllocation alloc = { 0, 0, bounds.width(), bounds.height() }; 1499 GtkAllocation alloc =
1500 { 0, 0, params.bounds.width(), params.bounds.height() };
1513 gtk_widget_size_allocate(widget_, &alloc); 1501 gtk_widget_size_allocate(widget_, &alloc);
1514 } 1502 }
1515 } else { 1503 } else {
1516 // Use our own window class to override GtkWindow's move_focus method. 1504 // Use our own window class to override GtkWindow's move_focus method.
1517 widget_ = gtk_views_window_new( 1505 widget_ = gtk_views_window_new(
1518 (type_ == TYPE_WINDOW || type_ == TYPE_DECORATED_WINDOW) ? 1506 params.type == CreateParams::TYPE_WINDOW ? GTK_WINDOW_TOPLEVEL
1519 GTK_WINDOW_TOPLEVEL : GTK_WINDOW_POPUP); 1507 : GTK_WINDOW_POPUP);
1520 gtk_widget_set_name(widget_, "views-gtkwidget-window"); 1508 gtk_widget_set_name(widget_, "views-gtkwidget-window");
1521 if (transient_to_parent_) 1509 if (transient_to_parent_) {
1522 gtk_window_set_transient_for(GTK_WINDOW(widget_), GTK_WINDOW(parent)); 1510 gtk_window_set_transient_for(GTK_WINDOW(widget_),
1511 GTK_WINDOW(params.parent));
1512 }
1523 GTK_WIDGET_UNSET_FLAGS(widget_, GTK_DOUBLE_BUFFERED); 1513 GTK_WIDGET_UNSET_FLAGS(widget_, GTK_DOUBLE_BUFFERED);
1524 1514
1525 // Gtk determines the size for windows based on the requested size of the 1515 // Gtk determines the size for windows based on the requested size of the
1526 // child. For WidgetGtk the child is a fixed. If the fixed ends up with a 1516 // child. For WidgetGtk the child is a fixed. If the fixed ends up with a
1527 // child widget it's possible the child widget will drive the requested size 1517 // child widget it's possible the child widget will drive the requested size
1528 // of the widget, which we don't want. We explicitly set a value of 1x1 here 1518 // of the widget, which we don't want. We explicitly set a value of 1x1 here
1529 // so that gtk doesn't attempt to resize the window if we end up with a 1519 // so that gtk doesn't attempt to resize the window if we end up with a
1530 // situation where the requested size of a child of the fixed is greater 1520 // situation where the requested size of a child of the fixed is greater
1531 // than the size of the window. By setting the size in this manner we're 1521 // than the size of the window. By setting the size in this manner we're
1532 // also allowing users of WidgetGtk to change the requested size at any 1522 // also allowing users of WidgetGtk to change the requested size at any
1533 // time. 1523 // time.
1534 gtk_widget_set_size_request(widget_, 1, 1); 1524 gtk_widget_set_size_request(widget_, 1, 1);
1535 1525
1536 if (!bounds.size().IsEmpty()) { 1526 if (!params.bounds.size().IsEmpty()) {
1537 // When we realize the window, the window manager is given a size. If we 1527 // When we realize the window, the window manager is given a size. If we
1538 // don't specify a size before then GTK defaults to 200x200. Specify 1528 // don't specify a size before then GTK defaults to 200x200. Specify
1539 // a size now so that the window manager sees the requested size. 1529 // a size now so that the window manager sees the requested size.
1540 GtkAllocation alloc = { 0, 0, bounds.width(), bounds.height() }; 1530 GtkAllocation alloc =
1531 { 0, 0, params.bounds.width(), params.bounds.height() };
1541 gtk_widget_size_allocate(widget_, &alloc); 1532 gtk_widget_size_allocate(widget_, &alloc);
1542 } 1533 }
1543 if (type_ != TYPE_DECORATED_WINDOW) { 1534 gtk_window_set_decorated(GTK_WINDOW(widget_), false);
1544 gtk_window_set_decorated(GTK_WINDOW(widget_), false); 1535 // We'll take care of positioning our window.
1545 // We'll take care of positioning our window. 1536 gtk_window_set_position(GTK_WINDOW(widget_), GTK_WIN_POS_NONE);
1546 gtk_window_set_position(GTK_WINDOW(widget_), GTK_WIN_POS_NONE);
1547 }
1548 1537
1549 window_contents_ = gtk_views_fixed_new(); 1538 window_contents_ = gtk_views_fixed_new();
1550 gtk_widget_set_name(window_contents_, "views-gtkwidget-window-fixed"); 1539 gtk_widget_set_name(window_contents_, "views-gtkwidget-window-fixed");
1551 if (!is_double_buffered_) 1540 if (!is_double_buffered_)
1552 GTK_WIDGET_UNSET_FLAGS(window_contents_, GTK_DOUBLE_BUFFERED); 1541 GTK_WIDGET_UNSET_FLAGS(window_contents_, GTK_DOUBLE_BUFFERED);
1553 gtk_fixed_set_has_window(GTK_FIXED(window_contents_), true); 1542 gtk_fixed_set_has_window(GTK_FIXED(window_contents_), true);
1554 gtk_container_add(GTK_CONTAINER(widget_), window_contents_); 1543 gtk_container_add(GTK_CONTAINER(widget_), window_contents_);
1555 gtk_widget_show(window_contents_); 1544 gtk_widget_show(window_contents_);
1556 g_object_set_data(G_OBJECT(window_contents_), kNativeWidgetKey, 1545 g_object_set_data(G_OBJECT(window_contents_), kNativeWidgetKey,
1557 static_cast<Widget*>(this)); 1546 static_cast<Widget*>(this));
(...skipping 17 matching lines...) Expand all
1575 GdkColormap* rgba_colormap = 1564 GdkColormap* rgba_colormap =
1576 gdk_screen_get_rgba_colormap(gtk_widget_get_screen(widget_)); 1565 gdk_screen_get_rgba_colormap(gtk_widget_get_screen(widget_));
1577 if (!rgba_colormap) { 1566 if (!rgba_colormap) {
1578 transparent_ = false; 1567 transparent_ = false;
1579 return; 1568 return;
1580 } 1569 }
1581 // To make the background transparent we need to install the RGBA colormap 1570 // To make the background transparent we need to install the RGBA colormap
1582 // on both the window and fixed. In addition we need to make sure no 1571 // on both the window and fixed. In addition we need to make sure no
1583 // decorations are drawn. The last bit is to make sure the widget doesn't 1572 // decorations are drawn. The last bit is to make sure the widget doesn't
1584 // attempt to draw a pixmap in it's background. 1573 // attempt to draw a pixmap in it's background.
1585 if (type_ != TYPE_CHILD) { 1574 if (!child_) {
1586 DCHECK(parent == NULL); 1575 DCHECK(parent == NULL);
1587 gtk_widget_set_colormap(widget_, rgba_colormap); 1576 gtk_widget_set_colormap(widget_, rgba_colormap);
1588 gtk_widget_set_app_paintable(widget_, true); 1577 gtk_widget_set_app_paintable(widget_, true);
1589 g_signal_connect(widget_, "expose_event", 1578 g_signal_connect(widget_, "expose_event",
1590 G_CALLBACK(&OnWindowPaintThunk), this); 1579 G_CALLBACK(&OnWindowPaintThunk), this);
1591 gtk_widget_realize(widget_); 1580 gtk_widget_realize(widget_);
1592 gdk_window_set_decorations(widget_->window, 1581 gdk_window_set_decorations(widget_->window,
1593 static_cast<GdkWMDecoration>(0)); 1582 static_cast<GdkWMDecoration>(0));
1594 } else { 1583 } else {
1595 DCHECK(parent); 1584 DCHECK(parent);
(...skipping 29 matching lines...) Expand all
1625 cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR); 1614 cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
1626 gdk_cairo_region(cr, event->region); 1615 gdk_cairo_region(cr, event->region);
1627 cairo_fill(cr); 1616 cairo_fill(cr);
1628 cairo_destroy(cr); 1617 cairo_destroy(cr);
1629 } 1618 }
1630 1619
1631 //////////////////////////////////////////////////////////////////////////////// 1620 ////////////////////////////////////////////////////////////////////////////////
1632 // Widget, public: 1621 // Widget, public:
1633 1622
1634 // static 1623 // static
1635 Widget* Widget::CreateWidget(const CreateParams& params) { 1624 Widget* Widget::CreateWidget() {
1636 // TODO(beng): coalesce with CreateParams::Type. 1625 return new WidgetGtk();
1637 WidgetGtk::Type widget_gtk_type = WidgetGtk::TYPE_DECORATED_WINDOW;
1638 switch (params.type) {
1639 case CreateParams::TYPE_CONTROL:
1640 widget_gtk_type = WidgetGtk::TYPE_CHILD;
1641 break;
1642 case CreateParams::TYPE_MENU:
1643 widget_gtk_type = WidgetGtk::TYPE_POPUP;
1644 break;
1645 case CreateParams::TYPE_POPUP:
1646 widget_gtk_type = WidgetGtk::TYPE_POPUP;
1647 break;
1648 case CreateParams::TYPE_WINDOW:
1649 widget_gtk_type = WidgetGtk::TYPE_DECORATED_WINDOW;
1650 break;
1651 default:
1652 NOTREACHED();
1653 break;
1654 }
1655
1656 WidgetGtk* widget = new WidgetGtk(widget_gtk_type);
1657 widget->SetCreateParams(params);
1658 return widget;
1659 } 1626 }
1660 1627
1661 // static 1628 // static
1662 void Widget::NotifyLocaleChanged() { 1629 void Widget::NotifyLocaleChanged() {
1663 GList *window_list = gtk_window_list_toplevels(); 1630 GList *window_list = gtk_window_list_toplevels();
1664 for (GList* element = window_list; element; element = g_list_next(element)) { 1631 for (GList* element = window_list; element; element = g_list_next(element)) {
1665 NativeWidget* native_widget = 1632 NativeWidget* native_widget =
1666 NativeWidget::GetNativeWidgetForNativeWindow(GTK_WINDOW(element->data)); 1633 NativeWidget::GetNativeWidgetForNativeWindow(GTK_WINDOW(element->data));
1667 if (native_widget) 1634 if (native_widget)
1668 native_widget->GetWidget()->LocaleChanged(); 1635 native_widget->GetWidget()->LocaleChanged();
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
1745 1712
1746 NativeWidget* native_widget = GetNativeWidgetForNativeView(native_view); 1713 NativeWidget* native_widget = GetNativeWidgetForNativeView(native_view);
1747 if (native_widget) 1714 if (native_widget)
1748 children->insert(native_widget); 1715 children->insert(native_widget);
1749 gtk_container_foreach(GTK_CONTAINER(native_view), 1716 gtk_container_foreach(GTK_CONTAINER(native_view),
1750 EnumerateChildWidgetsForNativeWidgets, 1717 EnumerateChildWidgetsForNativeWidgets,
1751 reinterpret_cast<gpointer>(children)); 1718 reinterpret_cast<gpointer>(children));
1752 } 1719 }
1753 1720
1754 } // namespace views 1721 } // namespace views
OLDNEW
« no previous file with comments | « views/widget/widget_gtk.h ('k') | views/widget/widget_win.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698