diff options
Diffstat (limited to 'views')
-rw-r--r-- | views/controls/button/native_button_gtk.cc | 8 | ||||
-rw-r--r-- | views/controls/button/native_button_gtk.h | 2 | ||||
-rw-r--r-- | views/controls/native/native_view_host_gtk.cc | 66 | ||||
-rw-r--r-- | views/controls/native/native_view_host_gtk.h | 14 | ||||
-rw-r--r-- | views/widget/widget_gtk.cc | 103 | ||||
-rw-r--r-- | views/widget/widget_gtk.h | 32 |
6 files changed, 114 insertions, 111 deletions
diff --git a/views/controls/button/native_button_gtk.cc b/views/controls/button/native_button_gtk.cc index c97d1e0..1680019 100644 --- a/views/controls/button/native_button_gtk.cc +++ b/views/controls/button/native_button_gtk.cc @@ -83,7 +83,7 @@ gfx::Size NativeButtonGtk::GetPreferredSize() { void NativeButtonGtk::CreateNativeControl() { GtkWidget* widget = gtk_button_new(); g_signal_connect(G_OBJECT(widget), "clicked", - G_CALLBACK(CallClicked), NULL); + G_CALLBACK(CallClicked), this); NativeControlCreated(widget); } @@ -96,10 +96,8 @@ void NativeButtonGtk::NativeControlCreated(GtkWidget* widget) { } // static -void NativeButtonGtk::CallClicked(GtkButton* widget) { - View* view = NativeViewHostGtk::GetViewForNative(GTK_WIDGET(widget)); - if (view) - static_cast<NativeButtonGtk*>(view)->OnClicked(); +void NativeButtonGtk::CallClicked(GtkButton* widget, NativeButtonGtk* button) { + button->OnClicked(); } void NativeButtonGtk::OnClicked() { diff --git a/views/controls/button/native_button_gtk.h b/views/controls/button/native_button_gtk.h index e719202..6c3f600 100644 --- a/views/controls/button/native_button_gtk.h +++ b/views/controls/button/native_button_gtk.h @@ -36,7 +36,7 @@ class NativeButtonGtk : public NativeControlGtk, public NativeButtonWrapper { virtual bool IsCheckbox() const { return false; } private: - static void CallClicked(GtkButton* widget); + static void CallClicked(GtkButton* widget, NativeButtonGtk* button); // Invoked when the user clicks on the button. void OnClicked(); diff --git a/views/controls/native/native_view_host_gtk.cc b/views/controls/native/native_view_host_gtk.cc index 7f59144..6fa7325 100644 --- a/views/controls/native/native_view_host_gtk.cc +++ b/views/controls/native/native_view_host_gtk.cc @@ -24,47 +24,21 @@ NativeViewHostGtk::NativeViewHostGtk(NativeViewHost* host) NativeViewHostGtk::~NativeViewHostGtk() { } -// static -View* NativeViewHostGtk::GetViewForNative(GtkWidget* widget) { - gpointer user_data = g_object_get_data(G_OBJECT(widget), "chrome-view"); - return static_cast<View*>(user_data); -} - -// static -void NativeViewHostGtk::SetViewForNative(GtkWidget* widget, View* view) { - g_object_set_data(G_OBJECT(widget), "chrome-view", view); -} - //////////////////////////////////////////////////////////////////////////////// // NativeViewHostGtk, NativeViewHostWrapper implementation: void NativeViewHostGtk::NativeViewAttached() { DCHECK(host_->native_view()); - GtkWidget* current_parent = gtk_widget_get_parent(host_->native_view()); - GtkWidget* new_parent = host_->GetWidget()->GetNativeView(); - // Only adjust the parent if the parent actually changed. - if (current_parent != new_parent) { - // First hide the new window. We don't want anything to draw (like sub-hwnd - // borders), when we change the parent below. - gtk_widget_hide(host_->native_view()); - - if (current_parent) { - gtk_container_remove(GTK_CONTAINER(current_parent), - host_->native_view()); - } - - // Adds a mapping between the GtkWidget and us. - SetViewForNative(host_->native_view(), host_); - - if (!destroy_signal_id_) { - destroy_signal_id_ = g_signal_connect(G_OBJECT(host_->native_view()), - "destroy", G_CALLBACK(CallDestroy), - NULL); - } + if (gtk_widget_get_parent(host_->native_view())) + GetHostWidget()->ReparentChild(host_->native_view()); + else + GetHostWidget()->AddChild(host_->native_view()); - // Set the parent. - static_cast<WidgetGtk*>(host_->GetWidget())->AddChild(host_->native_view()); + if (!destroy_signal_id_) { + destroy_signal_id_ = g_signal_connect(G_OBJECT(host_->native_view()), + "destroy", G_CALLBACK(CallDestroy), + this); } // Always layout though. @@ -88,9 +62,9 @@ void NativeViewHostGtk::NativeViewDetaching() { void NativeViewHostGtk::AddedToWidget() { if (!host_->native_view()) return; - WidgetGtk* parent_widget = static_cast<WidgetGtk*>(host_->GetWidget()); + WidgetGtk* parent_widget = GetHostWidget(); GtkWidget* widget_parent = gtk_widget_get_parent(host_->native_view()); - GtkWidget* parent_widget_widget = parent_widget->child_widget_parent(); + GtkWidget* parent_widget_widget = parent_widget->window_contents(); if (widget_parent != parent_widget_widget) { g_object_ref(host_->native_view()); if (widget_parent) @@ -110,10 +84,10 @@ void NativeViewHostGtk::RemovedFromWidget() { if (!host_->native_view()) return; - WidgetGtk* parent_widget = static_cast<WidgetGtk*>(host_->GetWidget()); + WidgetGtk* parent_widget = GetHostWidget(); gtk_widget_hide(host_->native_view()); if (parent_widget) { - gtk_container_remove(GTK_CONTAINER(parent_widget->child_widget_parent()), + gtk_container_remove(GTK_CONTAINER(parent_widget->window_contents()), host_->native_view()); } } @@ -157,8 +131,7 @@ void NativeViewHostGtk::UninstallClip() { } void NativeViewHostGtk::ShowWidget(int x, int y, int w, int h) { - WidgetGtk* parent = static_cast<WidgetGtk*>(host_->GetWidget()); - parent->PositionChild(host_->native_view(), x, y, w, h); + GetHostWidget()->PositionChild(host_->native_view(), x, y, w, h); gtk_widget_show(host_->native_view()); } @@ -173,13 +146,14 @@ void NativeViewHostGtk::SetFocus() { //////////////////////////////////////////////////////////////////////////////// // NativeViewHostGtk, private: -// static -void NativeViewHostGtk::CallDestroy(GtkObject* object) { - View* view = GetViewForNative(GTK_WIDGET(object)); - if (!view) - return; +WidgetGtk* NativeViewHostGtk::GetHostWidget() const { + return static_cast<WidgetGtk*>(host_->GetWidget()); +} - return static_cast<NativeViewHost*>(view)->NativeViewDestroyed(); +// static +void NativeViewHostGtk::CallDestroy(GtkObject* object, + NativeViewHostGtk* host) { + return host->host_->NativeViewDestroyed(); } //////////////////////////////////////////////////////////////////////////////// diff --git a/views/controls/native/native_view_host_gtk.h b/views/controls/native/native_view_host_gtk.h index 40a6a65..154da70 100644 --- a/views/controls/native/native_view_host_gtk.h +++ b/views/controls/native/native_view_host_gtk.h @@ -14,17 +14,13 @@ namespace views { class View; +class WidgetGtk; class NativeViewHostGtk : public NativeViewHostWrapper { public: explicit NativeViewHostGtk(NativeViewHost* host); virtual ~NativeViewHostGtk(); - // Sets and retrieves the View associated with a particular widget. - // TODO(beng): move to NativeViewHost, and have take gfx::NativeViews. - static View* GetViewForNative(GtkWidget* widget); - static void SetViewForNative(GtkWidget* widget, View* view); - // Overridden from NativeViewHostWrapper: virtual void NativeViewAttached(); virtual void NativeViewDetaching(); @@ -38,6 +34,11 @@ class NativeViewHostGtk : public NativeViewHostWrapper { virtual void SetFocus(); private: + WidgetGtk* GetHostWidget() const; + + // Invoked from the 'destroy' signal. + static void CallDestroy(GtkObject* object, NativeViewHostGtk* host); + // Our associated NativeViewHost. NativeViewHost* host_; @@ -48,9 +49,6 @@ class NativeViewHostGtk : public NativeViewHostWrapper { // Signal handle id for 'destroy' signal. gulong destroy_signal_id_; - // Invoked from the 'destroy' signal. - static void CallDestroy(GtkObject* object); - DISALLOW_COPY_AND_ASSIGN(NativeViewHostGtk); }; diff --git a/views/widget/widget_gtk.cc b/views/widget/widget_gtk.cc index 7d7e74b..1aec6a4 100644 --- a/views/widget/widget_gtk.cc +++ b/views/widget/widget_gtk.cc @@ -53,6 +53,9 @@ static int GetFlagsForEventButton(const GdkEventButton& event) { return flags; } +// static +GtkWidget* WidgetGtk::null_parent_ = NULL; + //////////////////////////////////////////////////////////////////////////////// // WidgetGtk, public: @@ -60,7 +63,7 @@ WidgetGtk::WidgetGtk(Type type) : is_window_(false), type_(type), widget_(NULL), - child_widget_parent_(NULL), + window_contents_(NULL), is_mouse_down_(false), has_capture_(false), last_mouse_event_was_move_(false), @@ -84,7 +87,7 @@ void WidgetGtk::Init(GtkWidget* parent, #endif // Make container here. - CreateGtkWidget(); + CreateGtkWidget(parent); // Make sure we receive our motion events. @@ -92,7 +95,7 @@ void WidgetGtk::Init(GtkWidget* parent, // minimum we need painting to happen on the parent (otherwise painting // doesn't work at all), and similarly we need mouse release events on the // parent as windows don't get mouse releases. - gtk_widget_add_events(child_widget_parent_, + gtk_widget_add_events(window_contents_, GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_BUTTON_PRESS_MASK | @@ -109,33 +112,34 @@ void WidgetGtk::Init(GtkWidget* parent, MessageLoopForUI::current()->AddObserver(this); - g_signal_connect_after(G_OBJECT(child_widget_parent_), "size_allocate", + // TODO(beng): make these take this rather than NULL. + g_signal_connect_after(G_OBJECT(window_contents_), "size_allocate", G_CALLBACK(CallSizeAllocate), NULL); - g_signal_connect(G_OBJECT(child_widget_parent_), "expose_event", + g_signal_connect(G_OBJECT(window_contents_), "expose_event", G_CALLBACK(CallPaint), NULL); - g_signal_connect(G_OBJECT(child_widget_parent_), "enter_notify_event", + g_signal_connect(G_OBJECT(window_contents_), "enter_notify_event", G_CALLBACK(CallEnterNotify), NULL); - g_signal_connect(G_OBJECT(child_widget_parent_), "leave_notify_event", + g_signal_connect(G_OBJECT(window_contents_), "leave_notify_event", G_CALLBACK(CallLeaveNotify), NULL); - g_signal_connect(G_OBJECT(child_widget_parent_), "motion_notify_event", + g_signal_connect(G_OBJECT(window_contents_), "motion_notify_event", G_CALLBACK(CallMotionNotify), NULL); - g_signal_connect(G_OBJECT(child_widget_parent_), "button_press_event", + g_signal_connect(G_OBJECT(window_contents_), "button_press_event", G_CALLBACK(CallButtonPress), NULL); - g_signal_connect(G_OBJECT(child_widget_parent_), "button_release_event", + g_signal_connect(G_OBJECT(window_contents_), "button_release_event", G_CALLBACK(CallButtonRelease), NULL); - g_signal_connect(G_OBJECT(child_widget_parent_), "grab_broken_event", + g_signal_connect(G_OBJECT(window_contents_), "focus_out_event", + G_CALLBACK(CallFocusOut), NULL); + g_signal_connect(G_OBJECT(window_contents_), "grab_broken_event", G_CALLBACK(CallGrabBrokeEvent), NULL); - g_signal_connect(G_OBJECT(child_widget_parent_), "grab_notify", + g_signal_connect(G_OBJECT(window_contents_), "grab_notify", G_CALLBACK(CallGrabNotify), NULL); - g_signal_connect(G_OBJECT(child_widget_parent_), "focus_out_event", - G_CALLBACK(CallFocusOut), NULL); - g_signal_connect(G_OBJECT(child_widget_parent_), "key_press_event", + g_signal_connect(G_OBJECT(window_contents_), "key_press_event", G_CALLBACK(CallKeyPress), NULL); - g_signal_connect(G_OBJECT(child_widget_parent_), "key_release_event", + g_signal_connect(G_OBJECT(window_contents_), "key_release_event", G_CALLBACK(CallKeyRelease), NULL); - g_signal_connect(G_OBJECT(child_widget_parent_), "scroll_event", + g_signal_connect(G_OBJECT(window_contents_), "scroll_event", G_CALLBACK(CallScroll), NULL); - g_signal_connect(G_OBJECT(child_widget_parent_), "visibility_notify_event", + g_signal_connect(G_OBJECT(window_contents_), "visibility_notify_event", G_CALLBACK(CallVisibilityNotify), NULL); // In order to receive notification when the window is no longer the front @@ -167,10 +171,12 @@ void WidgetGtk::Init(GtkWidget* parent, tooltip_manager_.reset(new TooltipManagerGtk(this)); if (type_ == TYPE_CHILD) { - WidgetGtk* parent_widget = GetViewForNative(parent); - parent_widget->AddChild(widget_); - parent_widget->PositionChild(widget_, bounds.x(), bounds.y(), - bounds.width(), bounds.height()); + if (parent) { + WidgetGtk* parent_widget = GetViewForNative(parent); + parent_widget->AddChild(widget_); + parent_widget->PositionChild(widget_, bounds.x(), bounds.y(), + bounds.width(), bounds.height()); + } } else { if (bounds.width() > 0 && bounds.height() > 0) gtk_window_resize(GTK_WINDOW(widget_), bounds.width(), bounds.height()); @@ -199,11 +205,15 @@ bool WidgetGtk::MakeTransparent() { } void WidgetGtk::AddChild(GtkWidget* child) { - gtk_container_add(GTK_CONTAINER(child_widget_parent_), child); + gtk_container_add(GTK_CONTAINER(window_contents_), child); } void WidgetGtk::RemoveChild(GtkWidget* child) { - gtk_container_remove(GTK_CONTAINER(child_widget_parent_), child); + gtk_container_remove(GTK_CONTAINER(window_contents_), child); +} + +void WidgetGtk::ReparentChild(GtkWidget* child) { + gtk_widget_reparent(child, window_contents_); } void WidgetGtk::PositionChild(GtkWidget* child, int x, int y, int w, int h) { @@ -211,7 +221,7 @@ void WidgetGtk::PositionChild(GtkWidget* child, int x, int y, int w, int h) { // For some reason we need to do both of these to size a widget. gtk_widget_size_allocate(child, &alloc); gtk_widget_set_size_request(child, w, h); - gtk_fixed_move(GTK_FIXED(child_widget_parent_), child, x, y); + gtk_fixed_move(GTK_FIXED(window_contents_), child, x, y); } void WidgetGtk::SetContentsView(View* view) { @@ -389,10 +399,17 @@ void WidgetGtk::DidProcessEvent(GdkEvent* event) { //////////////////////////////////////////////////////////////////////////////// // TODO(beng): organize into sections: -void WidgetGtk::CreateGtkWidget() { +void WidgetGtk::CreateGtkWidget(GtkWidget* parent) { if (type_ == TYPE_CHILD) { - child_widget_parent_ = widget_ = gtk_fixed_new(); + window_contents_ = widget_ = gtk_fixed_new(); gtk_fixed_set_has_window(GTK_FIXED(widget_), true); + if (!parent && !null_parent_) { + GtkWidget* popup = gtk_window_new(GTK_WINDOW_POPUP); + null_parent_ = gtk_fixed_new(); + gtk_container_add(GTK_CONTAINER(popup), null_parent_); + gtk_widget_realize(null_parent_); + } + gtk_container_add(GTK_CONTAINER(parent ? parent : null_parent_), widget_); SetViewForNative(widget_, this); } else { widget_ = gtk_window_new( @@ -403,16 +420,15 @@ void WidgetGtk::CreateGtkWidget() { SetWindowForNative(widget_, static_cast<WindowGtk*>(this)); SetViewForNative(widget_, this); - child_widget_parent_ = gtk_fixed_new(); - gtk_fixed_set_has_window(GTK_FIXED(child_widget_parent_), true); - gtk_container_add(GTK_CONTAINER(widget_), child_widget_parent_); - gtk_widget_show(child_widget_parent_); - SetViewForNative(child_widget_parent_, this); + window_contents_ = gtk_fixed_new(); + gtk_fixed_set_has_window(GTK_FIXED(window_contents_), true); + gtk_container_add(GTK_CONTAINER(widget_), window_contents_); + gtk_widget_show(window_contents_); + SetViewForNative(window_contents_, this); if (transparent_) ConfigureWidgetForTransparentBackground(); } - // The widget needs to be realized before handlers like size-allocate can // function properly. gtk_widget_realize(widget_); @@ -500,12 +516,12 @@ gboolean WidgetGtk::OnGrabBrokeEvent(GtkWidget* widget, GdkEvent* event) { } void WidgetGtk::OnGrabNotify(GtkWidget* widget, gboolean was_grabbed) { - gtk_grab_remove(child_widget_parent_); + gtk_grab_remove(window_contents_); HandleGrabBroke(); } void WidgetGtk::OnDestroy(GtkWidget* widget) { - widget_ = child_widget_parent_ = NULL; + widget_ = window_contents_ = NULL; root_view_->OnWidgetDestroyed(); if (delete_on_destroy_) delete this; @@ -564,7 +580,7 @@ bool WidgetGtk::ProcessMousePressed(GdkEventButton* event) { is_mouse_down_ = true; if (!has_capture_) { has_capture_ = true; - gtk_grab_add(child_widget_parent_); + gtk_grab_add(window_contents_); } return true; } @@ -581,7 +597,7 @@ void WidgetGtk::ProcessMouseReleased(GdkEventButton* event) { if (has_capture_ && ReleaseCaptureOnMouseReleased()) { has_capture_ = false; - gtk_grab_remove(child_widget_parent_); + gtk_grab_remove(window_contents_); } is_mouse_down_ = false; root_view_->OnMouseReleased(mouse_up, false); @@ -763,8 +779,7 @@ Window* WidgetGtk::GetWindowImpl(GtkWidget* widget) { } void WidgetGtk::ConfigureWidgetForTransparentBackground() { - DCHECK(widget_ && child_widget_parent_ && - widget_ != child_widget_parent_); + DCHECK(widget_ && window_contents_ && widget_ != window_contents_); GdkColormap* rgba_colormap = gdk_screen_get_rgba_colormap(gdk_screen_get_default()); @@ -785,12 +800,12 @@ void WidgetGtk::ConfigureWidgetForTransparentBackground() { // Widget must be realized before setting pixmap. gdk_window_set_back_pixmap(widget_->window, NULL, FALSE); - gtk_widget_set_colormap(child_widget_parent_, rgba_colormap); - gtk_widget_set_app_paintable(child_widget_parent_, true); - GTK_WIDGET_UNSET_FLAGS(child_widget_parent_, GTK_DOUBLE_BUFFERED); - gtk_widget_realize(child_widget_parent_); + gtk_widget_set_colormap(window_contents_, rgba_colormap); + gtk_widget_set_app_paintable(window_contents_, true); + GTK_WIDGET_UNSET_FLAGS(window_contents_, GTK_DOUBLE_BUFFERED); + gtk_widget_realize(window_contents_); // Widget must be realized before setting pixmap. - gdk_window_set_back_pixmap(child_widget_parent_->window, NULL, FALSE); + gdk_window_set_back_pixmap(window_contents_->window, NULL, FALSE); } void WidgetGtk::HandleGrabBroke() { diff --git a/views/widget/widget_gtk.h b/views/widget/widget_gtk.h index 2442f74..b5dd6a0 100644 --- a/views/widget/widget_gtk.h +++ b/views/widget/widget_gtk.h @@ -56,15 +56,25 @@ class WidgetGtk : public Widget, public MessageLoopForUI::Observer { delete_on_destroy_ = delete_on_destroy; } + // Adds and removes the specified widget as a child of this widget's contents. + // These methods make sure to add the widget to the window's contents + // container if this widget is a window. void AddChild(GtkWidget* child); void RemoveChild(GtkWidget* child); + // A safe way to reparent a child widget to this widget. Calls + // gtk_widget_reparent which handles refcounting to avoid destroying the + // widget when removing it from its old parent. + void ReparentChild(GtkWidget* child); + // Positions a child GtkWidget at the specified location and bounds. void PositionChild(GtkWidget* child, int x, int y, int w, int h); - // Parent GtkWidget all children are added to. This is not necessarily - // the same as returned by GetNativeView. - GtkWidget* child_widget_parent() const { return child_widget_parent_; } + // Parent GtkWidget all children are added to. When this WidgetGtk corresponds + // to a top level window, this is the GtkFixed within the GtkWindow, not the + // GtkWindow itself. For child widgets, this is the same GtkFixed as + // |widget_|. + GtkWidget* window_contents() const { return window_contents_; } virtual void SetContentsView(View* view); @@ -174,7 +184,10 @@ class WidgetGtk : public Widget, public MessageLoopForUI::Observer { static Window* GetWindowImpl(GtkWidget* widget); // Creates the GtkWidget. - void CreateGtkWidget(); + void CreateGtkWidget(GtkWidget* parent); + + // Attaches the widget contents to the window's widget. + void AttachGtkWidgetToWindow(); // Invoked from create widget to enable the various bits needed for a // transparent background. This is only invoked if MakeTransparent has been @@ -186,10 +199,15 @@ class WidgetGtk : public Widget, public MessageLoopForUI::Observer { const Type type_; // Our native views. If we're a window/popup, then widget_ is the window and - // child_widget_parent_ is a GtkFixed. If we're not a window/popup, then - // widget_ and child_widget_parent_ are a GtkFixed. + // window_contents_ is a GtkFixed. If we're not a window/popup, then widget_ + // and window_contents_ point to the same GtkFixed. GtkWidget* widget_; - GtkWidget* child_widget_parent_; + GtkWidget* window_contents_; + + // Child GtkWidgets created with no parent need to be parented to a valid top + // level window otherwise Gtk throws a fit. |null_parent_| is an invisible + // popup that such GtkWidgets are parented to. + static GtkWidget* null_parent_; // The root of the View hierarchy attached to this window. scoped_ptr<RootView> root_view_; |