| Index: views/widget/widget_gtk.cc
|
| ===================================================================
|
| --- views/widget/widget_gtk.cc (revision 85284)
|
| +++ views/widget/widget_gtk.cc (working copy)
|
| @@ -284,9 +284,9 @@
|
| ////////////////////////////////////////////////////////////////////////////////
|
| // WidgetGtk, public:
|
|
|
| -WidgetGtk::WidgetGtk()
|
| +WidgetGtk::WidgetGtk(internal::NativeWidgetDelegate* delegate)
|
| : is_window_(false),
|
| - ALLOW_THIS_IN_INITIALIZER_LIST(delegate_(this)),
|
| + delegate_(delegate),
|
| widget_(NULL),
|
| window_contents_(NULL),
|
| child_(false),
|
| @@ -301,6 +301,7 @@
|
| transient_to_parent_(false),
|
| got_initial_focus_in_(false),
|
| has_focus_(false),
|
| + focus_on_creation_(true),
|
| always_on_top_(false),
|
| is_double_buffered_(false),
|
| should_handle_menu_key_release_(false),
|
| @@ -311,7 +312,6 @@
|
| // the widget.
|
| TouchFactory::GetInstance();
|
| #endif
|
| - set_native_widget(this);
|
| static bool installed_message_loop_observer = false;
|
| if (!installed_message_loop_observer) {
|
| installed_message_loop_observer = true;
|
| @@ -325,8 +325,9 @@
|
| // We need to delete the input method before calling DestroyRootView(),
|
| // because it'll set focus_manager_ to NULL.
|
| input_method_.reset();
|
| - DestroyRootView();
|
| DCHECK(delete_on_destroy_ || widget_ == NULL);
|
| + if (delete_on_destroy_)
|
| + delete delegate_;
|
| }
|
|
|
| GtkWindow* WidgetGtk::GetTransientParent() const {
|
| @@ -443,7 +444,7 @@
|
| }
|
|
|
| void WidgetGtk::IsActiveChanged() {
|
| - WidgetDelegate* d = widget_delegate();
|
| + WidgetDelegate* d = GetWidget()->widget_delegate();
|
| if (d) {
|
| bool a = IsActive();
|
| d->OnWidgetActivated(a);
|
| @@ -451,8 +452,11 @@
|
| }
|
|
|
| void WidgetGtk::SetInitialFocus() {
|
| - View* v = widget_delegate() ?
|
| - widget_delegate()->GetInitiallyFocusedView() : NULL;
|
| + if (!focus_on_creation_)
|
| + return;
|
| +
|
| + View* v = GetWidget()->widget_delegate() ?
|
| + GetWidget()->widget_delegate()->GetInitiallyFocusedView() : NULL;
|
| if (v)
|
| v->RequestFocus();
|
| }
|
| @@ -496,52 +500,13 @@
|
| }
|
| if (was_active != IsActive()) {
|
| IsActiveChanged();
|
| - GetRootView()->SchedulePaint();
|
| + GetWidget()->GetRootView()->SchedulePaint();
|
| }
|
| }
|
|
|
| ////////////////////////////////////////////////////////////////////////////////
|
| // WidgetGtk, Widget implementation:
|
|
|
| -gfx::NativeView WidgetGtk::GetNativeView() const {
|
| - return widget_;
|
| -}
|
| -
|
| -gfx::NativeWindow WidgetGtk::GetNativeWindow() const {
|
| - return child_ ? NULL : GTK_WINDOW(widget_);
|
| -}
|
| -
|
| -bool WidgetGtk::GetAccelerator(int cmd_id, ui::Accelerator* accelerator) {
|
| - NOTIMPLEMENTED();
|
| - return false;
|
| -}
|
| -
|
| -Window* WidgetGtk::GetWindow() {
|
| - return GetWindowImpl(widget_);
|
| -}
|
| -
|
| -const Window* WidgetGtk::GetWindow() const {
|
| - return GetWindowImpl(widget_);
|
| -}
|
| -
|
| -void WidgetGtk::ViewHierarchyChanged(bool is_add, View* parent, View* child) {
|
| - Widget::ViewHierarchyChanged(is_add, parent, child);
|
| - if (drop_target_.get())
|
| - drop_target_->ResetTargetViewIfEquals(child);
|
| -}
|
| -
|
| -void WidgetGtk::NotifyAccessibilityEvent(
|
| - View* view,
|
| - ui::AccessibilityTypes::Event event_type,
|
| - bool send_native_event) {
|
| - // Send the notification to the delegate.
|
| - if (ViewsDelegate::views_delegate)
|
| - ViewsDelegate::views_delegate->NotifyAccessibilityEvent(view, event_type);
|
| -
|
| - // In the future if we add native GTK accessibility support, the
|
| - // notification should be sent here.
|
| -}
|
| -
|
| void WidgetGtk::ClearNativeFocus() {
|
| DCHECK(!child_);
|
| if (!GetNativeView()) {
|
| @@ -552,7 +517,7 @@
|
| }
|
|
|
| bool WidgetGtk::HandleKeyboardEvent(const KeyEvent& key) {
|
| - if (!GetFocusManager())
|
| + if (!GetWidget()->GetFocusManager())
|
| return false;
|
|
|
| const int key_code = key.key_code();
|
| @@ -569,7 +534,7 @@
|
| // VKEY_MENU is triggered by key release event.
|
| // FocusManager::OnKeyEvent() returns false when the key has been consumed.
|
| if (key_code != ui::VKEY_MENU)
|
| - handled = !GetFocusManager()->OnKeyEvent(key);
|
| + handled = !GetWidget()->GetFocusManager()->OnKeyEvent(key);
|
| else
|
| should_handle_menu_key_release_ = true;
|
| } else if (key_code == ui::VKEY_MENU && should_handle_menu_key_release_ &&
|
| @@ -577,7 +542,7 @@
|
| // Trigger VKEY_MENU when only this key is pressed and released, and both
|
| // press and release events are not handled by others.
|
| Accelerator accelerator(ui::VKEY_MENU, false, false, false);
|
| - handled = GetFocusManager()->ProcessAccelerator(accelerator);
|
| + handled = GetWidget()->GetFocusManager()->ProcessAccelerator(accelerator);
|
| }
|
|
|
| return handled;
|
| @@ -626,10 +591,10 @@
|
| ////////////////////////////////////////////////////////////////////////////////
|
| // WidgetGtk, NativeWidget implementation:
|
|
|
| -void WidgetGtk::InitNativeWidget(const InitParams& params) {
|
| +void WidgetGtk::InitNativeWidget(const Widget::InitParams& params) {
|
| SetInitParams(params);
|
|
|
| - InitParams modified_params = params;
|
| + Widget::InitParams modified_params = params;
|
| gfx::NativeView parent = params.parent;
|
| if (params.parent_widget) {
|
| WidgetGtk* parent_gtk =
|
| @@ -766,9 +731,34 @@
|
| }
|
|
|
| Widget* WidgetGtk::GetWidget() {
|
| - return this;
|
| + return delegate_->AsWidget();
|
| }
|
|
|
| +const Widget* WidgetGtk::GetWidget() const {
|
| + return delegate_->AsWidget();
|
| +}
|
| +
|
| +gfx::NativeView WidgetGtk::GetNativeView() const {
|
| + return widget_;
|
| +}
|
| +
|
| +gfx::NativeWindow WidgetGtk::GetNativeWindow() const {
|
| + return child_ ? NULL : GTK_WINDOW(widget_);
|
| +}
|
| +
|
| +Window* WidgetGtk::GetContainingWindow() {
|
| + return GetWindowImpl(widget_);
|
| +}
|
| +
|
| +const Window* WidgetGtk::GetContainingWindow() const {
|
| + return GetWindowImpl(widget_);
|
| +}
|
| +
|
| +void WidgetGtk::ViewRemoved(View* view) {
|
| + if (drop_target_.get())
|
| + drop_target_->ResetTargetViewIfEquals(view);
|
| +}
|
| +
|
| void WidgetGtk::SetNativeWindowProperty(const char* name, void* value) {
|
| g_object_set_data(G_OBJECT(widget_), name, value);
|
| }
|
| @@ -785,6 +775,13 @@
|
| return false;
|
| }
|
|
|
| +void WidgetGtk::SendNativeAccessibilityEvent(
|
| + View* view,
|
| + ui::AccessibilityTypes::Event event_type) {
|
| + // In the future if we add native GTK accessibility support, the
|
| + // notification should be sent here.
|
| +}
|
| +
|
| void WidgetGtk::SetMouseCapture() {
|
| DCHECK(!HasMouseCapture());
|
| gtk_grab_add(window_contents_);
|
| @@ -801,6 +798,18 @@
|
| return GTK_WIDGET_HAS_GRAB(window_contents_);
|
| }
|
|
|
| +bool WidgetGtk::IsMouseButtonDown() const {
|
| + bool button_pressed = false;
|
| + GdkEvent* event = gtk_get_current_event();
|
| + if (event) {
|
| + button_pressed = event->type == GDK_BUTTON_PRESS ||
|
| + event->type == GDK_2BUTTON_PRESS ||
|
| + event->type == GDK_3BUTTON_PRESS;
|
| + gdk_event_free(event);
|
| + }
|
| + return button_pressed;
|
| +}
|
| +
|
| InputMethod* WidgetGtk::GetInputMethodNative() {
|
| return input_method_.get();
|
| }
|
| @@ -1018,7 +1027,7 @@
|
| // preferred size for these would prevents us from setting smaller window
|
| // sizes.
|
| if (child_) {
|
| - gfx::Size size(GetRootView()->GetPreferredSize());
|
| + gfx::Size size(GetWidget()->GetRootView()->GetPreferredSize());
|
| requisition->width = size.width();
|
| requisition->height = size.height();
|
| }
|
| @@ -1153,7 +1162,7 @@
|
| gint y,
|
| guint time) {
|
| if (!drop_target_.get())
|
| - drop_target_.reset(new DropTargetGtk(GetRootView(), context));
|
| + drop_target_.reset(new DropTargetGtk(GetWidget()->GetRootView(), context));
|
| return drop_target_->OnDragMotion(context, x, y, time);
|
| }
|
|
|
| @@ -1164,7 +1173,8 @@
|
| return false;
|
| }
|
|
|
| - if (!last_mouse_event_was_move_ && !is_mouse_button_pressed_) {
|
| + if (!GetWidget()->last_mouse_event_was_move_ &&
|
| + !GetWidget()->is_mouse_button_pressed_) {
|
| // When a mouse button is pressed gtk generates a leave, enter, press.
|
| // RootView expects to get a mouse move before a press, otherwise enter is
|
| // not set. So we generate a move here.
|
| @@ -1180,13 +1190,13 @@
|
| MouseEvent mouse_event(TransformEvent(&motion));
|
| delegate_->OnMouseEvent(mouse_event);
|
| }
|
| -
|
| return false;
|
| }
|
|
|
| gboolean WidgetGtk::OnLeaveNotify(GtkWidget* widget, GdkEventCrossing* event) {
|
| - last_mouse_event_was_move_ = false;
|
| - if (!HasMouseCapture() && !is_mouse_button_pressed_) {
|
| + GetWidget()->ResetLastMouseMoveFlag();
|
| +
|
| + if (!HasMouseCapture() && !GetWidget()->is_mouse_button_pressed_) {
|
| MouseEvent mouse_event(TransformEvent(event));
|
| delegate_->OnMouseEvent(mouse_event);
|
| }
|
| @@ -1346,10 +1356,6 @@
|
| ////////////////////////////////////////////////////////////////////////////////
|
| // WidgetGtk, private:
|
|
|
| -RootView* WidgetGtk::CreateRootView() {
|
| - return new RootView(this);
|
| -}
|
| -
|
| gfx::AcceleratedWidget WidgetGtk::GetAcceleratedWidget() {
|
| DCHECK(window_contents_ && window_contents_->window);
|
| return GDK_WINDOW_XID(window_contents_->window);
|
| @@ -1392,28 +1398,24 @@
|
| gtk_bindings_activate_event(GTK_OBJECT(widget_), event);
|
| }
|
|
|
| -void WidgetGtk::SetInitParams(const InitParams& params) {
|
| +void WidgetGtk::SetInitParams(const Widget::InitParams& params) {
|
| DCHECK(!GetNativeView());
|
|
|
| delete_on_destroy_ = params.delete_on_destroy;
|
| child_ = params.child;
|
|
|
| + // TODO(beng): The secondary checks here actually obviate the need for
|
| + // params.transient but that's only because WidgetGtk considers
|
| + // any top-level widget to be a transient widget. We will probably
|
| + // want to ammend this assumption at some point.
|
| + if (params.transient || params.parent || params.parent_widget)
|
| + transient_to_parent_ = true;
|
| if (params.transparent)
|
| MakeTransparent();
|
| if (!params.accept_events && !child_)
|
| ignore_events_ = true;
|
| if (params.double_buffer)
|
| EnableDoubleBuffer(true);
|
| -
|
| - if (params.type == InitParams::TYPE_MENU) {
|
| - GdkEvent* event = gtk_get_current_event();
|
| - if (event) {
|
| - is_mouse_button_pressed_ = event->type == GDK_BUTTON_PRESS ||
|
| - event->type == GDK_2BUTTON_PRESS ||
|
| - event->type == GDK_3BUTTON_PRESS;
|
| - gdk_event_free(event);
|
| - }
|
| - }
|
| }
|
|
|
| gboolean WidgetGtk::OnWindowPaint(GtkWidget* widget, GdkEventExpose* event) {
|
| @@ -1460,13 +1462,13 @@
|
| WidgetGtk* widget_gtk = static_cast<WidgetGtk*>(
|
| NativeWidget::GetNativeWidgetForNativeView(parent));
|
| if (widget_gtk && widget_gtk->is_window_)
|
| - return static_cast<WindowGtk*>(widget_gtk);
|
| + return static_cast<WindowGtk*>(widget_gtk)->GetWindow();
|
| parent = gtk_widget_get_parent(parent);
|
| }
|
| return NULL;
|
| }
|
|
|
| -void WidgetGtk::CreateGtkWidget(const InitParams& params) {
|
| +void WidgetGtk::CreateGtkWidget(const Widget::InitParams& params) {
|
| // We turn off double buffering for two reasons:
|
| // 1. We draw to a canvas then composite to the screen, which means we're
|
| // doing our own double buffering already.
|
| @@ -1520,8 +1522,8 @@
|
| } else {
|
| // Use our own window class to override GtkWindow's move_focus method.
|
| widget_ = gtk_views_window_new(
|
| - params.type == InitParams::TYPE_WINDOW ? GTK_WINDOW_TOPLEVEL
|
| - : GTK_WINDOW_POPUP);
|
| + params.type == Widget::InitParams::TYPE_WINDOW ? GTK_WINDOW_TOPLEVEL
|
| + : GTK_WINDOW_POPUP);
|
| gtk_widget_set_name(widget_, "views-gtkwidget-window");
|
| if (transient_to_parent_) {
|
| gtk_window_set_transient_for(GTK_WINDOW(widget_),
|
| @@ -1560,7 +1562,7 @@
|
| gtk_container_add(GTK_CONTAINER(widget_), window_contents_);
|
| gtk_widget_show(window_contents_);
|
| g_object_set_data(G_OBJECT(window_contents_), kNativeWidgetKey,
|
| - static_cast<Widget*>(this));
|
| + static_cast<WidgetGtk*>(this));
|
| if (transparent_)
|
| ConfigureWidgetForTransparentBackground(NULL);
|
|
|
| @@ -1643,11 +1645,6 @@
|
| // Widget, public:
|
|
|
| // static
|
| -Widget* Widget::CreateWidget() {
|
| - return new WidgetGtk();
|
| -}
|
| -
|
| -// static
|
| void Widget::NotifyLocaleChanged() {
|
| GList *window_list = gtk_window_list_toplevels();
|
| for (GList* element = window_list; element; element = g_list_next(element)) {
|
| @@ -1660,6 +1657,22 @@
|
| }
|
|
|
| // static
|
| +void Widget::CloseAllSecondaryWidgets() {
|
| + GList* windows = gtk_window_list_toplevels();
|
| + for (GList* window = windows; window;
|
| + window = g_list_next(window)) {
|
| + NativeWidget* native_widget = NativeWidget::GetNativeWidgetForNativeView(
|
| + GTK_WIDGET(window->data));
|
| + if (native_widget) {
|
| + Widget* widget = native_widget->GetWidget();
|
| + if (widget->is_secondary_widget())
|
| + widget->Close();
|
| + }
|
| + }
|
| + g_list_free(windows);
|
| +}
|
| +
|
| +// static
|
| bool Widget::ConvertRect(const Widget* source,
|
| const Widget* target,
|
| gfx::Rect* rect) {
|
| @@ -1689,6 +1702,12 @@
|
| // NativeWidget, public:
|
|
|
| // static
|
| +NativeWidget* NativeWidget::CreateNativeWidget(
|
| + internal::NativeWidgetDelegate* delegate) {
|
| + return new WidgetGtk(delegate);
|
| +}
|
| +
|
| +// static
|
| NativeWidget* NativeWidget::GetNativeWidgetForNativeView(
|
| gfx::NativeView native_view) {
|
| if (!native_view)
|
| @@ -1740,4 +1759,40 @@
|
| reinterpret_cast<gpointer>(children));
|
| }
|
|
|
| +// static
|
| +void NativeWidget::ReparentNativeView(gfx::NativeView native_view,
|
| + gfx::NativeView new_parent) {
|
| + if (!native_view)
|
| + return;
|
| +
|
| + gfx::NativeView previous_parent = gtk_widget_get_parent(native_view);
|
| + if (previous_parent == new_parent)
|
| + return;
|
| +
|
| + NativeWidgets widgets;
|
| + GetAllNativeWidgets(native_view, &widgets);
|
| +
|
| + // First notify all the widgets that they are being disassociated
|
| + // from their previous parent.
|
| + for (NativeWidgets::iterator it = widgets.begin();
|
| + it != widgets.end(); ++it) {
|
| + // TODO(beng): Rename this notification to NotifyNativeViewChanging()
|
| + // and eliminate the bool parameter.
|
| + (*it)->GetWidget()->NotifyNativeViewHierarchyChanged(false,
|
| + previous_parent);
|
| + }
|
| +
|
| + if (gtk_widget_get_parent(native_view))
|
| + gtk_widget_reparent(native_view, new_parent);
|
| + else
|
| + gtk_container_add(GTK_CONTAINER(new_parent), native_view);
|
| +
|
| + // And now, notify them that they have a brand new parent.
|
| + for (NativeWidgets::iterator it = widgets.begin();
|
| + it != widgets.end(); ++it) {
|
| + (*it)->GetWidget()->NotifyNativeViewHierarchyChanged(true,
|
| + new_parent);
|
| + }
|
| +}
|
| +
|
| } // namespace views
|
|
|