diff options
author | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-13 16:03:53 +0000 |
---|---|---|
committer | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-13 16:03:53 +0000 |
commit | 4672de6247fe7a865b2abeaac1b4a76c9369b7a3 (patch) | |
tree | eaa314bbb797dae5152877b1ad170f44d1eb51b4 /views/widget/widget_gtk.cc | |
parent | 37ae86f0c4b50dc83b13da17ae1a9ef7083fa76f (diff) | |
download | chromium_src-4672de6247fe7a865b2abeaac1b4a76c9369b7a3.zip chromium_src-4672de6247fe7a865b2abeaac1b4a76c9369b7a3.tar.gz chromium_src-4672de6247fe7a865b2abeaac1b4a76c9369b7a3.tar.bz2 |
Split the hierarchy.
* Widget ----
Now recognizes a supplied NativeWidget via InitParams. If this is specified then a default one is not created.
Is now created directly rather than using a factory. NativeWidget creation is not performed until Init() is called. This means some functions that rely on a NativeWidget must not be called until _AFTER_ Init() (explains some of the function call reordering in this CL, e.g. moving SetOpacity() until after Init()).
ResetLastMouseMovedFlag() moved to this API so that BaseTabStrip can call it in a cross-platform way.
Made last remaining unimplemented methods on Widget pass-thru to NativeWidget implementations.
* WidgetWin/WidgetGtk ----
The NativeWidget implementations now both require a NativeWidgetDelegate implementation upon construction. This is passed through the constructor by the static factory method NativeWidget::CreateNativeWidget and by subclasses such as WindowWin, BubbleWidgetWin, etc.
Some classes that are constructed directly (e.g. LockWindow, in ChromeOS) never have a Widget created for them, so they create the Widget themselves in their base class initializer.
Code in these classes (and their WindowWin/WindowGtk, BrowserFrameWin, BrowserFrameGtk subclasses) must now call GetWidget() etc to call Widget API methods since they are no longer subclasses.
static_casting to this (and derived) types must now be done on the Widget's native_widget().
GetWindow() is renamed to GetContainingWindow() to avoid naming conflicts.
* Window ----
Window is now a subclass of Widget.
Now recognizes a supplied NativeWindow via InitParams. If this is specified then a default one is not created.
Window::CloseWindow becomes an override of Widget::Close.
CloseAllSecondaryWindows() becomes CloseAllSecondaryWidgets() and moves to widget.h
IsAppWindow() is removed and replaced by set_is_secondary_widget on Widget.
* MenuHost ----
Subclasses Widget now.
* TabContentsViewViews ----
It looks like the Gtk-views code here was still using the old implementation of the Native version of this class - i.e. a class that subclassed TabContentsView AND WidgetGtk. A no-no. I had to write NativeTabContentsViewGtk, which is almost identical to NativeTabContentsViewWin with the Gtk bits of TabContentsViewGtk thrown in.
* BrowserFrame ----
Platform-specific functionality is now restricted to BrowserFrameWin/BrowserFrameGtk behind a NativeBrowserFrame interface. Construction is exposed via a static factory method on NativeBrowserFrame.
BrowserFrame becomes a concrete class that now subclasses Window.
As a result, it no longer needs a GetWindow() accessor method, so people with a BrowserFrame* can just call Window methods directly on it.
It is constructed directly, replacing the BrowserFrame::Create() method.
NativeBrowserFrameDelegate is no longer needed.
BrowserFrameChromeos is simpler as a couple of #ifdefs in BrowserFrame, so I got rid of that too.
* AutocompletePopupWin/Gtk ----
No longer required. AutocompletePopupContentsView now just uses a Widget directly.
* There is some lingering ugliness:
- If you set a native_window field on Window::InitParams you must also manually set widget_init_params.native_widget. I will make InitParams do more of this automatically later.
- It'd be nice for the ContentsView to be specified via InitParams. I'll get to this later.
- NativeBrowserFrame could probably disappear as an interface. It only exists to provide a couple of methods that may be implemented in other ways.
- delete_on_destroy should now be an ownership directionality enum. I will do this later.
- Secondary-widgetness should somehow be inferred from transience. Later.
- set_focus_on_creation for both the NativeWidgets should probably move to Widget if it is really needed.
- WidgetWin/Gtk::SetInitialFocus seems like it could move to Widget.
- I need to clean up function order in some cases.
BUG=72040
TEST=none
Review URL: http://codereview.chromium.org/7012006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@85269 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'views/widget/widget_gtk.cc')
-rw-r--r-- | views/widget/widget_gtk.cc | 223 |
1 files changed, 139 insertions, 84 deletions
diff --git a/views/widget/widget_gtk.cc b/views/widget/widget_gtk.cc index b506dac..bbb0fd5 100644 --- a/views/widget/widget_gtk.cc +++ b/views/widget/widget_gtk.cc @@ -284,9 +284,9 @@ bool WidgetGtk::debug_paint_enabled_ = false; //////////////////////////////////////////////////////////////////////////////// // 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 @@ WidgetGtk::WidgetGtk() 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 @@ WidgetGtk::WidgetGtk() // 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 @@ WidgetGtk::~WidgetGtk() { // 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::DoDrag(const OSExchangeData& data, int operation) { } 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::IsActiveChanged() { } 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 @@ void WidgetGtk::ActiveWindowChanged(GdkWindow* active_window) { } 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 @@ void WidgetGtk::ClearNativeFocus() { } bool WidgetGtk::HandleKeyboardEvent(const KeyEvent& key) { - if (!GetFocusManager()) + if (!GetWidget()->GetFocusManager()) return false; const int key_code = key.key_code(); @@ -569,7 +534,7 @@ bool WidgetGtk::HandleKeyboardEvent(const KeyEvent& key) { // 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 @@ bool WidgetGtk::HandleKeyboardEvent(const KeyEvent& key) { // 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 @@ void WidgetGtk::RegisterChildExposeHandler(GtkWidget* child) { //////////////////////////////////////////////////////////////////////////////// // 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,7 +731,32 @@ void WidgetGtk::InitNativeWidget(const InitParams& params) { } 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) { @@ -785,6 +775,13 @@ bool WidgetGtk::IsScreenReaderActive() const { 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 @@ bool WidgetGtk::HasMouseCapture() const { 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 @@ void WidgetGtk::OnSizeRequest(GtkWidget* widget, GtkRequisition* requisition) { // 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 @@ gboolean WidgetGtk::OnDragMotion(GtkWidget* widget, 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 @@ gboolean WidgetGtk::OnEnterNotify(GtkWidget* widget, GdkEventCrossing* event) { 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 @@ gboolean WidgetGtk::OnEnterNotify(GtkWidget* widget, GdkEventCrossing* event) { 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 @@ void WidgetGtk::HandleGtkGrabBroke() { //////////////////////////////////////////////////////////////////////////////// // 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 @@ void WidgetGtk::DispatchKeyEventPostIME(const KeyEvent& key) { 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 @@ Window* WidgetGtk::GetWindowImpl(GtkWidget* widget) { 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 @@ void WidgetGtk::CreateGtkWidget(const InitParams& params) { } 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 @@ void WidgetGtk::CreateGtkWidget(const InitParams& params) { 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 @@ void WidgetGtk::DrawTransparentBackground(GtkWidget* widget, // 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 @@ void Widget::NotifyLocaleChanged() { } // 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 @@ bool Widget::ConvertRect(const Widget* source, // 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 @@ void NativeWidget::GetAllNativeWidgets(gfx::NativeView native_view, 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 |