diff options
Diffstat (limited to 'views/widget/widget_gtk.cc')
-rw-r--r-- | views/widget/widget_gtk.cc | 209 |
1 files changed, 117 insertions, 92 deletions
diff --git a/views/widget/widget_gtk.cc b/views/widget/widget_gtk.cc index cb9eddf..0eca3d7 100644 --- a/views/widget/widget_gtk.cc +++ b/views/widget/widget_gtk.cc @@ -44,12 +44,10 @@ using ui::OSExchangeData; using ui::OSExchangeDataProviderGtk; using ui::ActiveWindowWatcherX; -namespace views { - namespace { -// Links the GtkWidget to its NativeWidget. -const char* const kNativeWidgetKey = "__VIEWS_NATIVE_WIDGET__"; +// g_object data keys to associate a WidgetGtk object to a GtkWidget. +const char* kWidgetKey = "__VIEWS_WIDGET__"; // A g_object data key to associate a CompositePainter object to a GtkWidget. const char* kCompositePainterKey = "__VIEWS_COMPOSITE_PAINTER__"; // A g_object data key to associate the flag whether or not the widget @@ -136,26 +134,10 @@ class CompositePainter { DISALLOW_COPY_AND_ASSIGN(CompositePainter); }; -void EnumerateChildWidgetsForNativeWidgets(GtkWidget* child_widget, - gpointer param) { - // Walk child widgets, if necessary. - if (GTK_IS_CONTAINER(child_widget)) { - gtk_container_foreach(GTK_CONTAINER(child_widget), - EnumerateChildWidgetsForNativeWidgets, - param); - } - - NativeWidget* native_widget = - NativeWidget::GetNativeWidgetForNativeView(child_widget); - if (native_widget) { - NativeWidget::NativeWidgets* widgets = - reinterpret_cast<NativeWidget::NativeWidgets*>(param); - widgets->insert(native_widget); - } -} - } // namespace +namespace views { + // During drag and drop GTK sends a drag-leave during a drop. This means we // have no way to tell the difference between a normal drag leave and a drop. // To work around that we listen for DROP_START, then ignore the subsequent @@ -185,8 +167,7 @@ class WidgetGtk::DropObserver : public MessageLoopForUI::Observer { if (!gtk_widget) return NULL; - return static_cast<WidgetGtk*>( - NativeWidget::GetNativeWidgetForNativeView(gtk_widget)); + return WidgetGtk::GetViewForNative(gtk_widget); } DISALLOW_COPY_AND_ASSIGN(DropObserver); @@ -440,11 +421,22 @@ void WidgetGtk::IsActiveChanged() { GetWidgetDelegate()->IsActiveChanged(IsActive()); } +// static +WidgetGtk* WidgetGtk::GetViewForNative(GtkWidget* widget) { + return static_cast<WidgetGtk*>(GetWidgetFromNativeView(widget)); +} + void WidgetGtk::ResetDropTarget() { ignore_drag_leave_ = false; drop_target_.reset(NULL); } +// static +RootView* WidgetGtk::GetRootViewForWidget(GtkWidget* widget) { + gpointer user_data = g_object_get_data(G_OBJECT(widget), "root-view"); + return static_cast<RootView*>(user_data); +} + void WidgetGtk::GetRequestedSize(gfx::Size* out) const { int width, height; if (GTK_IS_VIEWS_FIXED(widget_) && @@ -525,6 +517,7 @@ void WidgetGtk::Init(GtkWidget* parent, GDK_POINTER_MOTION_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK); + SetRootViewForWidget(widget_, GetRootView()); g_signal_connect_after(G_OBJECT(window_contents_), "size_request", G_CALLBACK(&OnSizeRequestThunk), this); @@ -637,8 +630,7 @@ void WidgetGtk::SetBounds(const gfx::Rect& bounds) { if (type_ == TYPE_CHILD) { GtkWidget* parent = gtk_widget_get_parent(widget_); if (GTK_IS_VIEWS_FIXED(parent)) { - WidgetGtk* parent_widget = static_cast<WidgetGtk*>( - NativeWidget::GetNativeWidgetForNativeView(parent)); + WidgetGtk* parent_widget = GetViewForNative(parent); parent_widget->PositionChild(widget_, bounds.x(), bounds.y(), bounds.width(), bounds.height()); } else { @@ -743,6 +735,16 @@ void WidgetGtk::SetAlwaysOnTop(bool on_top) { gtk_window_set_keep_above(GTK_WINDOW(widget_), on_top); } +Widget* WidgetGtk::GetRootWidget() const { + GtkWidget* parent = widget_; + GtkWidget* last_parent = parent; + while (parent) { + last_parent = parent; + parent = gtk_widget_get_parent(parent); + } + return last_parent ? GetViewForNative(last_parent) : NULL; +} + bool WidgetGtk::IsVisible() const { return GTK_WIDGET_VISIBLE(widget_); } @@ -794,11 +796,11 @@ FocusManager* WidgetGtk::GetFocusManager() { if (focus_manager_) return focus_manager_; - NativeWidget* native_widget = GetTopLevelNativeWidget(GetNativeView()); - if (native_widget && native_widget != this) { - // WidgetGtk subclasses may override GetFocusManager(), for example for + Widget* root = GetRootWidget(); + if (root && root != this) { + // Widget subclasses may override GetFocusManager(), for example for // dealing with cases where the widget has been unparented. - return native_widget->GetWidget()->GetFocusManager(); + return root->GetFocusManager(); } return NULL; } @@ -934,13 +936,6 @@ void WidgetGtk::EnableDebugPaint() { } //////////////////////////////////////////////////////////////////////////////// -// WidgetGtk, NativeWidget implementation: - -Widget* WidgetGtk::GetWidget() { - return this; -} - -//////////////////////////////////////////////////////////////////////////////// // WidgetGtk, protected: void WidgetGtk::OnSizeRequest(GtkWidget* widget, GtkRequisition* requisition) { @@ -1378,11 +1373,15 @@ bool WidgetGtk::ProcessScroll(GdkEventScroll* event) { } // static +void WidgetGtk::SetRootViewForWidget(GtkWidget* widget, RootView* root_view) { + g_object_set_data(G_OBJECT(widget), "root-view", root_view); +} + +// static Window* WidgetGtk::GetWindowImpl(GtkWidget* widget) { GtkWidget* parent = widget; while (parent) { - WidgetGtk* widget_gtk = static_cast<WidgetGtk*>( - NativeWidget::GetNativeWidgetForNativeView(parent)); + WidgetGtk* widget_gtk = GetViewForNative(parent); if (widget_gtk && widget_gtk->is_window_) return static_cast<WindowGtk*>(widget_gtk); parent = gtk_widget_get_parent(parent); @@ -1479,7 +1478,7 @@ void WidgetGtk::CreateGtkWidget(GtkWidget* parent, const gfx::Rect& bounds) { gtk_fixed_set_has_window(GTK_FIXED(window_contents_), true); gtk_container_add(GTK_CONTAINER(widget_), window_contents_); gtk_widget_show(window_contents_); - g_object_set_data(G_OBJECT(window_contents_), kNativeWidgetKey, + g_object_set_data(G_OBJECT(window_contents_), kWidgetKey, static_cast<Widget*>(this)); if (transparent_) @@ -1493,7 +1492,9 @@ void WidgetGtk::CreateGtkWidget(GtkWidget* parent, const gfx::Rect& bounds) { // function properly. gtk_widget_realize(widget_); } - SetNativeWindowProperty(kNativeWidgetKey, this); + // Setting the WidgetKey property to widget_, which is used by + // GetWidgetFromNativeWindow. + SetNativeWindowProperty(kWidgetKey, this); } void WidgetGtk::ConfigureWidgetForTransparentBackground(GtkWidget* parent) { @@ -1572,71 +1573,95 @@ Widget* Widget::CreatePopupWidget(TransparencyParam transparent, return popup; } -// static -void Widget::NotifyLocaleChanged() { - GList *window_list = gtk_window_list_toplevels(); - for (GList* element = window_list; element; element = g_list_next(element)) { - NativeWidget* widget = - NativeWidget::GetNativeWidgetForNativeWindow(GTK_WINDOW(element->data)); - if (widget) - widget->GetWidget()->LocaleChanged(); +// Callback from gtk_container_foreach. Locates the first root view of widget +// or one of it's descendants. +static void RootViewLocatorCallback(GtkWidget* widget, + gpointer root_view_p) { + RootView** root_view = static_cast<RootView**>(root_view_p); + if (!*root_view) { + *root_view = WidgetGtk::GetRootViewForWidget(widget); + if (!*root_view && GTK_IS_CONTAINER(widget)) { + // gtk_container_foreach only iterates over children, not all descendants, + // so we have to recurse here to get all descendants. + gtk_container_foreach(GTK_CONTAINER(widget), RootViewLocatorCallback, + root_view_p); + } } - g_list_free(window_list); -} - -//////////////////////////////////////////////////////////////////////////////// -// NativeWidget, public: - -// static -NativeWidget* NativeWidget::GetNativeWidgetForNativeView( - gfx::NativeView native_view) { - if (!native_view) - return NULL; - return reinterpret_cast<WidgetGtk*>( - g_object_get_data(G_OBJECT(native_view), kNativeWidgetKey)); } // static -NativeWidget* NativeWidget::GetNativeWidgetForNativeWindow( - gfx::NativeWindow native_window) { - if (!native_window) - return NULL; - return reinterpret_cast<WidgetGtk*>( - g_object_get_data(G_OBJECT(native_window), kNativeWidgetKey)); +RootView* Widget::FindRootView(GtkWindow* window) { + RootView* root_view = WidgetGtk::GetRootViewForWidget(GTK_WIDGET(window)); + if (root_view) + return root_view; + + // Enumerate all children and check if they have a RootView. + gtk_container_foreach(GTK_CONTAINER(window), RootViewLocatorCallback, + static_cast<gpointer>(&root_view)); + return root_view; +} + +static void AllRootViewsLocatorCallback(GtkWidget* widget, + gpointer root_view_p) { + std::set<RootView*>* root_views_set = + reinterpret_cast<std::set<RootView*>*>(root_view_p); + RootView *root_view = WidgetGtk::GetRootViewForWidget(widget); + if (!root_view && GTK_IS_CONTAINER(widget)) { + // gtk_container_foreach only iterates over children, not all descendants, + // so we have to recurse here to get all descendants. + gtk_container_foreach(GTK_CONTAINER(widget), AllRootViewsLocatorCallback, + root_view_p); + } else { + if (root_view) + root_views_set->insert(root_view); + } } // static -NativeWidget* NativeWidget::GetTopLevelNativeWidget( - gfx::NativeView native_view) { - if (!native_view) - return NULL; +void Widget::FindAllRootViews(GtkWindow* window, + std::vector<RootView*>* root_views) { + RootView* root_view = WidgetGtk::GetRootViewForWidget(GTK_WIDGET(window)); + if (root_view) + root_views->push_back(root_view); - NativeWidget* widget = NULL; + std::set<RootView*> root_views_set; - GtkWidget* parent_gtkwidget = native_view; - NativeWidget* parent_widget; - do { - parent_widget = GetNativeWidgetForNativeView(parent_gtkwidget); - if (parent_widget) - widget = parent_widget; - parent_gtkwidget = gtk_widget_get_parent(parent_gtkwidget); - } while (parent_gtkwidget); + // Enumerate all children and check if they have a RootView. + gtk_container_foreach(GTK_CONTAINER(window), AllRootViewsLocatorCallback, + reinterpret_cast<gpointer>(&root_views_set)); + root_views->clear(); + root_views->reserve(root_views_set.size()); + for (std::set<RootView*>::iterator it = root_views_set.begin(); + it != root_views_set.end(); + ++it) + root_views->push_back(*it); +} - return widget; +// static +Widget* Widget::GetWidgetFromNativeView(gfx::NativeView native_view) { + gpointer raw_widget = g_object_get_data(G_OBJECT(native_view), kWidgetKey); + if (raw_widget) + return reinterpret_cast<Widget*>(raw_widget); + return NULL; } // static -void NativeWidget::GetAllNativeWidgets(gfx::NativeView native_view, - NativeWidgets* children) { - if (!native_view) - return; +Widget* Widget::GetWidgetFromNativeWindow(gfx::NativeWindow native_window) { + gpointer raw_widget = g_object_get_data(G_OBJECT(native_window), kWidgetKey); + if (raw_widget) + return reinterpret_cast<Widget*>(raw_widget); + return NULL; +} - NativeWidget* native_widget = GetNativeWidgetForNativeView(native_view); - if (native_widget) - children->insert(native_widget); - gtk_container_foreach(GTK_CONTAINER(native_view), - EnumerateChildWidgetsForNativeWidgets, - reinterpret_cast<gpointer>(children)); +// static +void Widget::NotifyLocaleChanged() { + GList *window_list = gtk_window_list_toplevels(); + for (GList* element = window_list; element; element = g_list_next(element)) { + Widget* widget = GetWidgetFromNativeWindow(GTK_WINDOW(element->data)); + if (widget) + widget->LocaleChanged(); + } + g_list_free(window_list); } } // namespace views |