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 | |
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')
-rw-r--r-- | views/widget/drop_target_gtk.cc | 10 | ||||
-rw-r--r-- | views/widget/native_widget.h | 26 | ||||
-rw-r--r-- | views/widget/native_widget_delegate.h | 4 | ||||
-rw-r--r-- | views/widget/native_widget_test_utils_gtk.cc | 4 | ||||
-rw-r--r-- | views/widget/native_widget_test_utils_win.cc | 4 | ||||
-rw-r--r-- | views/widget/tooltip_manager_gtk.cc | 6 | ||||
-rw-r--r-- | views/widget/widget.cc | 59 | ||||
-rw-r--r-- | views/widget/widget.h | 92 | ||||
-rw-r--r-- | views/widget/widget_gtk.cc | 223 | ||||
-rw-r--r-- | views/widget/widget_gtk.h | 59 | ||||
-rw-r--r-- | views/widget/widget_win.cc | 192 | ||||
-rw-r--r-- | views/widget/widget_win.h | 42 | ||||
-rw-r--r-- | views/widget/widget_win_unittest.cc | 2 |
13 files changed, 432 insertions, 291 deletions
diff --git a/views/widget/drop_target_gtk.cc b/views/widget/drop_target_gtk.cc index 5025ae4..c135d91 100644 --- a/views/widget/drop_target_gtk.cc +++ b/views/widget/drop_target_gtk.cc @@ -167,7 +167,7 @@ gboolean DropTargetGtk::OnDragDrop(GdkDragContext* context, if (!pending_view_) { // User isn't over a view, no drop can occur. static_cast<WidgetGtk*>( - helper_.root_view()->GetWidget())->ResetDropTarget(); + helper_.root_view()->GetWidget()->native_widget())->ResetDropTarget(); // WARNING: we've been deleted. return FALSE; } @@ -246,7 +246,8 @@ void DropTargetGtk::FinishDrop(GdkDragContext* context, gtk_drag_finish(context, gdk_action != 0, (gdk_action & GDK_ACTION_MOVE), time); - static_cast<WidgetGtk*>(helper_.root_view()->GetWidget())->ResetDropTarget(); + static_cast<WidgetGtk*>(helper_.root_view()->GetWidget()->native_widget())-> + ResetDropTarget(); // WARNING: we've been deleted. } @@ -264,9 +265,8 @@ void DropTargetGtk::RequestFormats(GdkDragContext* context, int formats, const std::set<GdkAtom>& custom_formats, guint time) { - GtkWidget* widget = - static_cast<WidgetGtk*>(helper_.root_view()->GetWidget())-> - window_contents(); + GtkWidget* widget = static_cast<WidgetGtk*>(helper_.root_view()->GetWidget()-> + native_widget())->window_contents(); const std::set<GdkAtom>& known_formats = data_provider().known_custom_formats(); diff --git a/views/widget/native_widget.h b/views/widget/native_widget.h index 451a0e9..c672044 100644 --- a/views/widget/native_widget.h +++ b/views/widget/native_widget.h @@ -36,6 +36,11 @@ class NativeWidget { virtual ~NativeWidget() {} + // Creates an appropriate default NativeWidget implementation for the current + // OS/circumstance. + static NativeWidget* CreateNativeWidget( + internal::NativeWidgetDelegate* delegate); + // Retrieves the NativeWidget implementation associated with the given // NativeView or Window, or NULL if the supplied handle has no associated // NativeView. @@ -64,6 +69,19 @@ class NativeWidget { // Returns the Widget associated with this NativeWidget. This function is // guaranteed to return non-NULL for the lifetime of the NativeWidget. virtual Widget* GetWidget() = 0; + virtual const Widget* GetWidget() const = 0; + + // Returns the NativeView/Window associated with this NativeWidget. + virtual gfx::NativeView GetNativeView() const = 0; + virtual gfx::NativeWindow GetNativeWindow() const = 0; + + // Returns the enclosing Window, or NULL if there is no enclosing Window. + virtual Window* GetContainingWindow() = 0; + virtual const Window* GetContainingWindow() const = 0; + + // Notifies the NativeWidget that a view was removed from the Widget's view + // hierarchy. + virtual void ViewRemoved(View* view) = 0; // Sets/Gets a native window property on the underlying native window object. // Returns NULL if the property does not exist. Setting the property value to @@ -78,6 +96,11 @@ class NativeWidget { // Returns true if a system screen reader is active for the NativeWidget. virtual bool IsScreenReaderActive() const = 0; + // Notify native Accessibility clients of an event. + virtual void SendNativeAccessibilityEvent( + View* view, + ui::AccessibilityTypes::Event event_type) = 0; + // Sets or releases event capturing for this native widget. virtual void SetMouseCapture() = 0; virtual void ReleaseMouseCapture() = 0; @@ -85,6 +108,9 @@ class NativeWidget { // Returns true if this native widget is capturing all events. virtual bool HasMouseCapture() const = 0; + // Returns true if any mouse button is currently pressed. + virtual bool IsMouseButtonDown() const = 0; + // Returns the InputMethod for this native widget. // Note that all widgets in a widget hierarchy share the same input method. // TODO(suzhe): rename to GetInputMethod() when NativeWidget implementation diff --git a/views/widget/native_widget_delegate.h b/views/widget/native_widget_delegate.h index 036bb48..05af457 100644 --- a/views/widget/native_widget_delegate.h +++ b/views/widget/native_widget_delegate.h @@ -50,6 +50,10 @@ class NativeWidgetDelegate { virtual bool OnKeyEvent(const KeyEvent& event) = 0; virtual bool OnMouseEvent(const MouseEvent& event) = 0; virtual void OnMouseCaptureLost() = 0; + + // + virtual Widget* AsWidget() = 0; + virtual const Widget* AsWidget() const = 0; }; } // namespace internal diff --git a/views/widget/native_widget_test_utils_gtk.cc b/views/widget/native_widget_test_utils_gtk.cc index 6c478f2..2e0a820 100644 --- a/views/widget/native_widget_test_utils_gtk.cc +++ b/views/widget/native_widget_test_utils_gtk.cc @@ -16,7 +16,7 @@ NativeWidget* CreateNativeWidget() { } NativeWidget* CreateNativeWidgetWithContents(View* contents_view) { - Widget* widget = Widget::CreateWidget(); + Widget* widget = new Widget; Widget::InitParams params(Widget::InitParams::TYPE_WINDOW); params.delete_on_destroy = false; params.bounds = gfx::Rect(10, 10, 200, 200); @@ -25,7 +25,7 @@ NativeWidget* CreateNativeWidgetWithContents(View* contents_view) { } NativeWidget* CreateNativeWidgetWithParent(NativeWidget* parent) { - Widget* widget = Widget::CreateWidget(); + Widget* widget = new Widget; Widget::InitParams params(Widget::InitParams::TYPE_CONTROL); params.delete_on_destroy = false; params.parent = parent ? parent->GetWidget()->GetNativeView() : NULL; diff --git a/views/widget/native_widget_test_utils_win.cc b/views/widget/native_widget_test_utils_win.cc index 59e1d8d..fd89efe 100644 --- a/views/widget/native_widget_test_utils_win.cc +++ b/views/widget/native_widget_test_utils_win.cc @@ -15,7 +15,7 @@ NativeWidget* CreateNativeWidget() { } NativeWidget* CreateNativeWidgetWithContents(View* contents_view) { - Widget* widget = Widget::CreateWidget(); + Widget* widget = new Widget; Widget::InitParams params(Widget::InitParams::TYPE_WINDOW); params.delete_on_destroy = false; params.bounds = gfx::Rect(10, 10, 200, 200); @@ -24,7 +24,7 @@ NativeWidget* CreateNativeWidgetWithContents(View* contents_view) { } NativeWidget* CreateNativeWidgetWithParent(NativeWidget* parent) { - Widget* widget = Widget::CreateWidget(); + Widget* widget = new Widget; Widget::InitParams params(Widget::InitParams::TYPE_CONTROL); params.delete_on_destroy = false; params.child = false; // Implicitly set to true by ctor with TYPE_CONTROL. diff --git a/views/widget/tooltip_manager_gtk.cc b/views/widget/tooltip_manager_gtk.cc index dfc0e39..7c8c0dd 100644 --- a/views/widget/tooltip_manager_gtk.cc +++ b/views/widget/tooltip_manager_gtk.cc @@ -85,12 +85,12 @@ bool TooltipManagerGtk::ShowTooltip(int x, int y, bool for_keyboard, view = keyboard_view_; view_loc.SetPoint(view->width() / 2, view->height() / 2); } else if (!for_keyboard) { - RootView* root_view = widget_->GetRootView(); + RootView* root_view = widget_->GetWidget()->GetRootView(); view = root_view->GetEventHandlerForPoint(gfx::Point(x, y)); view_loc.SetPoint(x, y); View::ConvertPointFromWidget(view, &view_loc); } else { - FocusManager* focus_manager = widget_->GetFocusManager(); + FocusManager* focus_manager = widget_->GetWidget()->GetFocusManager(); if (focus_manager) { view = focus_manager->GetFocusedView(); if (view) @@ -116,7 +116,7 @@ bool TooltipManagerGtk::ShowTooltip(int x, int y, bool for_keyboard, int max_width, line_count; gfx::Point screen_loc(x, y); - View::ConvertPointToScreen(widget_->GetRootView(), &screen_loc); + View::ConvertPointToScreen(widget_->GetWidget()->GetRootView(), &screen_loc); TrimTooltipToFit(&text, &max_width, &line_count, screen_loc.x(), screen_loc.y()); tooltip_window_.SetTooltipText(text); diff --git a/views/widget/widget.cc b/views/widget/widget.cc index a7c03d9..e02f8f9d 100644 --- a/views/widget/widget.cc +++ b/views/widget/widget.cc @@ -9,6 +9,7 @@ #include "ui/gfx/compositor/compositor.h" #include "views/focus/view_storage.h" #include "views/ime/input_method.h" +#include "views/views_delegate.h" #include "views/widget/default_theme_provider.h" #include "views/widget/root_view.h" #include "views/widget/native_widget.h" @@ -21,6 +22,7 @@ namespace views { Widget::InitParams::InitParams() : type(TYPE_WINDOW), child(false), + transient(false), transparent(false), accept_events(true), can_activate(true), @@ -37,6 +39,7 @@ Widget::InitParams::InitParams() Widget::InitParams::InitParams(Type type) : type(type), child(type == TYPE_CONTROL), + transient(type == TYPE_POPUP || type == TYPE_MENU), transparent(false), accept_events(true), can_activate(type != TYPE_POPUP && type != TYPE_MENU), @@ -63,41 +66,50 @@ Widget::Widget() last_mouse_event_was_move_(false), native_widget_(NULL), widget_delegate_(NULL), - dragged_view_(NULL) { + dragged_view_(NULL), + delete_on_destroy_(false), + is_secondary_widget_(true) { } Widget::~Widget() { + DestroyRootView(); + + if (!delete_on_destroy_) + delete native_widget_; } void Widget::Init(const InitParams& params) { + delete_on_destroy_ = params.delete_on_destroy; + native_widget_ = + params.native_widget ? params.native_widget + : NativeWidget::CreateNativeWidget(this); GetRootView(); default_theme_provider_.reset(new DefaultThemeProvider); + if (params.type == InitParams::TYPE_MENU) + is_mouse_button_pressed_ = native_widget_->IsMouseButtonDown(); native_widget_->InitNativeWidget(params); } // Unconverted methods (see header) -------------------------------------------- gfx::NativeView Widget::GetNativeView() const { - return NULL; + return native_widget_->GetNativeView(); } gfx::NativeWindow Widget::GetNativeWindow() const { - return NULL; -} - -void Widget::GenerateMousePressedForView(View* view, const gfx::Point& point) { + return native_widget_->GetNativeWindow(); } bool Widget::GetAccelerator(int cmd_id, ui::Accelerator* accelerator) { return false; } -Window* Widget::GetWindow() { - return NULL; +Window* Widget::GetContainingWindow() { + return native_widget_->GetContainingWindow(); } -const Window* Widget::GetWindow() const { - return NULL; +const Window* Widget::GetContainingWindow() const { + return native_widget_->GetContainingWindow(); } void Widget::ViewHierarchyChanged(bool is_add, View* parent, View* child) { @@ -108,7 +120,8 @@ void Widget::ViewHierarchyChanged(bool is_add, View* parent, View* child) { FocusManager* focus_manager = GetFocusManager(); if (focus_manager) focus_manager->ViewRemoved(child); - ViewStorage::GetInstance()->ViewRemoved(parent, child); + ViewStorage::GetInstance()->ViewRemoved(child); + native_widget_->ViewRemoved(child); } } @@ -273,6 +286,10 @@ void Widget::SetCursor(gfx::NativeCursor cursor) { native_widget_->SetCursor(cursor); } +void Widget::ResetLastMouseMoveFlag() { + last_mouse_event_was_move_ = false; +} + FocusTraversable* Widget::GetFocusTraversable() { return root_view_.get(); } @@ -293,6 +310,18 @@ void Widget::SetFocusTraversableParentView(View* parent_view) { root_view_->SetFocusTraversableParentView(parent_view); } +void Widget::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); + + if (send_native_event) + native_widget_->SendNativeAccessibilityEvent(view, event_type); +} + //////////////////////////////////////////////////////////////////////////////// // Widget, NativeWidgetDelegate implementation: @@ -407,6 +436,14 @@ void Widget::OnMouseCaptureLost() { is_mouse_button_pressed_ = false; } +Widget* Widget::AsWidget() { + return this; +} + +const Widget* Widget::AsWidget() const { + return this; +} + //////////////////////////////////////////////////////////////////////////////// // Widget, FocusTraversable implementation: diff --git a/views/widget/widget.h b/views/widget/widget.h index 110ee20..3c74618 100644 --- a/views/widget/widget.h +++ b/views/widget/widget.h @@ -52,12 +52,20 @@ class Window; // Widget is a platform-independent type that communicates with a platform or // context specific NativeWidget implementation. // -// TODO(beng): Note that this class being non-abstract means that we have a -// violation of Google style in that we are using multiple -// inheritance. The intention is to split this into a separate -// object associated with but not equal to a NativeWidget -// implementation. Multiple inheritance is required for this -// transitional step. +// A special note on ownership: +// +// Depending on the value of "delete_on_destroy", the Widget either owns or +// is owned by its NativeWidget: +// +// delete_on_destroy = true (default) +// The Widget instance is owned by its NativeWidget. When the NativeWidget +// is destroyed (in response to a native destruction message), it deletes +// the Widget from its destructor. +// delete_on_destroy = false (non-default) +// The Widget instance owns its NativeWidget. This state implies someone +// else wants to control the lifetime of this object. When they destroy +// the Widget it is responsible for destroying the NativeWidget (from its +// destructor). // class Widget : public internal::NativeWidgetDelegate, public FocusTraversable { @@ -76,6 +84,7 @@ class Widget : public internal::NativeWidgetDelegate, Type type; bool child; + bool transient; bool transparent; bool accept_events; bool can_activate; @@ -95,13 +104,14 @@ class Widget : public internal::NativeWidgetDelegate, Widget(); virtual ~Widget(); - // Creates a Widget instance with the supplied params. - static Widget* CreateWidget(); - // Enumerates all windows pertaining to us and notifies their // view hierarchies that the locale has changed. static void NotifyLocaleChanged(); + // Closes all Widgets that aren't identified as "secondary widgets". Called + // during application shutdown when the last non-secondary widget is closed. + static void CloseAllSecondaryWidgets(); + // Converts a rectangle from one Widget's coordinate system to another's. // Returns false if the conversion couldn't be made, because either these two // Widgets do not have a common ancestor or they are not on the screen yet. @@ -114,22 +124,15 @@ class Widget : public internal::NativeWidgetDelegate, // Unconverted methods ------------------------------------------------------- - // TODO(beng): - // Widget subclasses are still implementing these methods by overriding from - // here rather than by implementing NativeWidget. + // TODO(beng): reorder, they've been converted now. // Returns the gfx::NativeView associated with this Widget. - virtual gfx::NativeView GetNativeView() const; + gfx::NativeView GetNativeView() const; // Returns the gfx::NativeWindow associated with this Widget. This may return // NULL on some platforms if the widget was created with a type other than // TYPE_WINDOW. - virtual gfx::NativeWindow GetNativeWindow() const; - - // Starts a drag operation for the specified view. |point| is a position in - // |view| coordinates that the drag was initiated from. - virtual void GenerateMousePressedForView(View* view, - const gfx::Point& point); + gfx::NativeWindow GetNativeWindow() const; // Returns the accelerator given a command id. Returns false if there is // no accelerator associated with a given id, which is a common condition. @@ -137,15 +140,15 @@ class Widget : public internal::NativeWidgetDelegate, // Returns the Window containing this Widget, or NULL if not contained in a // window. - virtual Window* GetWindow(); - virtual const Window* GetWindow() const; + Window* GetContainingWindow(); + const Window* GetContainingWindow() const; // Forwarded from the RootView so that the widget can do any cleanup. - virtual void ViewHierarchyChanged(bool is_add, View* parent, View* child); + void ViewHierarchyChanged(bool is_add, View* parent, View* child); // Performs any necessary cleanup and forwards to RootView. - virtual void NotifyNativeViewHierarchyChanged(bool attached, - gfx::NativeView native_view); + void NotifyNativeViewHierarchyChanged(bool attached, + gfx::NativeView native_view); // Converted methods --------------------------------------------------------- @@ -188,7 +191,7 @@ class Widget : public internal::NativeWidgetDelegate, void SetShape(gfx::NativeRegion shape); // Hides the widget then closes it after a return to the message loop. - void Close(); + virtual void Close(); // TODO(beng): Move off public API. // Closes the widget immediately. Compare to |Close|. This will destroy the @@ -212,6 +215,16 @@ class Widget : public internal::NativeWidgetDelegate, // Returns the RootView contained by this Widget. RootView* GetRootView(); + // A secondary widget is one that is automatically closed (via Close()) when + // all non-secondary widgets are closed. + // Default is true. + // TODO(beng): This is an ugly API, should be handled implicitly via + // transience. + void set_is_secondary_widget(bool is_secondary_widget) { + is_secondary_widget_ = is_secondary_widget; + } + bool is_secondary_widget() const { return is_secondary_widget_; } + // Returns whether the Widget is visible to the user. bool IsVisible() const; @@ -257,6 +270,12 @@ class Widget : public internal::NativeWidgetDelegate, // before the current is restored. void SetCursor(gfx::NativeCursor cursor); + // Resets the last move flag so that we can go around the optimization + // that disregards duplicate mouse moves when ending animation requires + // a new hit-test to do some highlighting as in TabStrip::RemoveTabAnimation + // to cause the close button to highlight. + void ResetLastMouseMoveFlag(); + // Retrieves the focus traversable for this widget. FocusTraversable* GetFocusTraversable(); @@ -280,10 +299,10 @@ class Widget : public internal::NativeWidgetDelegate, // cases where the view is a native control that's already sending a // native accessibility event and the duplicate event would cause // problems. - virtual void NotifyAccessibilityEvent( + void NotifyAccessibilityEvent( View* view, ui::AccessibilityTypes::Event event_type, - bool send_native_event) = 0; + bool send_native_event); NativeWidget* native_widget() { return native_widget_; } @@ -299,6 +318,8 @@ class Widget : public internal::NativeWidgetDelegate, virtual bool OnKeyEvent(const KeyEvent& event) OVERRIDE; virtual bool OnMouseEvent(const MouseEvent& event) OVERRIDE; virtual void OnMouseCaptureLost() OVERRIDE; + virtual Widget* AsWidget() OVERRIDE; + virtual const Widget* AsWidget() const OVERRIDE; // Overridden from FocusTraversable: virtual FocusSearch* GetFocusSearch() OVERRIDE; @@ -306,6 +327,9 @@ class Widget : public internal::NativeWidgetDelegate, virtual View* GetFocusTraversableParentView() OVERRIDE; protected: + // TODO(beng): Remove WidgetGtk's dependence on the mouse state flags. + friend class WidgetGtk; + // Creates the RootView to be used within this Widget. Subclasses may override // to create custom RootViews that do specialized event processing. // TODO(beng): Investigate whether or not this is needed. @@ -316,19 +340,15 @@ class Widget : public internal::NativeWidgetDelegate, // TODO(beng): remove once we fold those objects onto this one. void DestroyRootView(); - // TODO(beng): Temporarily provided as a way to associate the subclass' - // implementation of NativeWidget with this. - void set_native_widget(NativeWidget* native_widget) { - native_widget_ = native_widget; - } - // Used for testing. void ReplaceFocusManager(FocusManager* focus_manager); + // TODO(beng): Remove WidgetGtk's dependence on these: // TODO(msw): Make this mouse state member private. // If true, the mouse is currently down. bool is_mouse_button_pressed_; + // TODO(beng): Remove WidgetGtk's dependence on these: // TODO(msw): Make these mouse state members private. // The following are used to detect duplicate mouse move events and not // deliver them. Displaying a window may result in the system generating @@ -370,6 +390,12 @@ class Widget : public internal::NativeWidgetDelegate, // The compositor for accelerated drawing. scoped_refptr<ui::Compositor> compositor_; + // See class documentation for Widget above for a note about ownership. + bool delete_on_destroy_; + + // See set_is_secondary_widget(). + bool is_secondary_widget_; + DISALLOW_COPY_AND_ASSIGN(Widget); }; 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 diff --git a/views/widget/widget_gtk.h b/views/widget/widget_gtk.h index eaa29cd..54acfa6 100644 --- a/views/widget/widget_gtk.h +++ b/views/widget/widget_gtk.h @@ -41,25 +41,13 @@ class NativeWidgetDelegate; } // Widget implementation for GTK. -class WidgetGtk : public Widget, - public NativeWidget, +class WidgetGtk : public NativeWidget, public ui::ActiveWindowWatcherX::Observer, public internal::InputMethodDelegate { public: - WidgetGtk(); + explicit WidgetGtk(internal::NativeWidgetDelegate* delegate); virtual ~WidgetGtk(); - // Marks this window as transient to its parent. A window that is transient - // to its parent results in the parent rendering active when the child is - // active. - // This must be invoked before Init. This is only used for types other than - // TYPE_CHILD. The default is false. - // See gtk_window_set_transient_for for details. - void make_transient_to_parent() { - DCHECK(!widget_); - transient_to_parent_ = true; - } - // Returns the transient parent. See make_transient_to_parent for details on // what the transient parent is. GtkWindow* GetTransientParent() const; @@ -123,19 +111,6 @@ class WidgetGtk : public Widget, // Overridden from ui::ActiveWindowWatcherX::Observer. virtual void ActiveWindowChanged(GdkWindow* active_window); - // Overridden from Widget: - virtual gfx::NativeView GetNativeView() const; - virtual gfx::NativeWindow GetNativeWindow() const; - virtual bool GetAccelerator(int cmd_id, ui::Accelerator* accelerator); - virtual Window* GetWindow(); - virtual const Window* GetWindow() const; - virtual void ViewHierarchyChanged(bool is_add, View *parent, - View *child); - virtual void NotifyAccessibilityEvent( - View* view, - ui::AccessibilityTypes::Event event_type, - bool send_native_event); - // Clears the focus on the native widget having the focus. virtual void ClearNativeFocus(); @@ -168,16 +143,30 @@ class WidgetGtk : public Widget, // detached widget. static void RegisterChildExposeHandler(GtkWidget* widget); + void set_focus_on_creation(bool focus_on_creation) { + focus_on_creation_ = focus_on_creation; + } + // Overridden from NativeWidget: - virtual void InitNativeWidget(const InitParams& params) OVERRIDE; + virtual void InitNativeWidget(const Widget::InitParams& params) OVERRIDE; virtual Widget* GetWidget() OVERRIDE; + virtual const Widget* GetWidget() const OVERRIDE; + virtual gfx::NativeView GetNativeView() const OVERRIDE; + virtual gfx::NativeWindow GetNativeWindow() const OVERRIDE; + virtual Window* GetContainingWindow() OVERRIDE; + virtual const Window* GetContainingWindow() const OVERRIDE; + virtual void ViewRemoved(View* view) OVERRIDE; virtual void SetNativeWindowProperty(const char* name, void* value) OVERRIDE; virtual void* GetNativeWindowProperty(const char* name) OVERRIDE; virtual TooltipManager* GetTooltipManager() const OVERRIDE; virtual bool IsScreenReaderActive() const OVERRIDE; + virtual void SendNativeAccessibilityEvent( + View* view, + ui::AccessibilityTypes::Event event_type) OVERRIDE; virtual void SetMouseCapture() OVERRIDE; virtual void ReleaseMouseCapture() OVERRIDE; virtual bool HasMouseCapture() const OVERRIDE; + virtual bool IsMouseButtonDown() const OVERRIDE; virtual InputMethod* GetInputMethodNative() OVERRIDE; virtual void ReplaceInputMethod(InputMethod* input_method) OVERRIDE; virtual gfx::Rect GetWindowScreenBounds() const OVERRIDE; @@ -268,16 +257,13 @@ class WidgetGtk : public Widget, class DropObserver; friend class DropObserver; - // Overridden from Widget - virtual RootView* CreateRootView() OVERRIDE; - // Overridden from NativeWidget virtual gfx::AcceleratedWidget GetAcceleratedWidget() OVERRIDE; // Overridden from internal::InputMethodDelegate virtual void DispatchKeyEventPostIME(const KeyEvent& key) OVERRIDE; - void SetInitParams(const InitParams& params); + void SetInitParams(const Widget::InitParams& params); // This is called only when the window is transparent. CHROMEGTK_CALLBACK_1(WidgetGtk, gboolean, OnWindowPaint, GdkEventExpose*); @@ -291,7 +277,7 @@ class WidgetGtk : public Widget, static Window* GetWindowImpl(GtkWidget* widget); // Creates the GtkWidget. - void CreateGtkWidget(const InitParams& params); + void CreateGtkWidget(const Widget::InitParams& params); // Invoked from create widget to enable the various bits needed for a // transparent background. This is only invoked if MakeTransparent has been @@ -307,6 +293,7 @@ class WidgetGtk : public Widget, GdkEventExpose* event); // A delegate implementation that handles events received here. + // See class documentation for Widget in widget.h for a note about ownership. internal::NativeWidgetDelegate* delegate_; // Our native views. If we're a window/popup, then widget_ is the window and @@ -333,7 +320,7 @@ class WidgetGtk : public Widget, // The following factory is used to delay destruction. ScopedRunnableMethodFactory<WidgetGtk> close_widget_factory_; - // See description above setter. + // See class documentation for Widget in widget.h for a note about ownership. bool delete_on_destroy_; // See description above make_transparent for details. @@ -385,6 +372,10 @@ class WidgetGtk : public Widget, // this to determine whether we should process the event. bool has_focus_; + // Whether we should SetFocus() on a newly created window after + // Init(). Defaults to true. + bool focus_on_creation_; + // If true, the window stays on top of the screen. This is only used // for types other than TYPE_CHILD. bool always_on_top_; diff --git a/views/widget/widget_win.cc b/views/widget/widget_win.cc index a5d2044..67166ff 100644 --- a/views/widget/widget_win.cc +++ b/views/widget/widget_win.cc @@ -132,8 +132,8 @@ bool WidgetWin::screen_reader_active_ = false; //////////////////////////////////////////////////////////////////////////////// // WidgetWin, public: -WidgetWin::WidgetWin() - : ALLOW_THIS_IN_INITIALIZER_LIST(delegate_(this)), +WidgetWin::WidgetWin(internal::NativeWidgetDelegate* delegate) + : delegate_(delegate), close_widget_factory_(this), active_mouse_tracking_flags_(0), use_layered_buffer_(false), @@ -147,14 +147,14 @@ WidgetWin::WidgetWin() accessibility_view_events_(kMaxAccessibilityViewEvents), previous_cursor_(NULL), is_input_method_win_(false) { - set_native_widget(this); } WidgetWin::~WidgetWin() { // We need to delete the input method before calling DestroyRootView(), // because it'll set focus_manager_ to NULL. input_method_.reset(); - DestroyRootView(); + if (delete_on_destroy_) + delete delegate_; } // static @@ -192,7 +192,24 @@ void WidgetWin::ClearAccessibilityViewEvent(View* view) { } //////////////////////////////////////////////////////////////////////////////// -// WidgetWin, Widget implementation: +// WidgetWin, NativeWidget implementation: + +void WidgetWin::InitNativeWidget(const Widget::InitParams& params) { + SetInitParams(params); + + // Create the window. + gfx::NativeView parent = params.parent_widget ? + params.parent_widget->GetNativeView() : params.parent; + WindowImpl::Init(parent, params.bounds); +} + +Widget* WidgetWin::GetWidget() { + return delegate_->AsWidget(); +} + +const Widget* WidgetWin::GetWidget() const { + return delegate_->AsWidget(); +} gfx::NativeView WidgetWin::GetNativeView() const { return WindowImpl::hwnd(); @@ -202,42 +219,19 @@ gfx::NativeWindow WidgetWin::GetNativeWindow() const { return WindowImpl::hwnd(); } -bool WidgetWin::GetAccelerator(int cmd_id, ui::Accelerator* accelerator) { - return false; -} - -Window* WidgetWin::GetWindow() { +Window* WidgetWin::GetContainingWindow() { return GetWindowImpl(hwnd()); } -const Window* WidgetWin::GetWindow() const { +const Window* WidgetWin::GetContainingWindow() const { return GetWindowImpl(hwnd()); } -void WidgetWin::ViewHierarchyChanged(bool is_add, View* parent, - View* child) { - Widget::ViewHierarchyChanged(is_add, parent, child); +void WidgetWin::ViewRemoved(View* view) { if (drop_target_.get()) - drop_target_->ResetTargetViewIfEquals(child); + drop_target_->ResetTargetViewIfEquals(view); - if (!is_add) - ClearAccessibilityViewEvent(child); -} - -//////////////////////////////////////////////////////////////////////////////// -// WidgetWin, NativeWidget implementation: - -void WidgetWin::InitNativeWidget(const Widget::InitParams& params) { - SetInitParams(params); - - // Create the window. - gfx::NativeView parent = params.parent_widget ? - params.parent_widget->GetNativeView() : params.parent; - WindowImpl::Init(parent, params.bounds); -} - -Widget* WidgetWin::GetWidget() { - return this; + ClearAccessibilityViewEvent(view); } void WidgetWin::SetNativeWindowProperty(const char* name, void* value) { @@ -265,6 +259,19 @@ bool WidgetWin::IsScreenReaderActive() const { return screen_reader_active_; } +void WidgetWin::SendNativeAccessibilityEvent( + View* view, + ui::AccessibilityTypes::Event event_type) { + // Now call the Windows-specific method to notify MSAA clients of this + // event. The widget gives us a temporary unique child ID to associate + // with this view so that clients can call get_accChild in + // NativeViewAccessibilityWin to retrieve the IAccessible associated + // with this view. + int child_id = AddAccessibilityViewEvent(view); + ::NotifyWinEvent(NativeViewAccessibilityWin::MSAAEvent(event_type), + GetNativeView(), OBJID_CLIENT, child_id); +} + void WidgetWin::SetMouseCapture() { DCHECK(!HasMouseCapture()); SetCapture(hwnd()); @@ -278,6 +285,14 @@ bool WidgetWin::HasMouseCapture() const { return GetCapture() == hwnd(); } +bool WidgetWin::IsMouseButtonDown() const { + return (GetKeyState(VK_LBUTTON) & 0x80) || + (GetKeyState(VK_RBUTTON) & 0x80) || + (GetKeyState(VK_MBUTTON) & 0x80) || + (GetKeyState(VK_XBUTTON1) & 0x80) || + (GetKeyState(VK_XBUTTON2) & 0x80); +} + InputMethod* WidgetWin::GetInputMethodNative() { return input_method_.get(); } @@ -447,26 +462,6 @@ void WidgetWin::SetCursor(gfx::NativeCursor cursor) { } } -void WidgetWin::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); - - // Now call the Windows-specific method to notify MSAA clients of this - // event. The widget gives us a temporary unique child ID to associate - // with this view so that clients can call get_accChild in - // NativeViewAccessibilityWin to retrieve the IAccessible associated - // with this view. - if (send_native_event) { - int child_id = AddAccessibilityViewEvent(view); - ::NotifyWinEvent(NativeViewAccessibilityWin::MSAAEvent(event_type), - GetNativeView(), OBJID_CLIENT, child_id); - } -} - //////////////////////////////////////////////////////////////////////////////// // WidgetWin, MessageLoop::Observer implementation: @@ -507,7 +502,7 @@ LRESULT WidgetWin::OnWndProc(UINT message, WPARAM w_param, LPARAM l_param) { PostProcessActivateMessage(this, LOWORD(w_param)); if (message == WM_ENABLE && restore_focus_when_enabled_) { restore_focus_when_enabled_ = false; - GetFocusManager()->RestoreFocusedView(); + GetWidget()->GetFocusManager()->RestoreFocusedView(); } return result; } @@ -558,7 +553,7 @@ LRESULT WidgetWin::OnCreate(CREATESTRUCT* create_struct) { props_.push_back(SetWindowSupportsRerouteMouseWheel(hwnd())); - drop_target_ = new DropTargetWin(GetRootView()); + drop_target_ = new DropTargetWin(GetWidget()->GetRootView()); // We need to add ourselves as a message loop observer so that we can repaint // aggressively if the contents of our window become invalid. Unfortunately @@ -569,10 +564,10 @@ LRESULT WidgetWin::OnCreate(CREATESTRUCT* create_struct) { // Windows special DWM window frame requires a special tooltip manager so // that window controls in Chrome windows don't flicker when you move your // mouse over them. See comment in aero_tooltip_manager.h. - if (GetThemeProvider()->ShouldUseNativeFrame()) { - tooltip_manager_.reset(new AeroTooltipManager(this)); + if (GetWidget()->GetThemeProvider()->ShouldUseNativeFrame()) { + tooltip_manager_.reset(new AeroTooltipManager(GetWidget())); } else { - tooltip_manager_.reset(new TooltipManagerWin(this)); + tooltip_manager_.reset(new TooltipManagerWin(GetWidget())); } // This message initializes the window so that focus border are shown for @@ -612,8 +607,8 @@ void WidgetWin::OnDestroy() { } void WidgetWin::OnDisplayChange(UINT bits_per_pixel, CSize screen_size) { - if (widget_delegate()) - widget_delegate()->OnDisplayChanged(); + if (GetWidget()->widget_delegate()) + GetWidget()->widget_delegate()->OnDisplayChanged(); } LRESULT WidgetWin::OnDwmCompositionChanged(UINT msg, @@ -651,7 +646,8 @@ LRESULT WidgetWin::OnGetObject(UINT uMsg, WPARAM w_param, LPARAM l_param) { if (OBJID_CLIENT == l_param) { // Retrieve MSAA dispatch object for the root view. base::win::ScopedComPtr<IAccessible> root( - NativeViewAccessibilityWin::GetAccessibleForView(GetRootView())); + NativeViewAccessibilityWin::GetAccessibleForView( + GetWidget()->GetRootView())); // Create a reference that MSAA will marshall to the client. reference_result = LresultFromObject(IID_IAccessible, w_param, @@ -789,14 +785,16 @@ LRESULT WidgetWin::OnMouseRange(UINT message, WPARAM w_param, LPARAM l_param) { } void WidgetWin::OnMove(const CPoint& point) { - if (widget_delegate()) - widget_delegate()->OnWidgetMove(); + // TODO(beng): move to Widget. + if (GetWidget()->widget_delegate()) + GetWidget()->widget_delegate()->OnWidgetMove(); SetMsgHandled(FALSE); } void WidgetWin::OnMoving(UINT param, const LPRECT new_bounds) { - if (widget_delegate()) - widget_delegate()->OnWidgetMove(); + // TODO(beng): move to Widget. + if (GetWidget()->widget_delegate()) + GetWidget()->widget_delegate()->OnWidgetMove(); } LRESULT WidgetWin::OnNCActivate(BOOL active) { @@ -893,8 +891,9 @@ LRESULT WidgetWin::OnSetText(const wchar_t* text) { } void WidgetWin::OnSettingChange(UINT flags, const wchar_t* section) { - if (flags == SPI_SETWORKAREA && widget_delegate()) - widget_delegate()->OnWorkAreaChanged(); + // TODO(beng): move to Widget. + if (flags == SPI_SETWORKAREA && GetWidget()->widget_delegate()) + GetWidget()->widget_delegate()->OnWorkAreaChanged(); SetMsgHandled(FALSE); } @@ -961,8 +960,9 @@ void WidgetWin::OnScreenReaderDetected() { } void WidgetWin::SetInitialFocus() { - View* v = widget_delegate() ? - widget_delegate()->GetInitiallyFocusedView() : NULL; + // TODO(beng): move to Widget. + View* v = GetWidget()->widget_delegate() ? + GetWidget()->widget_delegate()->GetInitiallyFocusedView() : NULL; if (v) v->RequestFocus(); } @@ -979,7 +979,7 @@ Window* WidgetWin::GetWindowImpl(HWND hwnd) { WidgetWin* widget = reinterpret_cast<WidgetWin*>(ui::GetWindowUserData(parent)); if (widget && widget->is_window_) - return static_cast<WindowWin*>(widget); + return static_cast<WindowWin*>(widget)->GetWindow(); parent = ::GetParent(parent); } return NULL; @@ -1016,7 +1016,7 @@ void WidgetWin::PostProcessActivateMessage(WidgetWin* widget, } } -void WidgetWin::SetInitParams(const InitParams& params) { +void WidgetWin::SetInitParams(const Widget::InitParams& params) { // Set non-style attributes. delete_on_destroy_ = params.delete_on_destroy; @@ -1044,21 +1044,15 @@ void WidgetWin::SetInitParams(const InitParams& params) { // Set type-dependent style attributes. switch (params.type) { - case InitParams::TYPE_WINDOW: - case InitParams::TYPE_CONTROL: + case Widget::InitParams::TYPE_WINDOW: + case Widget::InitParams::TYPE_CONTROL: break; - case InitParams::TYPE_POPUP: + case Widget::InitParams::TYPE_POPUP: style |= WS_POPUP; ex_style |= WS_EX_TOOLWINDOW; break; - case InitParams::TYPE_MENU: + case Widget::InitParams::TYPE_MENU: style |= WS_POPUP; - is_mouse_button_pressed_ = - ((GetKeyState(VK_LBUTTON) & 0x80) || - (GetKeyState(VK_RBUTTON) & 0x80) || - (GetKeyState(VK_MBUTTON) & 0x80) || - (GetKeyState(VK_XBUTTON1) & 0x80) || - (GetKeyState(VK_XBUTTON2) & 0x80)); break; default: NOTREACHED(); @@ -1089,7 +1083,7 @@ void WidgetWin::RedrawLayeredWindowContents() { layered_window_invalid_rect_.y(), layered_window_invalid_rect_.width(), layered_window_invalid_rect_.height()); - GetRootView()->Paint(layered_window_contents_.get()); + GetWidget()->GetRootView()->Paint(layered_window_contents_.get()); layered_window_contents_->restore(); RECT wr; @@ -1107,7 +1101,7 @@ void WidgetWin::RedrawLayeredWindowContents() { void WidgetWin::ClientAreaSizeChanged() { RECT r; - if (GetThemeProvider()->ShouldUseNativeFrame() || IsZoomed()) + if (GetWidget()->GetThemeProvider()->ShouldUseNativeFrame() || IsZoomed()) GetClientRect(&r); else GetWindowRect(&r); @@ -1133,13 +1127,26 @@ void WidgetWin::DispatchKeyEventPostIME(const KeyEvent& key) { // Widget, public: // static -Widget* Widget::CreateWidget() { - return new WidgetWin; +void Widget::NotifyLocaleChanged() { + NOTIMPLEMENTED(); } +namespace { +BOOL CALLBACK WindowCallbackProc(HWND hwnd, LPARAM lParam) { + NativeWidget* native_widget = + NativeWidget::GetNativeWidgetForNativeView(hwnd); + if (native_widget) { + Widget* widget = native_widget->GetWidget(); + if (widget->is_secondary_widget()) + widget->Close(); + } + return TRUE; +} +} // namespace + // static -void Widget::NotifyLocaleChanged() { - NOTIMPLEMENTED(); +void Widget::CloseAllSecondaryWidgets() { + EnumThreadWindows(GetCurrentThreadId(), WindowCallbackProc, 0); } bool Widget::ConvertRect(const Widget* source, @@ -1167,17 +1174,26 @@ bool Widget::ConvertRect(const Widget* source, //////////////////////////////////////////////////////////////////////////////// // NativeWidget, public: +// static +NativeWidget* NativeWidget::CreateNativeWidget( + internal::NativeWidgetDelegate* delegate) { + return new WidgetWin(delegate); +} + +// static NativeWidget* NativeWidget::GetNativeWidgetForNativeView( gfx::NativeView native_view) { return reinterpret_cast<WidgetWin*>( ViewProp::GetValue(native_view, kNativeWidgetKey)); } +// static NativeWidget* NativeWidget::GetNativeWidgetForNativeWindow( gfx::NativeWindow native_window) { return GetNativeWidgetForNativeView(native_window); } +// static NativeWidget* NativeWidget::GetTopLevelNativeWidget( gfx::NativeView native_view) { if (!native_view) @@ -1206,6 +1222,7 @@ NativeWidget* NativeWidget::GetTopLevelNativeWidget( return widget; } +// static void NativeWidget::GetAllNativeWidgets(gfx::NativeView native_view, NativeWidgets* children) { if (!native_view) @@ -1218,6 +1235,7 @@ void NativeWidget::GetAllNativeWidgets(gfx::NativeView native_view, reinterpret_cast<LPARAM>(children)); } +// static void NativeWidget::ReparentNativeView(gfx::NativeView native_view, gfx::NativeView new_parent) { if (!native_view) diff --git a/views/widget/widget_win.h b/views/widget/widget_win.h index 3c2974b..d013ddb 100644 --- a/views/widget/widget_win.h +++ b/views/widget/widget_win.h @@ -23,7 +23,6 @@ #include "views/ime/input_method_delegate.h" #include "views/layout/layout_manager.h" #include "views/widget/native_widget.h" -#include "views/widget/widget.h" namespace ui { class ViewProp; @@ -45,8 +44,6 @@ namespace internal { class NativeWidgetDelegate; } -RootView* GetRootViewForHWND(HWND hwnd); - // A Windows message reflected from other windows. This message is sent // with the following arguments: // hWnd - Target window @@ -80,12 +77,11 @@ const int WM_NCUAHDRAWFRAME = 0xAF; // /////////////////////////////////////////////////////////////////////////////// class WidgetWin : public ui::WindowImpl, - public Widget, public NativeWidget, public MessageLoopForUI::Observer, public internal::InputMethodDelegate { public: - WidgetWin(); + explicit WidgetWin(internal::NativeWidgetDelegate* delegate); virtual ~WidgetWin(); // Returns true if we are on Windows Vista or greater and composition is @@ -113,20 +109,6 @@ class WidgetWin : public ui::WindowImpl, // Clear a view that has recently been removed on a hierarchy change. void ClearAccessibilityViewEvent(View* view); - // Overridden from Widget: - virtual gfx::NativeView GetNativeView() const OVERRIDE; - virtual gfx::NativeWindow GetNativeWindow() const OVERRIDE; - virtual bool GetAccelerator(int cmd_id, - ui::Accelerator* accelerator) OVERRIDE; - virtual Window* GetWindow() OVERRIDE; - virtual const Window* GetWindow() const OVERRIDE; - virtual void ViewHierarchyChanged(bool is_add, View *parent, - View *child) OVERRIDE; - virtual void NotifyAccessibilityEvent( - View* view, - ui::AccessibilityTypes::Event event_type, - bool send_native_event); - BOOL IsWindow() const { return ::IsWindow(GetNativeView()); } @@ -183,24 +165,26 @@ class WidgetWin : public ui::WindowImpl, return ::GetClientRect(GetNativeView(), rect); } - // Resets the last move flag so that we can go around the optimization - // that disregards duplicate mouse moves when ending animation requires - // a new hit-test to do some highlighting as in TabStrip::RemoveTabAnimation - // to cause the close button to highlight. - void ResetLastMouseMoveFlag() { - last_mouse_event_was_move_ = false; - } - // Overridden from NativeWidget: virtual void InitNativeWidget(const Widget::InitParams& params) OVERRIDE; virtual Widget* GetWidget() OVERRIDE; + virtual const Widget* GetWidget() const OVERRIDE; + virtual gfx::NativeView GetNativeView() const OVERRIDE; + virtual gfx::NativeWindow GetNativeWindow() const OVERRIDE; + virtual Window* GetContainingWindow() OVERRIDE; + virtual const Window* GetContainingWindow() const OVERRIDE; + virtual void ViewRemoved(View* view) OVERRIDE; virtual void SetNativeWindowProperty(const char* name, void* value) OVERRIDE; virtual void* GetNativeWindowProperty(const char* name) OVERRIDE; virtual TooltipManager* GetTooltipManager() const OVERRIDE; virtual bool IsScreenReaderActive() const OVERRIDE; + virtual void SendNativeAccessibilityEvent( + View* view, + ui::AccessibilityTypes::Event event_type) OVERRIDE; virtual void SetMouseCapture() OVERRIDE; virtual void ReleaseMouseCapture() OVERRIDE; virtual bool HasMouseCapture() const OVERRIDE; + virtual bool IsMouseButtonDown() const OVERRIDE; virtual InputMethod* GetInputMethodNative() OVERRIDE; virtual void ReplaceInputMethod(InputMethod* input_method) OVERRIDE; virtual gfx::Rect GetWindowScreenBounds() const OVERRIDE; @@ -443,6 +427,7 @@ class WidgetWin : public ui::WindowImpl, virtual void DispatchKeyEventPostIME(const KeyEvent& key) OVERRIDE; // A delegate implementation that handles events received here. + // See class documentation for Widget in widget.h for a note about ownership. internal::NativeWidgetDelegate* delegate_; // The following factory is used for calls to close the WidgetWin @@ -481,8 +466,7 @@ class WidgetWin : public ui::WindowImpl, // A factory that allows us to schedule a redraw for layered windows. ScopedRunnableMethodFactory<WidgetWin> paint_layered_window_factory_; - // Whether or not the window should delete itself when it is destroyed. - // Set this to false via its setter for stack allocated instances. + // See class documentation for Widget in widget.h for a note about ownership. bool delete_on_destroy_; // True if we are allowed to update the layered window from the DIB backing diff --git a/views/widget/widget_win_unittest.cc b/views/widget/widget_win_unittest.cc index 3c13138..c9a33e8 100644 --- a/views/widget/widget_win_unittest.cc +++ b/views/widget/widget_win_unittest.cc @@ -43,7 +43,7 @@ class WidgetWinTest : public testing::Test { }; WidgetWin* WidgetWinTest::CreateWidgetWin() { - scoped_ptr<Widget> widget(Widget::CreateWidget()); + scoped_ptr<Widget> widget(new Widget); Widget::InitParams params(Widget::InitParams::TYPE_WINDOW); params.delete_on_destroy = false; params.bounds = gfx::Rect(50, 50, 650, 650); |