summaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
authorben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-01 22:14:38 +0000
committerben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-01 22:14:38 +0000
commit2a3851ec96ce92e9d51ef2737bf8a7137dad49e3 (patch)
treea0abc20bc21cef3eda852c0b2556f2ffe2b527be /ui
parent4258ecebbc45339f390bf874726014eeff2400ed (diff)
downloadchromium_src-2a3851ec96ce92e9d51ef2737bf8a7137dad49e3.zip
chromium_src-2a3851ec96ce92e9d51ef2737bf8a7137dad49e3.tar.gz
chromium_src-2a3851ec96ce92e9d51ef2737bf8a7137dad49e3.tar.bz2
sFirst cut at an experiment with what a simplified View/Widget API would look like.
Of note: - Widget is a cross-platform class encapsulating widget-specific state - NativeWidget interface wraps different implementations of a native widget. Starting with HWND. - NativeWidget implementation should eventually be swappable at runtime. - Simpler Event construction directly from a NativeEvent (e.g. MSG struct) - Simpler View API with fewer, more clearly delineated overrides. Notes: - Window* are just empty files for now while I get View/Widget to work. BUG=none TEST=see unittests, in development Review URL: http://codereview.chromium.org/6286013 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@73353 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui')
-rw-r--r--ui/views/OWNERS2
-rw-r--r--ui/views/README.chromium4
-rw-r--r--ui/views/demo/main.cc177
-rw-r--r--ui/views/events/context_menu_controller.h47
-rw-r--r--ui/views/events/drag_controller.h37
-rw-r--r--ui/views/events/event.cc44
-rw-r--r--ui/views/events/event.h190
-rw-r--r--ui/views/events/event_win.cc195
-rw-r--r--ui/views/layout/fill_layout.cc37
-rw-r--r--ui/views/layout/fill_layout.h35
-rw-r--r--ui/views/layout/layout_manager.cc15
-rw-r--r--ui/views/layout/layout_manager.h57
-rw-r--r--ui/views/native_types.h20
-rw-r--r--ui/views/rendering/border.cc69
-rw-r--r--ui/views/rendering/border.h50
-rw-r--r--ui/views/rendering/border_unittest.cc63
-rw-r--r--ui/views/run_all_unittests.cc19
-rw-r--r--ui/views/view.cc629
-rw-r--r--ui/views/view.h393
-rw-r--r--ui/views/view_unittest.cc204
-rw-r--r--ui/views/views.gyp186
-rw-r--r--ui/views/widget/native_widget.h69
-rw-r--r--ui/views/widget/native_widget_listener.h53
-rw-r--r--ui/views/widget/native_widget_views.cc10
-rw-r--r--ui/views/widget/native_widget_views.h15
-rw-r--r--ui/views/widget/native_widget_win.cc626
-rw-r--r--ui/views/widget/native_widget_win.h271
-rw-r--r--ui/views/widget/root_view.cc145
-rw-r--r--ui/views/widget/root_view.h62
-rw-r--r--ui/views/widget/widget.cc219
-rw-r--r--ui/views/widget/widget.h131
-rw-r--r--ui/views/widget/widget.rc9
-rw-r--r--ui/views/widget/widget_resource.h11
-rw-r--r--ui/views/widget/widget_unittest.cc23
-rw-r--r--ui/views/window/native_window.h3
-rw-r--r--ui/views/window/native_window_views.cc3
-rw-r--r--ui/views/window/native_window_views.h3
-rw-r--r--ui/views/window/native_window_win.cc3
-rw-r--r--ui/views/window/native_window_win.h3
-rw-r--r--ui/views/window/window.cc3
-rw-r--r--ui/views/window/window.h3
41 files changed, 4138 insertions, 0 deletions
diff --git a/ui/views/OWNERS b/ui/views/OWNERS
new file mode 100644
index 0000000..3ff71eb
--- /dev/null
+++ b/ui/views/OWNERS
@@ -0,0 +1,2 @@
+ben@chromium.org
+sky@chromium.org
diff --git a/ui/views/README.chromium b/ui/views/README.chromium
new file mode 100644
index 0000000..7975925
--- /dev/null
+++ b/ui/views/README.chromium
@@ -0,0 +1,4 @@
+This is a work-in-progress Views prototype that is not currently in use.
+
+Please contact beng with questions.
+
diff --git a/ui/views/demo/main.cc b/ui/views/demo/main.cc
new file mode 100644
index 0000000..f3b2763
--- /dev/null
+++ b/ui/views/demo/main.cc
@@ -0,0 +1,177 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <windows.h>
+#include <atlbase.h>
+#include <atlapp.h>
+#include <atlcrack.h>
+#include <atlmisc.h>
+
+#include "base/at_exit.h"
+#include "base/message_loop.h"
+#include "gfx/canvas.h"
+#include "ui/views/view.h"
+#include "ui/views/widget/widget.h"
+#include "ui/views/widget/native_widget_win.h"
+
+class V2DemoDispatcher : public MessageLoopForUI::Dispatcher {
+ public:
+ V2DemoDispatcher() {}
+ virtual ~V2DemoDispatcher() {}
+
+ private:
+ // Overridden from MessageLoopForUI::Dispatcher:
+ virtual bool Dispatch(const MSG& msg) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ return true;
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(V2DemoDispatcher);
+};
+
+class ColorView : public ui::View {
+ public:
+ explicit ColorView(SkColor color) : color_(color) {
+ }
+ ColorView() : color_(SK_ColorBLACK) {}
+ virtual ~ColorView() {}
+
+ protected:
+ SkColor color() const { return color_; }
+ void set_color(SkColor color) { color_ = color; }
+
+ private:
+ // Overridden from ui::View:
+ virtual void OnPaint(gfx::Canvas* canvas) {
+ canvas->FillRectInt(color_, 0, 0, width(), height());
+ }
+ virtual bool OnMousePressed(const ui::MouseEvent& event) {
+ color_ = color_ == SK_ColorBLACK ? SK_ColorWHITE : SK_ColorBLACK;
+ Invalidate();
+ return true;
+ }
+ virtual void OnMouseReleased(const ui::MouseEvent& event, bool canceled) {
+ color_ = color_ == SK_ColorWHITE ? SK_ColorMAGENTA : SK_ColorGREEN;
+ Invalidate();
+ }
+ virtual void OnMouseMoved(const ui::MouseEvent& event) {
+ U8CPU r = SkColorGetR(color_);
+ color_ = SkColorSetRGB(++r % 255, SkColorGetG(color_),
+ SkColorGetB(color_));
+ Invalidate();
+ }
+ virtual bool OnMouseDragged(const ui::MouseEvent& event) {
+ U8CPU g = SkColorGetG(color_);
+ color_ = SkColorSetRGB(SkColorGetR(color_), ++g % 255,
+ SkColorGetB(color_));
+ Invalidate();
+ return true;
+ }
+
+ SkColor color_;
+
+ DISALLOW_COPY_AND_ASSIGN(ColorView);
+};
+
+class FancyPantsView : public ColorView {
+ public:
+ FancyPantsView()
+ : ColorView(SK_ColorMAGENTA),
+ c1_(new ColorView(SK_ColorGREEN)),
+ c2_(new ColorView(SK_ColorRED)) {
+ AddChildView(c1_);
+ AddChildView(c2_);
+ }
+ virtual ~FancyPantsView() {}
+
+ // Overridden from ui::View:
+ virtual void Layout() {
+ c1_->SetBounds(20, 20, width() - 40, height() - 40);
+ c2_->SetBounds(50, 50, 50, 50);
+ Invalidate();
+ }
+ virtual bool OnMousePressed(const ui::MouseEvent& event) {
+ old_color_ = color();
+ set_color(SK_ColorWHITE);
+ mouse_offset_ = event.location();
+ return true;
+ }
+ virtual bool OnMouseDragged(const ui::MouseEvent& event) {
+ gfx::Rect old_bounds = bounds();
+ SetPosition(gfx::Point(event.x() - mouse_offset_.x(),
+ event.y() - mouse_offset_.y()));
+ gfx::Rect new_bounds = bounds();
+ parent()->InvalidateRect(old_bounds.Union(new_bounds));
+ return true;
+ }
+ virtual void OnMouseReleased(const ui::MouseEvent& event) {
+ set_color(old_color_);
+ }
+ virtual void OnMouseCaptureLost() {
+ set_color(SK_ColorYELLOW);
+ }
+
+ private:
+ View* c1_;
+ View* c2_;
+
+ gfx::Point mouse_offset_;
+ SkColor old_color_;
+
+ DISALLOW_COPY_AND_ASSIGN(FancyPantsView);
+};
+
+
+
+class ContentsView : public ColorView {
+ public:
+ ContentsView()
+ : c1_(new ColorView(SK_ColorBLUE)),
+ c2_(new ColorView(SK_ColorGREEN)),
+ c3_(new FancyPantsView()),
+ ColorView(SK_ColorRED) {
+ set_parent_owned(false);
+ AddChildView(c1_);
+ AddChildView(c2_);
+ c3_->SetPosition(gfx::Point(200, 200));
+ AddChildView(c3_);
+ }
+
+ virtual ~ContentsView() {}
+
+ void Init() {
+ //c3_->SetHasLayer(true);
+ }
+
+ private:
+ // Overridden from ui::View:
+ virtual void Layout() {
+ c1_->SetBounds(20, 20, width() - 40, height() - 40);
+ c2_->SetBounds(50, 50, 50, 50);
+ c3_->SetSize(gfx::Size(75, 75));
+ Invalidate();
+ }
+
+ View* c1_;
+ View* c2_;
+ FancyPantsView* c3_;
+};
+
+int main(int argc, char **argv) {
+ OleInitialize(NULL);
+ base::AtExitManager exit_manager;
+ MessageLoop main_message_loop(MessageLoop::TYPE_UI);
+
+ ContentsView cv;
+ ui::Widget widget(&cv);
+ widget.InitWithNativeViewParent(NULL, gfx::Rect(20, 20, 400, 400));
+ cv.Init();
+ widget.Show();
+
+ V2DemoDispatcher dispatcher;
+ MessageLoopForUI::current()->Run(&dispatcher);
+
+ OleUninitialize();
+}
diff --git a/ui/views/events/context_menu_controller.h b/ui/views/events/context_menu_controller.h
new file mode 100644
index 0000000..3b8a0b0
--- /dev/null
+++ b/ui/views/events/context_menu_controller.h
@@ -0,0 +1,47 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_EVENTS_CONTEXT_MENU_CONTROLLER_H_
+#define UI_VIEWS_EVENTS_CONTEXT_MENU_CONTROLLER_H_
+#pragma once
+
+namespace gfx {
+class Point;
+}
+
+namespace ui {
+
+class View;
+
+// ContextMenuController is responsible for showing the context menu for a
+// View. To use a ContextMenuController invoke SetContextMenuController on a
+// View. When the appropriate user gesture occurs ShowContextMenu is invoked
+// on the ContextMenuController.
+//
+// Setting a ContextMenuController on a View makes the View process mouse
+// events.
+//
+// It is up to subclasses that do their own mouse processing to invoke
+// the appropriate ContextMenuController method, typically by invoking super's
+// implementation for mouse processing.
+//
+class ContextMenuController {
+ public:
+ // Invoked to show the context menu for the source view. If |is_mouse_gesture|
+ // is true, |point| is the location of the mouse. If |is_mouse_gesture| is
+ // false, this method was not invoked by a mouse gesture and |point| is the
+ // recommended location to show the menu at.
+ //
+ // |point| is in screen coordinates.
+ virtual void ShowContextMenu(View* source,
+ const gfx::Point& point,
+ bool is_mouse_gesture) = 0;
+
+ protected:
+ virtual ~ContextMenuController() {}
+};
+
+} // namespace ui
+
+#endif // UI_VIEWS_EVENTS_CONTEXT_MENU_CONTROLLER_H_
diff --git a/ui/views/events/drag_controller.h b/ui/views/events/drag_controller.h
new file mode 100644
index 0000000..4352195
--- /dev/null
+++ b/ui/views/events/drag_controller.h
@@ -0,0 +1,37 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_EVENTS_DRAG_CONTROLLER_H_
+#define UI_VIEWS_EVENTS_DRAG_CONTROLLER_H_
+#pragma once
+
+namespace ui {
+
+// DragController is responsible for writing drag data for a View, as well as
+// supplying the supported drag operations without having to subclass View.
+class DragController {
+ public:
+ // Writes the data for the drag.
+ virtual void WriteDragData(View* sender,
+ const gfx::Point& press_pt,
+ OSExchangeData* data) = 0;
+
+ // Returns the supported drag operations (see DragDropTypes for possible
+ // values). A drag is only started if this returns a non-zero value.
+ virtual int GetDragOperations(View* sender, const gfx::Point& p) = 0;
+
+ // Returns true if a drag operation can be started.
+ // |press_pt| represents the coordinates where the mouse was initially
+ // pressed down. |p| is the current mouse coordinates.
+ virtual bool CanStartDrag(View* sender,
+ const gfx::Point& press_pt,
+ const gfx::Point& p) = 0;
+
+ protected:
+ virtual ~DragController() {}
+};
+
+} // namespace ui
+
+#endif // UI_VIEWS_EVENTS_DRAG_CONTROLLER_H_
diff --git a/ui/views/events/event.cc b/ui/views/events/event.cc
new file mode 100644
index 0000000..4c62b8a
--- /dev/null
+++ b/ui/views/events/event.cc
@@ -0,0 +1,44 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/events/event.h"
+
+#include "ui/views/view.h"
+
+namespace ui {
+
+////////////////////////////////////////////////////////////////////////////////
+// Event, protected:
+
+Event::Event(EventType type, int flags)
+ : type_(type),
+ flags_(flags) {
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// LocatedEvent, protected:
+
+LocatedEvent::LocatedEvent(EventType type,
+ const gfx::Point& location,
+ int flags)
+ : Event(type, flags),
+ location_(location) {
+}
+
+LocatedEvent::LocatedEvent(const LocatedEvent& other,
+ View* source,
+ View* target)
+ : Event(other.type(), other.flags()) {
+ location_ = other.location();
+ View::ConvertPointToView(source, target, &location_);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// MouseEvent, public:
+
+MouseEvent::MouseEvent(const MouseEvent& other, View* source, View* target)
+ : LocatedEvent(other, source, target) {
+}
+
+} // namespace views
diff --git a/ui/views/events/event.h b/ui/views/events/event.h
new file mode 100644
index 0000000..fc0a0d6
--- /dev/null
+++ b/ui/views/events/event.h
@@ -0,0 +1,190 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_EVENTS_EVENT_H_
+#define UI_VIEWS_EVENTS_EVENT_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "gfx/point.h"
+#include "ui/base/keycodes/keyboard_codes.h"
+#include "ui/views/native_types.h"
+
+class OSExchangeData;
+
+namespace ui {
+
+class View;
+
+class Event {
+ public:
+ // Event types.
+ enum EventType { ET_UNKNOWN = 0,
+ ET_MOUSE_PRESSED,
+ ET_MOUSE_DRAGGED,
+ ET_MOUSE_RELEASED,
+ ET_MOUSE_MOVED,
+ ET_MOUSE_ENTERED,
+ ET_MOUSE_EXITED,
+ ET_KEY_PRESSED,
+ ET_KEY_RELEASED,
+ ET_MOUSEWHEEL,
+ ET_DROP_TARGET_EVENT };
+
+ // Event flags currently supported. Although this is a "views"
+ // file, this header is used on non-views platforms (e.g. OSX). For
+ // example, these EventFlags are used by the automation provider for
+ // all platforms.
+ enum EventFlags { EF_CAPS_LOCK_DOWN = 1 << 0,
+ EF_SHIFT_DOWN = 1 << 1,
+ EF_CONTROL_DOWN = 1 << 2,
+ EF_ALT_DOWN = 1 << 3,
+ EF_LEFT_BUTTON_DOWN = 1 << 4,
+ EF_MIDDLE_BUTTON_DOWN = 1 << 5,
+ EF_RIGHT_BUTTON_DOWN = 1 << 6,
+ EF_COMMAND_DOWN = 1 << 7, // Only useful on OSX
+ };
+
+ EventType type() const { return type_; }
+ int flags() const { return flags_; }
+ void set_flags(int flags) { flags_ = flags; }
+
+ // The following methods return true if the respective keys were pressed at
+ // the time the event was created.
+ bool IsShiftDown() const { return (flags_ & EF_SHIFT_DOWN) != 0; }
+ bool IsControlDown() const { return (flags_ & EF_CONTROL_DOWN) != 0; }
+ bool IsCapsLockDown() const { return (flags_ & EF_CAPS_LOCK_DOWN) != 0; }
+ bool IsAltDown() const { return (flags_ & EF_ALT_DOWN) != 0; }
+
+ // Returns true if the event is any kind of mouse event.
+ bool IsMouseEvent() const {
+ return type_ == ET_MOUSE_PRESSED ||
+ type_ == ET_MOUSE_RELEASED ||
+ type_ == ET_MOUSE_MOVED ||
+ type_ == ET_MOUSE_EXITED ||
+ type_ == ET_MOUSEWHEEL;
+ }
+
+ protected:
+ Event(EventType type, int flags);
+
+ private:
+ EventType type_;
+ int flags_;
+
+ DISALLOW_COPY_AND_ASSIGN(Event);
+};
+
+class LocatedEvent : public Event {
+ public:
+ int x() const { return location_.x(); }
+ int y() const { return location_.y(); }
+ const gfx::Point& location() const { return location_; }
+
+ protected:
+ // Constructors called from subclasses.
+
+ // Simple initialization from cracked metadata.
+ LocatedEvent(EventType type, const gfx::Point& location, int flags);
+
+ // During event processing, event locations are translated from the
+ // coordinates of a source View to a target as the tree is descended. This
+ // translation occurs by constructing a new event from another event object,
+ // specifying a |source| and |target| View to facilitate coordinate
+ // conversion. Events that are processed in this manner will have a similar
+ // constructor that calls into this one.
+ LocatedEvent(const LocatedEvent& other, View* source, View* target);
+
+ private:
+ gfx::Point location_;
+
+ DISALLOW_COPY_AND_ASSIGN(LocatedEvent);
+};
+
+class MouseEvent : public LocatedEvent {
+ public:
+ // Flags specific to mouse events
+ enum MouseEventFlags {
+ EF_IS_DOUBLE_CLICK = 1 << 16,
+ EF_IS_NON_CLIENT = 1 << 17
+ };
+
+ explicit MouseEvent(NativeEvent native_event);
+
+ MouseEvent(const MouseEvent& other, View* source, View* target);
+
+ // Conveniences to quickly test what button is down:
+ bool IsOnlyLeftMouseButton() const {
+ return (flags() & EF_LEFT_BUTTON_DOWN) &&
+ !(flags() & (EF_MIDDLE_BUTTON_DOWN | EF_RIGHT_BUTTON_DOWN));
+ }
+ bool IsLeftMouseButton() const {
+ return (flags() & EF_LEFT_BUTTON_DOWN) != 0;
+ }
+ bool IsOnlyMiddleMouseButton() const {
+ return (flags() & EF_MIDDLE_BUTTON_DOWN) &&
+ !(flags() & (EF_LEFT_BUTTON_DOWN | EF_RIGHT_BUTTON_DOWN));
+ }
+ bool IsMiddleMouseButton() const {
+ return (flags() & EF_MIDDLE_BUTTON_DOWN) != 0;
+ }
+ bool IsOnlyRightMouseButton() const {
+ return (flags() & EF_RIGHT_BUTTON_DOWN) &&
+ !(flags() & (EF_LEFT_BUTTON_DOWN | EF_MIDDLE_BUTTON_DOWN));
+ }
+ bool IsRightMouseButton() const {
+ return (flags() & EF_RIGHT_BUTTON_DOWN) != 0;
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MouseEvent);
+};
+
+class KeyEvent : public Event {
+ public:
+ explicit KeyEvent(NativeEvent native_event);
+
+ KeyboardCode key_code() const { return key_code_; }
+
+ int repeat_count() const { return repeat_count_; }
+
+ private:
+ KeyboardCode key_code_;
+ int repeat_count_;
+ int message_flags_;
+
+ DISALLOW_COPY_AND_ASSIGN(KeyEvent);
+};
+
+class MouseWheelEvent : public LocatedEvent {
+ public:
+ explicit MouseWheelEvent(NativeEvent native_event);
+
+ int offset() const { return offset_; }
+
+ private:
+ int offset_;
+
+ DISALLOW_COPY_AND_ASSIGN(MouseWheelEvent);
+};
+
+/*
+class DropTargetEvent : public LocatedEvent {
+ public:
+ explicit DropTargetEvent(NativeEvent native_event);
+
+ const OSExchangeData& data() const { return data_; }
+ int source_operations() const { return source_operations_; }
+
+ private:
+ const OSExchangeData& data_;
+ int source_operations_;
+
+ DISALLOW_COPY_AND_ASSIGN(DropTargetEvent);
+};
+*/
+
+} // namespace ui
+
+#endif // UI_VIEWS_EVENTS_EVENT_H_
diff --git a/ui/views/events/event_win.cc b/ui/views/events/event_win.cc
new file mode 100644
index 0000000..10a4b55
--- /dev/null
+++ b/ui/views/events/event_win.cc
@@ -0,0 +1,195 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/events/event.h"
+
+#include <windowsx.h>
+
+#include "base/logging.h"
+#include "ui/base/keycodes/keyboard_code_conversion_win.h"
+
+namespace ui {
+
+namespace {
+
+// Returns a mask corresponding to the set of modifier keys that are currently
+// pressed. Windows key messages don't come with control key state as parameters
+// as with mouse messages, so we need to explicitly ask for these states.
+int GetKeyStateFlags() {
+ int flags = 0;
+ if (GetKeyState(VK_MENU) & 0x80)
+ flags |= Event::EF_ALT_DOWN;
+ if (GetKeyState(VK_SHIFT) & 0x80)
+ flags |= Event::EF_SHIFT_DOWN;
+ if (GetKeyState(VK_CONTROL) & 0x80)
+ flags |= Event::EF_CONTROL_DOWN;
+ return flags;
+}
+
+// Convert windows message identifiers to Event types.
+Event::EventType EventTypeFromNative(NativeEvent native_event) {
+ switch (native_event.message) {
+ case WM_KEYDOWN:
+ case WM_SYSKEYDOWN:
+ return Event::ET_KEY_PRESSED;
+ case WM_KEYUP:
+ case WM_SYSKEYUP:
+ return Event::ET_KEY_RELEASED;
+ case WM_LBUTTONDOWN:
+ case WM_MBUTTONDOWN:
+ case WM_NCLBUTTONDOWN:
+ case WM_NCMBUTTONDOWN:
+ case WM_NCRBUTTONDOWN:
+ case WM_RBUTTONDOWN:
+ return Event::ET_MOUSE_PRESSED;
+ case WM_LBUTTONDBLCLK:
+ case WM_LBUTTONUP:
+ case WM_MBUTTONDBLCLK:
+ case WM_MBUTTONUP:
+ case WM_NCLBUTTONDBLCLK:
+ case WM_NCLBUTTONUP:
+ case WM_NCMBUTTONDBLCLK:
+ case WM_NCMBUTTONUP:
+ case WM_NCRBUTTONDBLCLK:
+ case WM_NCRBUTTONUP:
+ case WM_RBUTTONDBLCLK:
+ case WM_RBUTTONUP:
+ return Event::ET_MOUSE_RELEASED;
+ case WM_MOUSEMOVE:
+ case WM_NCMOUSEMOVE:
+ return Event::ET_MOUSE_MOVED;
+ case WM_MOUSEWHEEL:
+ return Event::ET_MOUSEWHEEL;
+ case WM_MOUSELEAVE:
+ case WM_NCMOUSELEAVE:
+ return Event::ET_MOUSE_EXITED;
+ default:
+ NOTREACHED();
+ }
+ return Event::ET_UNKNOWN;
+}
+
+bool IsClientMouseEvent(NativeEvent native_event) {
+ return native_event.message == WM_MOUSELEAVE ||
+ (native_event.message >= WM_MOUSEFIRST &&
+ native_event.message <= WM_MOUSELAST);
+}
+
+bool IsNonClientMouseEvent(NativeEvent native_event) {
+ return native_event.message == WM_NCMOUSELEAVE ||
+ (native_event.message >= WM_NCMOUSEMOVE &&
+ native_event.message <= WM_NCMBUTTONDBLCLK);
+}
+
+gfx::Point MousePositionFromNative(NativeEvent native_event) {
+ if (IsClientMouseEvent(native_event)) {
+ // Client message. The position is contained in the LPARAM.
+ return gfx::Point(GET_X_LPARAM(native_event.lParam),
+ GET_Y_LPARAM(native_event.lParam));
+ }
+ DCHECK(IsNonClientMouseEvent(native_event));
+ // Non-client message. The position is contained in a POINTS structure in
+ // LPARAM, and is in screen coordinates so we have to convert to client.
+ POINT native_point = { GET_X_LPARAM(native_event.lParam),
+ GET_Y_LPARAM(native_event.lParam) };
+ ScreenToClient(native_event.hwnd, &native_point);
+ return gfx::Point(native_point);
+}
+
+int MouseEventFlagsFromNative(NativeEvent native_event) {
+ int flags = 0;
+
+ // Check if the event occurred in the non-client area.
+ if (IsNonClientMouseEvent(native_event))
+ flags |= MouseEvent::EF_IS_NON_CLIENT;
+
+ // Check for double click events.
+ switch (native_event.message) {
+ case WM_NCLBUTTONDBLCLK:
+ case WM_NCMBUTTONDBLCLK:
+ case WM_NCRBUTTONDBLCLK:
+ case WM_LBUTTONDBLCLK:
+ case WM_MBUTTONDBLCLK:
+ case WM_RBUTTONDBLCLK:
+ flags |= MouseEvent::EF_IS_DOUBLE_CLICK;
+ break;
+ }
+
+ // Check for pressed buttons.
+ if (IsClientMouseEvent(native_event)) {
+ if (native_event.wParam & MK_LBUTTON)
+ flags |= Event::EF_LEFT_BUTTON_DOWN;
+ if (native_event.wParam & MK_MBUTTON)
+ flags |= Event::EF_MIDDLE_BUTTON_DOWN;
+ if (native_event.wParam & MK_RBUTTON)
+ flags |= Event::EF_RIGHT_BUTTON_DOWN;
+ } else if (IsNonClientMouseEvent(native_event)) {
+ switch (native_event.message) {
+ case WM_NCLBUTTONDOWN:
+ flags |= Event::EF_LEFT_BUTTON_DOWN;
+ break;
+ case WM_NCMBUTTONDOWN:
+ flags |= Event::EF_MIDDLE_BUTTON_DOWN;
+ break;
+ case WM_NCRBUTTONDOWN:
+ flags |= Event::EF_RIGHT_BUTTON_DOWN;
+ break;
+ }
+ }
+
+ // Finally make sure the key state flags are included.
+ return flags | GetKeyStateFlags();
+}
+
+int MouseWheelEventFlagsFromNative(NativeEvent native_event) {
+ int native_flags = GET_KEYSTATE_WPARAM(native_event.wParam);
+ int flags = 0;
+ if (native_flags & MK_CONTROL)
+ flags |= Event::EF_CONTROL_DOWN;
+ if (native_flags & MK_SHIFT)
+ flags |= Event::EF_SHIFT_DOWN;
+ if (GetKeyState(VK_MENU) < 0)
+ flags |= Event::EF_ALT_DOWN;
+ if (native_flags & MK_LBUTTON)
+ flags |= Event::EF_LEFT_BUTTON_DOWN;
+ if (native_flags & MK_MBUTTON)
+ flags |= Event::EF_MIDDLE_BUTTON_DOWN;
+ if (native_flags & MK_RBUTTON)
+ flags |= Event::EF_RIGHT_BUTTON_DOWN;
+ return flags;
+}
+
+} // namespace
+
+////////////////////////////////////////////////////////////////////////////////
+// KeyEvent, public:
+
+KeyEvent::KeyEvent(NativeEvent native_event)
+ : Event(EventTypeFromNative(native_event), GetKeyStateFlags()),
+ key_code_(KeyboardCodeForWindowsKeyCode(native_event.wParam)),
+ repeat_count_(native_event.lParam & 0xFFFF),
+ message_flags_((native_event.lParam & 0xFFFF0000) >> 16) {
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// MouseEvent, public:
+
+MouseEvent::MouseEvent(NativeEvent native_event)
+ : LocatedEvent(EventTypeFromNative(native_event),
+ MousePositionFromNative(native_event),
+ MouseEventFlagsFromNative(native_event)) {
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// MouseWheelEvent, public:
+
+MouseWheelEvent::MouseWheelEvent(NativeEvent native_event)
+ : LocatedEvent(ET_MOUSEWHEEL,
+ MousePositionFromNative(native_event),
+ MouseWheelEventFlagsFromNative(native_event)),
+ offset_(GET_WHEEL_DELTA_WPARAM(native_event.wParam)) {
+}
+
+} // namespace ui
+
diff --git a/ui/views/layout/fill_layout.cc b/ui/views/layout/fill_layout.cc
new file mode 100644
index 0000000..5c603c7
--- /dev/null
+++ b/ui/views/layout/fill_layout.cc
@@ -0,0 +1,37 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/layout/fill_layout.h"
+
+#include "base/logging.h"
+#include "ui/views/view.h"
+
+namespace ui {
+
+////////////////////////////////////////////////////////////////////////////////
+// FillLayout, public:
+
+FillLayout::FillLayout() {
+}
+
+FillLayout::~FillLayout() {
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// FillLayout, LayoutManager implementation:
+
+void FillLayout::Layout(View* host) {
+ if (host->child_count() == 0)
+ return;
+
+ View* child = host->GetChildViewAt(0);
+ child->SetBounds(0, 0, host->width(), host->height());
+}
+
+gfx::Size FillLayout::GetPreferredSize(View* host) {
+ DCHECK(host->child_count() == 1);
+ return host->GetChildViewAt(0)->GetPreferredSize();
+}
+
+} // namespace ui
diff --git a/ui/views/layout/fill_layout.h b/ui/views/layout/fill_layout.h
new file mode 100644
index 0000000..559f2e8
--- /dev/null
+++ b/ui/views/layout/fill_layout.h
@@ -0,0 +1,35 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_LAYOUT_FILL_LAYOUT_H_
+#define UI_VIEWS_LAYOUT_FILL_LAYOUT_H_
+#pragma once
+
+#include "base/logging.h"
+#include "ui/views/layout/layout_manager.h"
+
+namespace ui {
+
+////////////////////////////////////////////////////////////////////////////////
+// FillLayout class
+//
+// A simple LayoutManager that compels a single view to fit its parent.
+//
+class FillLayout : public LayoutManager {
+ public:
+ FillLayout();
+ virtual ~FillLayout();
+
+ // Overridden from LayoutManager:
+ virtual void Layout(View* host);
+ virtual gfx::Size GetPreferredSize(View* host);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(FillLayout);
+};
+
+} // namespace ui
+
+#endif // UI_VIEWS_LAYOUT_FILL_LAYOUT_H_
+
diff --git a/ui/views/layout/layout_manager.cc b/ui/views/layout/layout_manager.cc
new file mode 100644
index 0000000..e3ac839
--- /dev/null
+++ b/ui/views/layout/layout_manager.cc
@@ -0,0 +1,15 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/layout/layout_manager.h"
+
+#include "ui/views/view.h"
+
+namespace ui {
+
+int LayoutManager::GetPreferredHeightForWidth(View* host, int width) {
+ return GetPreferredSize(host).height();
+}
+
+} // namespace ui
diff --git a/ui/views/layout/layout_manager.h b/ui/views/layout/layout_manager.h
new file mode 100644
index 0000000..d985d0d
--- /dev/null
+++ b/ui/views/layout/layout_manager.h
@@ -0,0 +1,57 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_LAYOUT_LAYOUT_MANAGER_H_
+#define UI_VIEWS_LAYOUT_LAYOUT_MANAGER_H_
+#pragma once
+
+namespace gfx {
+class Size;
+}
+
+namespace ui {
+
+class View;
+
+////////////////////////////////////////////////////////////////////////////////
+// LayoutManager interface
+//
+// An interface implemented by an object that manages sizing of a View's
+// children.
+//
+class LayoutManager {
+ public:
+ virtual ~LayoutManager() {}
+
+ // Notification that this LayoutManager has been installed on a particular
+ // host.
+ virtual void Installed(View* host) {}
+
+ // Notification that this LayoutManager has been uninstalled on a particular
+ // host.
+ virtual void Uninstalled(View* host) {}
+
+ // Lay out the children of |host| according to implementation-specific
+ // heuristics. The graphics used during painting is provided to allow for
+ // string sizing.
+ virtual void Layout(View* host) = 0;
+
+ // Return the preferred size which is the size required to give each
+ // children their respective preferred size.
+ virtual gfx::Size GetPreferredSize(View* host) = 0;
+
+ // Returns the preferred height for the specified width. The default
+ // implementation returns the value from GetPreferredSize.
+ virtual int GetPreferredHeightForWidth(View* host, int width);
+
+ // Notification that a view has been added.
+ virtual void ViewAdded(View* host, View* view) {}
+
+ // Notification that a view has been removed.
+ virtual void ViewRemoved(View* host, View* view) {}
+};
+
+} // namespace ui
+
+#endif // UI_VIEWS_LAYOUT_LAYOUT_MANAGER_H_
diff --git a/ui/views/native_types.h b/ui/views/native_types.h
new file mode 100644
index 0000000..c17a1bb
--- /dev/null
+++ b/ui/views/native_types.h
@@ -0,0 +1,20 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_NATIVE_TYPES_H_
+#define UI_VIEWS_NATIVE_TYPES_H_
+#pragma once
+
+#include "gfx/native_widget_types.h"
+
+namespace ui {
+
+#if defined(OS_WIN)
+typedef MSG NativeEvent;
+#endif
+
+} // namespace ui
+
+#endif // UI_VIEWS_NATIVE_TYPES_H_
+
diff --git a/ui/views/rendering/border.cc b/ui/views/rendering/border.cc
new file mode 100644
index 0000000..34493e6
--- /dev/null
+++ b/ui/views/rendering/border.cc
@@ -0,0 +1,69 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/rendering/border.h"
+
+#include "gfx/canvas.h"
+#include "ui/views/view.h"
+
+namespace ui {
+
+namespace internal {
+
+class SolidColorBorder : public Border {
+ public:
+ SolidColorBorder(int thickness, SkColor color) : color_(color) {
+ set_insets(gfx::Insets(thickness, thickness, thickness, thickness));
+ }
+ virtual ~SolidColorBorder() {
+ }
+
+ // Overridden from Border:
+ virtual void Paint(const View* view, gfx::Canvas* canvas) const {
+ canvas->FillRectInt(color_, 0, 0, view->width(), insets().top());
+ canvas->FillRectInt(color_, 0, 0, insets().left(), view->height());
+ canvas->FillRectInt(color_, 0, view->height() - insets().bottom(),
+ view->width(), insets().bottom());
+ canvas->FillRectInt(color_, view->width() - insets().right(), 0,
+ insets().right(), view->height());
+ }
+
+ private:
+ SkColor color_;
+
+ DISALLOW_COPY_AND_ASSIGN(SolidColorBorder);
+};
+
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Border, public:
+
+Border::~Border() {
+}
+
+// static
+Border* Border::CreateSolidBorder(int thickness, SkColor color) {
+ return new internal::SolidColorBorder(thickness, color);
+}
+
+// static
+Border* Border::CreateTransparentBorder(const gfx::Insets& insets) {
+ Border* b = new Border;
+ b->set_insets(insets);
+ return b;
+}
+
+void Border::Paint(const View* view, gfx::Canvas* canvas) const {
+ // Nothing to do.
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Border, private:
+
+Border::Border() {
+}
+
+} // namespace ui
+
diff --git a/ui/views/rendering/border.h b/ui/views/rendering/border.h
new file mode 100644
index 0000000..e1b196f
--- /dev/null
+++ b/ui/views/rendering/border.h
@@ -0,0 +1,50 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_BORDER_H_
+#define UI_VIEWS_BORDER_H_
+
+#include "base/logging.h"
+#include "gfx/insets.h"
+#include "third_party/skia/include/core/SkColor.h"
+
+namespace gfx {
+class Canvas;
+}
+
+namespace ui {
+
+class View;
+
+////////////////////////////////////////////////////////////////////////////////
+// Border class
+//
+// A class that provides padding for a View. Subclass to provide custom
+// rendering of the Border. Insets determine the size of border.
+//
+class Border {
+ public:
+ virtual ~Border();
+
+ // Create various common border types.
+ static Border* CreateSolidBorder(int thickness, SkColor color);
+ static Border* CreateTransparentBorder(const gfx::Insets& insets);
+
+ gfx::Insets insets() const { return insets_; }
+ void set_insets(const gfx::Insets& insets) { insets_ = insets; }
+
+ virtual void Paint(const View* view, gfx::Canvas* canvas) const;
+
+ protected:
+ Border();
+
+ private:
+ gfx::Insets insets_;
+
+ DISALLOW_COPY_AND_ASSIGN(Border);
+};
+
+} // namespace ui
+
+#endif // UI_VIEWS_BORDER_H_
diff --git a/ui/views/rendering/border_unittest.cc b/ui/views/rendering/border_unittest.cc
new file mode 100644
index 0000000..52e62bb
--- /dev/null
+++ b/ui/views/rendering/border_unittest.cc
@@ -0,0 +1,63 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <algorithm>
+
+#include "gfx/canvas.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/views/rendering/border.h"
+#include "ui/views/view.h"
+
+namespace ui {
+
+class BorderTest : public testing::Test {
+ public:
+ BorderTest() {}
+ virtual ~BorderTest() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BorderTest);
+};
+
+class TestBorder : public Border {
+ public:
+ TestBorder() : painted_(false) {}
+
+ bool painted() const { return painted_; }
+
+ // Overridden from Border:
+ virtual void Paint(const View* view, gfx::Canvas* canvas) const {
+ painted_ = true;
+ }
+
+ private:
+ mutable bool painted_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestBorder);
+};
+
+TEST_F(BorderTest, Basic) {
+ const int kViewSize = 100;
+ View v;
+ v.SetBounds(10, 10, kViewSize, kViewSize);
+
+ // With no border, the content size is the view size.
+ EXPECT_EQ(gfx::Rect(0, 0, kViewSize, kViewSize), v.GetContentsBounds());
+
+ const int kViewInset = 10;
+ v.SetBorder(Border::CreateTransparentBorder(
+ gfx::Insets(kViewInset, kViewInset, kViewInset, kViewInset)));
+
+ // With the border, the content bounds are inset by the border's insets.
+ EXPECT_EQ(gfx::Rect(kViewInset, kViewInset, kViewSize - 2 * kViewInset,
+ kViewSize - 2 * kViewInset),
+ v.GetContentsBounds());
+
+ TestBorder* border = new TestBorder;
+ v.SetBorder(border);
+ v.OnPaint(NULL);
+ EXPECT_TRUE(border->painted());
+}
+
+} // namespace ui
diff --git a/ui/views/run_all_unittests.cc b/ui/views/run_all_unittests.cc
new file mode 100644
index 0000000..d4dfd39
--- /dev/null
+++ b/ui/views/run_all_unittests.cc
@@ -0,0 +1,19 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/test/test_suite.h"
+
+class V2TestSuite : public base::TestSuite {
+ public:
+ V2TestSuite(int argc, char** argv) : base::TestSuite(argc, argv) {}
+
+ protected:
+ virtual void Initialize() {
+ base::TestSuite::Initialize();
+ }
+};
+
+int main(int argc, char **argv) {
+ return V2TestSuite(argc, argv).Run();
+}
diff --git a/ui/views/view.cc b/ui/views/view.cc
new file mode 100644
index 0000000..5057afe
--- /dev/null
+++ b/ui/views/view.cc
@@ -0,0 +1,629 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/view.h"
+
+#include <algorithm>
+#include <functional>
+
+#include "gfx/canvas.h"
+#include "gfx/point.h"
+#include "gfx/size.h"
+#include "ui/base/dragdrop/drag_drop_types.h"
+#include "ui/views/events/context_menu_controller.h"
+#include "ui/views/events/drag_controller.h"
+#include "ui/views/layout/layout_manager.h"
+#include "ui/views/rendering/border.h"
+#include "ui/views/widget/widget.h"
+
+namespace ui {
+
+namespace {
+
+// Saves gfx::Canvas state upon construction and automatically restores it when
+// it goes out of scope.
+class ScopedCanvasState {
+ public:
+ explicit ScopedCanvasState(gfx::Canvas* canvas) : canvas_(canvas) {
+ canvas_->Save();
+ }
+ ~ScopedCanvasState() {
+ canvas_->Restore();
+ }
+
+ private:
+ gfx::Canvas* canvas_;
+ DISALLOW_COPY_AND_ASSIGN(ScopedCanvasState);
+};
+
+bool ExceededDragThreshold(const gfx::Point& press_point,
+ const gfx::Point& event_point) {
+ // TODO(beng): implement
+ return true;
+}
+
+} // namespace
+
+////////////////////////////////////////////////////////////////////////////////
+// View, public:
+
+View::View()
+ : parent_(NULL),
+ parent_owned_(true),
+ visible_(true),
+ enabled_(true),
+ id_(-1),
+ group_(-1),
+ focusable_(false),
+ context_menu_controller_(NULL),
+ drag_controller_(NULL) {
+}
+
+View::~View() {
+ if (parent_)
+ parent_->RemoveChildView(this);
+
+ ViewVector::const_iterator it = children_.begin();
+ for (; it != children_.end(); ++it) {
+ (*it)->parent_ = NULL;
+ if ((*it)->parent_owned())
+ delete *it;
+ }
+}
+
+// Size and disposition --------------------------------------------------------
+
+void View::SetBounds(int x, int y, int width, int height) {
+ SetBoundsRect(gfx::Rect(x, y, std::max(0, width), std::max(0, height)));
+}
+
+void View::SetBoundsRect(const gfx::Rect& bounds) {
+ gfx::Rect old_bounds = bounds_;
+ bounds_ = bounds;
+ // TODO(beng): investigate usage of needs_layout_ in old View code.
+ if (old_bounds != bounds_) {
+ OnBoundsChanged();
+ Layout();
+ }
+}
+
+gfx::Rect View::GetVisibleBounds() const {
+ // TODO(beng):
+ return bounds();
+}
+
+void View::SetSize(const gfx::Size& size) {
+ SetBounds(x(), y(), size.width(), size.height());
+}
+
+void View::SetPosition(const gfx::Point& position) {
+ SetBounds(position.x(), position.y(), width(), height());
+}
+
+void View::SetBorder(Border* border) {
+ border_.reset(border);
+}
+
+gfx::Rect View::GetContentsBounds() const {
+ if (border_.get()) {
+ return gfx::Rect(
+ border_->insets().left(), border_->insets().top(),
+ width() - border_->insets().right() - border_->insets().left(),
+ height() - border_->insets().bottom() - border_->insets().top());
+ }
+ return gfx::Rect(0, 0, width(), height());
+}
+
+void View::OnBoundsChanged() {
+}
+
+gfx::Size View::GetPreferredSize() const {
+ return gfx::Size();
+}
+
+gfx::Size View::GetMinimumSize() const {
+ return GetPreferredSize();
+}
+
+void View::SetLayoutManager(LayoutManager* layout_manager) {
+ layout_manager_.reset(layout_manager);
+}
+
+void View::Layout() {
+ if (layout_manager_.get()) {
+ // Layout Manager handles laying out children.
+ layout_manager_->Layout(this);
+ } else {
+ // We handle laying out our own children.
+ ViewVector::iterator it = children_.begin();
+ for (; it != children_.end(); ++it)
+ (*it)->Layout();
+ }
+ // TODO(beng): needs_layout_? SchedulePaint()?
+}
+
+void View::SetVisible(bool visible) {
+ if (visible != visible_) {
+ visible_ = visible;
+
+ // InvaldateRect() checks for view visibility before proceeding, so we need
+ // to ask the parent to invalidate our bounds.
+ if (parent_)
+ parent_->InvalidateRect(bounds_);
+ }
+}
+
+void View::SetEnabled(bool enabled) {
+ if (enabled != enabled_) {
+ enabled_ = enabled;
+ Invalidate();
+ }
+}
+
+// Coordinate conversion -------------------------------------------------------
+
+// static
+void View::ConvertPointToView(View* source, View* target, gfx::Point* point) {
+ View* inner = NULL;
+ View* outer = NULL;
+ if (source->Contains(target)) {
+ inner = target;
+ outer = source;
+ } else if (target->Contains(source)) {
+ inner = source;
+ outer = target;
+ } // Note that we cannot do a plain "else" here since |source| and |target|
+ // may be in different hierarchies with no relation.
+
+ if (inner && outer) {
+ gfx::Point offset;
+ View* temp = inner;
+ while (temp != outer) {
+ offset.Offset(temp->x(), temp->y());
+ temp = temp->parent();
+ }
+ // When target is contained by source, we need to subtract the offset.
+ // When source is contained by target, we need to add the fofset.
+ int multiplier = inner == target ? -1 : 1;
+ point->Offset(multiplier * offset.x(), multiplier * offset.y());
+ }
+}
+
+// static
+void View::ConvertPointToScreen(View* source, gfx::Point* point) {
+ Widget* widget = source->GetWidget();
+ if (widget) {
+ ConvertPointToWidget(source, point);
+ gfx::Rect r = widget->GetClientAreaScreenBounds();
+ point->Offset(r.x(), r.y());
+ }
+}
+
+// static
+void View::ConvertPointToWidget(View* source, gfx::Point* point) {
+ for (View* v = source; v; v = v->parent())
+ point->Offset(v->x(), v->y());
+}
+
+// Tree operations -------------------------------------------------------------
+
+Widget* View::GetWidget() const {
+ return parent_ ? parent_->GetWidget() : NULL;
+}
+
+void View::AddChildView(View* view) {
+ AddChildViewAt(view, children_.size());
+}
+
+void View::AddChildViewAt(View* view, size_t index) {
+ CHECK(view != this) << "A view cannot be its own child.";
+
+ // Remove the child from its current parent if any.
+ if (view->parent())
+ view->parent()->RemoveChildView(view);
+
+ children_.insert(children_.begin() + index, view);
+ view->parent_ = this;
+
+ // Notify the hierarchy.
+ NotifyHierarchyChanged(this, view, true);
+
+ // TODO(beng): Notify other objects like tooltip, layout manager, etc.
+ // Figure out RegisterChildrenForVisibleBoundsNotification.
+}
+
+View* View::RemoveChildView(View* view) {
+ ViewVector::iterator it = find(children_.begin(), children_.end(), view);
+ if (it != children_.end()) {
+ View* old_parent = view->parent_;
+ view->parent_ = NULL;
+ children_.erase(it);
+ NotifyHierarchyChanged(old_parent, view, false);
+ }
+
+ // TODO(beng): Notify other objects like tooltip, layout manager, etc.
+ return view;
+}
+
+void View::RemoveAllChildViews(bool delete_children) {
+ // TODO(beng): use for_each.
+ ViewVector::iterator it = children_.begin();
+ while (it != children_.end()) {
+ View* v = RemoveChildView(*it);
+ if (delete_children)
+ delete v;
+ // TODO(beng): view deletion is actually more complicated in the old view.cc
+ // figure out why. (it uses a ScopedVector to accumulate a list
+ // of views to delete).
+ }
+}
+
+View* View::GetChildViewAt(size_t index) {
+ CHECK(index < child_count());
+ return children_[index];
+}
+
+bool View::Contains(View* child) {
+ while (child) {
+ if (child == this)
+ return true;
+ child = child->parent();
+ }
+ return false;
+}
+
+View* View::GetViewForPoint(const gfx::Point& point) const {
+ ViewVector::const_reverse_iterator it = children_.rbegin();
+ for (; it != children_.rend(); ++it) {
+ View* child = *it;
+ if (!child->visible())
+ continue;
+
+ gfx::Point point_in_child_coords(point);
+ View::ConvertPointToView(const_cast<View*>(this), child,
+ &point_in_child_coords);
+ if (child->HitTest(point_in_child_coords))
+ return child->GetViewForPoint(point_in_child_coords);
+ }
+ return const_cast<View*>(this);
+}
+
+bool View::HitTest(const gfx::Point& point) const {
+ // TODO(beng): Hit test mask support.
+ return gfx::Rect(0, 0, width(), height()).Contains(point);
+}
+
+View* View::GetViewById(int id) const {
+ if (id_ == id)
+ return const_cast<View*>(this);
+ ViewVector::const_iterator it = children_.begin();
+ for (; it != children_.end(); ++it) {
+ View* view = (*it)->GetViewById(id);
+ if (view)
+ return view;
+ }
+ return NULL;
+}
+
+void View::GetViewsWithGroup(int group, ViewVector* vec) const {
+ if (group_ == group)
+ vec->push_back(const_cast<View*>(this));
+ ViewVector::const_iterator it = children_.begin();
+ for (; it != children_.end(); ++it)
+ (*it)->GetViewsWithGroup(group, vec);
+}
+
+void View::OnViewAdded(View* parent, View* child) {
+}
+
+void View::OnViewRemoved(View* parent, View* child) {
+}
+
+void View::OnViewAddedToWidget() {
+}
+
+void View::OnViewRemovedFromWidget() {
+}
+
+// Accelerators ----------------------------------------------------------------
+
+void View::AddAccelerator(const Accelerator& accelerator) {
+}
+
+void View::RemoveAccelerator(const Accelerator& accelerator) {
+}
+
+void View::RemoveAllAccelerators() {
+}
+
+bool View::OnAcceleratorPressed(const Accelerator& accelerator) {
+ return false;
+}
+
+// Focus -----------------------------------------------------------------------
+
+FocusManager* View::GetFocusManager() const {
+ return NULL;
+}
+
+FocusTraversable* View::GetFocusTraversable() const {
+ return NULL;
+}
+
+View* View::GetNextFocusableView() const {
+ return NULL;
+}
+
+View* View::GetPreviousFocusableView() const {
+ return NULL;
+}
+
+bool View::SkipDefaultKeyEventProcessing(const KeyEvent& event) const {
+ return false;
+}
+
+bool View::IsFocusable() const {
+ return false;
+}
+
+bool View::HasFocus() const {
+ return false;
+}
+
+void View::RequestFocus() {
+}
+
+void View::OnFocus(/* const FocusEvent& event */) {
+}
+
+void View::OnBlur() {
+}
+
+// Input -----------------------------------------------------------------------
+
+bool View::OnKeyPressed(const KeyEvent& event) {
+ return true;
+}
+
+bool View::OnKeyReleased(const KeyEvent& event) {
+ return true;
+}
+
+bool View::OnMouseWheel(const MouseWheelEvent& event) {
+ return true;
+}
+
+bool View::OnMousePressed(const MouseEvent& event) {
+ return true;
+}
+
+bool View::OnMouseDragged(const MouseEvent& event) {
+ return true;
+}
+
+void View::OnMouseReleased(const MouseEvent& event) {
+
+}
+
+void View::OnMouseCaptureLost() {
+
+}
+
+void View::OnMouseMoved(const MouseEvent& event) {
+
+}
+
+void View::OnMouseEntered(const MouseEvent& event) {
+
+}
+
+void View::OnMouseExited(const MouseEvent& event) {
+
+}
+
+gfx::NativeCursor View::GetCursorForPoint(const gfx::Point& point) {
+ return NULL;
+}
+
+// Painting --------------------------------------------------------------------
+
+void View::Invalidate() {
+ InvalidateRect(gfx::Rect(0, 0, width(), height()));
+}
+
+void View::InvalidateRect(const gfx::Rect& invalid_rect) {
+ if (!visible_)
+ return;
+
+ if (parent_) {
+ gfx::Rect r = invalid_rect;
+ r.Offset(bounds_.origin());
+ parent_->InvalidateRect(r);
+ }
+}
+
+void View::Paint(gfx::Canvas* canvas) {
+ // Invisible views are not painted.
+ if (!visible_)
+ return;
+
+ ScopedCanvasState canvas_state(canvas);
+ if (canvas->ClipRectInt(x(), y(), width(), height())) {
+ canvas->TranslateInt(x(), y());
+ // TODO(beng): RTL
+ ScopedCanvasState canvas_state(canvas);
+ OnPaint(canvas);
+ PaintChildren(canvas);
+ }
+}
+
+void View::PaintChildren(gfx::Canvas* canvas) {
+ // TODO(beng): use for_each.
+ // std::for_each(children_.begin(), children_.end(),
+ // std::bind2nd(std::mem_fun_ref(&View::Paint), canvas));
+ ViewVector::iterator it = children_.begin();
+ for (; it != children_.end(); ++it)
+ (*it)->Paint(canvas);
+}
+
+void View::OnPaint(gfx::Canvas* canvas) {
+ // TODO(beng): investigate moving these function calls to Paint().
+ OnPaintBackground(canvas);
+ OnPaintFocusBorder(canvas);
+ OnPaintBorder(canvas);
+}
+
+void View::OnPaintBackground(gfx::Canvas* canvas) {
+}
+
+void View::OnPaintBorder(gfx::Canvas* canvas) {
+ if (border_.get())
+ border_->Paint(const_cast<const View*>(this), canvas);
+}
+
+void View::OnPaintFocusBorder(gfx::Canvas* canvas) {
+}
+
+// Resources -------------------------------------------------------------------
+
+ThemeProvider* View::GetThemeProvider() const {
+ Widget* widget = GetWidget();
+ return widget ? widget->GetThemeProvider() : NULL;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// View, private:
+
+void View::DragInfo::Reset() {
+ possible_drag = false;
+ press_point = gfx::Point();
+}
+
+void View::DragInfo::PossibleDrag(const gfx::Point& point) {
+ possible_drag = true;
+ press_point = point;
+}
+
+// Drag & Drop -----------------------------------------------------------------
+
+int View::GetDragOperations(const gfx::Point& point) {
+ return drag_controller_ ?
+ drag_controller_->GetDragOperations(const_cast<View*>(this), point) :
+ DragDropTypes::DRAG_NONE;
+}
+
+void View::WriteDragData(const gfx::Point& point, OSExchangeData* data) {
+ drag_controller_->WriteDragData(this, point, data);
+}
+
+void View::StartShellDrag(const MouseEvent& event,
+ const gfx::Point& press_point) {
+ // TODO(beng): system stuff.
+}
+
+// RootView API ----------------------------------------------------------------
+
+bool View::MousePressed(const MouseEvent& event, DragInfo* drag_info) {
+ bool handled = OnMousePressed(event);
+ // TODO(beng): deal with view deletion, see ProcessMousePressed() in old code.
+ if (!enabled_)
+ return handled;
+
+ int drag_operations =
+ enabled_ && event.IsOnlyLeftMouseButton() && HitTest(event.location()) ?
+ GetDragOperations(event.location()) : DragDropTypes::DRAG_NONE;
+ if (drag_operations != DragDropTypes::DRAG_NONE) {
+ drag_info->PossibleDrag(event.location());
+ return true;
+ }
+ bool has_context_menu = event.IsRightMouseButton() ?
+ !!context_menu_controller_ : NULL;
+ return has_context_menu || handled;
+}
+
+bool View::MouseDragged(const MouseEvent& event, DragInfo* drag_info) {
+ if (drag_info->possible_drag &&
+ ExceededDragThreshold(drag_info->press_point, event.location())) {
+ if (!drag_controller_ ||
+ drag_controller_->CanStartDrag(this, drag_info->press_point,
+ event.location())) {
+ StartShellDrag(event, drag_info->press_point);
+ }
+ } else {
+ if (OnMouseDragged(event))
+ return true;
+ }
+ // TODO(beng): Handle view deletion from OnMouseDragged().
+ return !!context_menu_controller_ || drag_info->possible_drag;
+}
+
+void View::MouseReleased(const MouseEvent& event) {
+ OnMouseReleased(event);
+ // TODO(beng): Handle view deletion from OnMouseReleased().
+ if (context_menu_controller_ && event.IsOnlyRightMouseButton()) {
+ gfx::Point location(event.location());
+ if (HitTest(location)) {
+ ConvertPointToScreen(this, &location);
+ context_menu_controller_->ShowContextMenu(this, location, true);
+ }
+ }
+}
+
+// Tree operations -------------------------------------------------------------
+
+void View::NotifyHierarchyChanged(View* parent, View* child, bool is_add) {
+ // Notify the child. Note that we call GetWidget() on the parent, not the
+ // child, since this method is called after the child is already removed from
+ // the hierarchy when |is_add| is false and so child->GetWidget() will always
+ // return NULL.
+ bool has_widget = parent->GetWidget() != NULL;
+ CallViewNotification(child, parent, child, is_add, has_widget);
+
+ // Notify the hierarchy up.
+ NotifyHierarchyChangedUp(parent, child, is_add);
+
+ // Notify the hierarchy down.
+ if (!is_add) {
+ // Because |child| has already been removed from |parent|'s child list, we
+ // need to notify its hierarchy manually.
+ child->NotifyHierarchyChangedDown(parent, child, is_add, has_widget);
+ }
+ NotifyHierarchyChangedDown(parent, child, is_add, has_widget);
+}
+
+void View::NotifyHierarchyChangedUp(View* parent, View* child, bool is_add) {
+ for (View* v = parent; v; v = v->parent()) {
+ if (is_add)
+ v->OnViewAdded(parent, child);
+ else
+ v->OnViewRemoved(parent, child);
+ }
+}
+
+void View::NotifyHierarchyChangedDown(View* parent, View* child, bool is_add,
+ bool has_widget) {
+ ViewVector::iterator it = children_.begin();
+ for (; it != children_.end(); ++it) {
+ CallViewNotification(*it, parent, child, is_add, has_widget);
+ (*it)->NotifyHierarchyChangedDown(parent, child, is_add, has_widget);
+ }
+}
+
+void View::CallViewNotification(View* target,
+ View* parent,
+ View* child,
+ bool is_add,
+ bool has_widget) {
+ if (is_add) {
+ target->OnViewAdded(parent, child);
+ if (has_widget)
+ target->OnViewAddedToWidget();
+ } else {
+ target->OnViewRemoved(parent, child);
+ if (has_widget)
+ target->OnViewRemovedFromWidget();
+ }
+}
+
+} // namespace ui
diff --git a/ui/views/view.h b/ui/views/view.h
new file mode 100644
index 0000000..bcb1451
--- /dev/null
+++ b/ui/views/view.h
@@ -0,0 +1,393 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_VIEW_H_
+#define UI_VIEWS_VIEW_H_
+
+#include <vector>
+
+#include "base/logging.h"
+#include "base/scoped_ptr.h"
+#include "gfx/rect.h"
+#include "ui/views/events/event.h"
+
+namespace gfx {
+class Canvas;
+class Point;
+class Rect;
+class Size;
+}
+
+namespace ui {
+namespace internal {
+class RootView;
+}
+class Accelerator;
+class Border;
+class ContextMenuController;
+class DragController;
+class FocusManager;
+class FocusTraversable;
+class LayoutManager;
+class ThemeProvider;
+class Widget;
+
+////////////////////////////////////////////////////////////////////////////////
+// View class
+//
+// View encapsulates rendering, layout and event handling for rectangles within
+// a view hierarchy.
+//
+// Client code typically subclasses View and overrides virtual methods to
+// handle painting, child view positioning and handle certain types of events.
+//
+// Views are owned by their parent View unless specified otherwise. This means
+// that in most cases Views are automatically destroyed when the window that
+// contains them is destroyed.
+//
+// TODO(beng): consider the visibility of many of these methods.
+// consider making RootView a friend and making many private or
+// protected.
+class View {
+ public:
+ typedef std::vector<View*> ViewVector;
+
+ // Creation and lifetime -----------------------------------------------------
+ View();
+ virtual ~View();
+
+ // By default a View is owned by its parent unless specified otherwise here.
+ bool parent_owned() const { return parent_owned_; }
+ void set_parent_owned(bool parent_owned) { parent_owned_ = parent_owned; }
+
+ void set_drag_controller(DragController* drag_controller) {
+ drag_controller_ = drag_controller;
+ }
+
+ // Size and disposition ------------------------------------------------------
+
+ void SetBounds(int x, int y, int width, int height);
+ void SetBoundsRect(const gfx::Rect& bounds);
+ void SetSize(const gfx::Size& size);
+ void SetPosition(const gfx::Point& position);
+ gfx::Rect bounds() const { return bounds_; }
+ gfx::Rect GetVisibleBounds() const;
+ int x() const { return bounds_.x(); }
+ int y() const { return bounds_.y(); }
+ int width() const { return bounds_.width(); }
+ int height() const { return bounds_.height(); }
+
+ // Owned by the view.
+ void SetBorder(Border* border);
+ Border* border() { return border_.get(); }
+
+ // Returns the bounds of the content area of the view, i.e. the rectangle
+ // enclosed by the view's border.
+ gfx::Rect GetContentsBounds() const;
+
+ // Override to be notified when the bounds of a view have changed.
+ virtual void OnBoundsChanged();
+
+ virtual gfx::Size GetPreferredSize() const;
+ virtual gfx::Size GetMinimumSize() const;
+
+ void SetLayoutManager(LayoutManager* layout_manager);
+ virtual void Layout();
+
+ // If a View is not visible, it will not be rendered, focused, etc.
+ bool visible() const { return visible_; }
+ void SetVisible(bool visible);
+
+ // Disabled Views will not receive mouse press/release events, nor can they be
+ // focused.
+ bool enabled() const { return enabled_; }
+ void SetEnabled(bool enabled);
+
+ // Coordinate conversion -----------------------------------------------------
+
+ // Converts a point from the coordinate system of |source| to |target|.
+ static void ConvertPointToView(View* source, View* target, gfx::Point* point);
+
+ // Converts a point from the coordinate system of |source| to the screen.
+ // If |source| is not attached to a Widget that is in screen space, |point| is
+ // not modified.
+ static void ConvertPointToScreen(View* source, gfx::Point* point);
+
+ // Converts a point from the coordinate system of |source| to the Widget that
+ // most closely contains it.
+ static void ConvertPointToWidget(View* source, gfx::Point* point);
+
+ // Tree operations -----------------------------------------------------------
+
+ // Returns the Widget that contains this View, or NULL if it is not contained
+ // within a Widget.
+ virtual Widget* GetWidget() const;
+
+ // Adds a View as a child of this one, optionally at |index|.
+ void AddChildView(View* view);
+ void AddChildViewAt(View* view, size_t index);
+
+ // Removes a View as a child of this View. Does not delete the child.
+ View* RemoveChildView(View* view);
+
+ // Removes all View children of this View. Deletes the children if
+ // |delete_children| is true.
+ void RemoveAllChildViews(bool delete_children);
+
+ // Returns the View at the specified |index|.
+ View* GetChildViewAt(size_t index);
+
+ // Returns the number of child views.
+ size_t child_count() const { return children_.size(); }
+
+ // Returns the parent View, or NULL if this View has no parent.
+ View* parent() const { return parent_; }
+
+ // Returns true if |child| is contained within this View's hierarchy, even as
+ // an indirect descendant. Will return true if child is also this View.
+ bool Contains(View* child);
+
+ // Returns the visible View that most closely contains the specified point.
+ // |point| is in this View's coordinates.
+ // This function is used by the event processing system in the Widget to
+ // locate views for event targeting. Override this function if you wish to
+ // specify a view other than the one most closely enclosing |point| to receive
+ // notifications for events within it.
+ // TODO(beng): This is [ab]used primarily for event handling. Should be
+ // renamed to something like GetViewForEvent().
+ virtual View* GetViewForPoint(const gfx::Point& point) const;
+
+ // Returns true if the specified point is contained within this View or its
+ // hit test mask. |point| is in this View's coordinates.
+ bool HitTest(const gfx::Point& point) const;
+
+ int id() const { return id_; }
+ void set_id(int id) { id_ = id; }
+ int group() const { return group_; }
+ void set_group(int group) { group_ = group; }
+
+ // Returns the View within this View's hierarchy whose id matches that
+ // specified.
+ View* GetViewById(int id) const;
+
+ // Populates a ViewVector with the Views within this View's hierarchy that
+ // match the specified group id.
+ void GetViewsWithGroup(int group, ViewVector* vec) const;
+
+ // Called on every view in the hierarchy when a view is added or removed.
+ virtual void OnViewAdded(View* parent, View* child);
+ virtual void OnViewRemoved(View* parent, View* child);
+
+ // Called on a View when it is added or removed from a Widget.
+ virtual void OnViewAddedToWidget();
+ virtual void OnViewRemovedFromWidget();
+
+ // Accelerators --------------------------------------------------------------
+
+ // Accelerator Registration.
+ void AddAccelerator(const Accelerator& accelerator);
+ void RemoveAccelerator(const Accelerator& accelerator);
+ void RemoveAllAccelerators();
+
+ virtual bool OnAcceleratorPressed(const Accelerator& accelerator);
+
+ // Focus ---------------------------------------------------------------------
+
+ // Manager.
+ FocusManager* GetFocusManager() const;
+
+ // Traversal.
+ virtual FocusTraversable* GetFocusTraversable() const;
+ View* GetNextFocusableView() const;
+ View* GetPreviousFocusableView() const;
+
+ // Attributes.
+ virtual bool SkipDefaultKeyEventProcessing(const KeyEvent& event) const;
+ void set_focusable(bool focusable) { focusable_ = focusable; }
+ bool IsFocusable() const;
+
+ bool HasFocus() const;
+ void RequestFocus();
+
+ virtual void OnFocus(/* const FocusEvent& event */);
+ virtual void OnBlur();
+
+ // Input ---------------------------------------------------------------------
+
+ virtual bool OnKeyPressed(const KeyEvent& event);
+ virtual bool OnKeyReleased(const KeyEvent& event);
+ virtual bool OnMouseWheel(const MouseWheelEvent& event);
+ // To receive OnMouseDragged() or OnMouseReleased() events, overriding classes
+ // must return true from this function.
+ virtual bool OnMousePressed(const MouseEvent& event);
+ virtual bool OnMouseDragged(const MouseEvent& event);
+ virtual void OnMouseReleased(const MouseEvent& event);
+ virtual void OnMouseCaptureLost();
+ virtual void OnMouseMoved(const MouseEvent& event);
+ virtual void OnMouseEntered(const MouseEvent& event);
+ virtual void OnMouseExited(const MouseEvent& event);
+
+ virtual gfx::NativeCursor GetCursorForPoint(const gfx::Point& point);
+
+ // Painting ------------------------------------------------------------------
+
+ // Add all or part of a View's bounds to the enclosing Widget's invalid
+ // rectangle. This will result in those areas being re-painted on the next
+ // update.
+ void Invalidate();
+ virtual void InvalidateRect(const gfx::Rect& invalid_rect);
+
+ // Called by the framework to paint a View. Performs translation and clipping
+ // for View coordinates and language direction as required, allows the View
+ // to paint itself via the various OnPaint*() event handlers and then paints
+ // the hierarchy beneath it.
+ // TODO(beng): Make private?
+ void Paint(gfx::Canvas* canvas);
+
+ // Responsible for calling Paint() on child Views. Override to control the
+ // order child Views are painted.
+ virtual void PaintChildren(gfx::Canvas* canvas);
+
+ // Override to provide rendering in any part of the View's bounds. Typically
+ // this is the "contents" of the view. If you override this method you will
+ // have to call the subsequent OnPaint*() methods manually.
+ virtual void OnPaint(gfx::Canvas* canvas);
+
+ // Override to paint a background before any content is drawn. Typically this
+ // is done if you are satisfied with a default OnPaint handler but wish to
+ // supply a different background.
+ virtual void OnPaintBackground(gfx::Canvas* canvas);
+
+ // Override to paint a border not specified by SetBorder().
+ virtual void OnPaintBorder(gfx::Canvas* canvas);
+
+ // Override to paint a focus border (usually a dotted rectangle) around
+ // relevant contents.
+ virtual void OnPaintFocusBorder(gfx::Canvas* canvas);
+
+ // Context menus -------------------------------------------------------------
+
+ void set_context_menu_controller(
+ ContextMenuController* context_menu_controller) {
+ context_menu_controller_ = context_menu_controller;
+ }
+
+ // Resources -----------------------------------------------------------------
+
+ ThemeProvider* GetThemeProvider() const;
+
+ private:
+ friend internal::RootView;
+
+ // State collected during a MousePressed event to detect possible drag
+ // operations.
+ struct DragInfo {
+ // Sets possible_drag to false and start_x/y to 0. This is invoked by
+ // RootView prior to invoke MousePressed().
+ void Reset();
+
+ // Sets possible_drag to true and start_pt to the specified point.
+ // This is invoked by the target view if it detects the press may generate
+ // a drag.
+ void PossibleDrag(const gfx::Point& point);
+
+ // Whether the press may generate a drag.
+ bool possible_drag;
+
+ // Position of the mouse press in screen coordinates.
+ gfx::Point press_point;
+ };
+
+ // Drag & Drop ---------------------------------------------------------------
+ int GetDragOperations(const gfx::Point& point);
+ void WriteDragData(const gfx::Point& point, OSExchangeData* data);
+ void StartShellDrag(const MouseEvent& event, const gfx::Point& press_point);
+
+ // RootView API --------------------------------------------------------------
+ // These methods are designed to be called by the RootView. The RootView
+ // should limit its interaction with the View to these methods and the public
+ // API.
+ bool MousePressed(const MouseEvent& event, DragInfo* drag_info);
+ bool MouseDragged(const MouseEvent& event, DragInfo* drag_info);
+ void MouseReleased(const MouseEvent& event);
+
+ // Tree operations -----------------------------------------------------------
+ void NotifyHierarchyChanged(View* parent, View* child, bool is_add);
+ void NotifyHierarchyChangedUp(View* parent, View* child, bool is_add);
+ void NotifyHierarchyChangedDown(View* parent, View* child, bool is_add,
+ bool has_widget);
+ void CallViewNotification(View* target,
+ View* parent,
+ View* child,
+ bool is_add,
+ bool has_widget);
+
+ // The View's parent view. This is set and reset when the View is added and
+ // removed from a hierarchy.
+ View* parent_;
+
+ // The View's children.
+ ViewVector children_;
+
+ // True if the hierarchy (i.e. the parent View) is responsible for deleting
+ // this View. Default is true.
+ bool parent_owned_;
+
+ // The bounds of the View, in its parent's coordinates.
+ gfx::Rect bounds_;
+
+ scoped_ptr<Border> border_;
+
+ // Whether or not this View is visible. The view still participates in layout
+ // but will not be painted.
+ bool visible_;
+
+ // Whether or not this View is enabled. When disabled, the event system will
+ // not propagate un-handled events beyond the View in the hierarchy.
+ bool enabled_;
+
+ // An identifier for this View. Caller must guarantee uniqueness.
+ int id_;
+
+ // An identifier for a group of potentially related Views.
+ int group_;
+
+ // True if this View is focusable by the FocusManager.
+ bool focusable_;
+
+ // An optional helper that handles layout for child views.
+ scoped_ptr<LayoutManager> layout_manager_;
+
+ // Shows the context menu.
+ ContextMenuController* context_menu_controller_;
+
+ // Delegate for drag and drop related functionality.
+ DragController* drag_controller_;
+
+ DISALLOW_COPY_AND_ASSIGN(View);
+};
+
+} // namespace ui
+
+#endif // UI_VIEWS_VIEW_H_
+
+/*
+
+TODO(beng):
+- focus
+- accessibility
+- scrolling
+- cursors
+- tooltips
+- rtl
+- l10n
+- mousewheel
+- more on painting
+- layer stuff
+- investigate why assorted notifications are necessary
+- native_widget_views
+- native_widget_gtk
+- pick a name
+
+*/ \ No newline at end of file
diff --git a/ui/views/view_unittest.cc b/ui/views/view_unittest.cc
new file mode 100644
index 0000000..14873a0
--- /dev/null
+++ b/ui/views/view_unittest.cc
@@ -0,0 +1,204 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <algorithm>
+
+#include "gfx/canvas.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/views/view.h"
+#include "ui/views/widget/widget.h"
+
+namespace ui {
+
+class ViewTest : public testing::Test {
+ public:
+ ViewTest() {}
+ virtual ~ViewTest() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ViewTest);
+};
+
+TEST_F(ViewTest, SizeAndDisposition) {
+ View v;
+ EXPECT_TRUE(v.bounds().IsEmpty());
+ EXPECT_TRUE(v.visible());
+
+ v.SetBoundsRect(gfx::Rect(10, 10, 200, 200));
+ EXPECT_EQ(200, v.width());
+
+ EXPECT_TRUE(v.GetPreferredSize().IsEmpty());
+}
+
+TEST_F(ViewTest, TreeOperations) {
+ View v;
+ EXPECT_EQ(NULL, v.GetWidget());
+ EXPECT_EQ(0, v.child_count());
+
+ View child1;
+ v.AddChildView(&child1);
+ EXPECT_EQ(1, v.child_count());
+ EXPECT_EQ(&v, child1.parent());
+
+ View child2;
+ v.AddChildViewAt(&child2, 0);
+ EXPECT_EQ(2, v.child_count());
+ EXPECT_EQ(child1.parent(), child2.parent());
+
+ v.RemoveChildView(&child2);
+ EXPECT_EQ(1, v.child_count());
+ EXPECT_EQ(NULL, child2.parent());
+
+ //v.RemoveAllChildViews(false);
+ //EXPECT_EQ(0, v.child_count());
+}
+
+class ObserverView : public View {
+ public:
+ ObserverView()
+ : view_added_(false),
+ view_removed_(false),
+ subject_view_(NULL) {}
+ virtual ~ObserverView() {}
+
+ void ResetTestState() {
+ view_added_ = false;
+ view_removed_ = false;
+ subject_view_ = NULL;
+ }
+
+ // Overridden from View:
+ virtual void OnViewAdded(View* parent, View* child) {
+ subject_view_ = child;
+ view_added_ = true;
+ view_removed_ = false;
+ }
+ virtual void OnViewRemoved(View* parent, View* child) {
+ subject_view_ = child;
+ view_removed_ = true;
+ view_added_ = false;
+ }
+
+ bool view_added() const { return view_added_; }
+ bool view_removed() const { return view_removed_; }
+ View* subject_view() const { return subject_view_; }
+
+ private:
+ bool view_added_;
+ bool view_removed_;
+ View* subject_view_;
+
+ DISALLOW_COPY_AND_ASSIGN(ObserverView);
+};
+
+class WidgetObserverView : public View {
+ public:
+ WidgetObserverView() : in_widget_(false) {}
+ virtual ~WidgetObserverView() {}
+
+ // Overridden from View:
+ virtual void OnViewAddedToWidget() {
+ in_widget_ = true;
+ }
+ virtual void OnViewRemovedFromWidget() {
+ in_widget_ = false;
+ }
+
+ bool in_widget() const { return in_widget_; }
+
+ private:
+ bool in_widget_;
+
+ DISALLOW_COPY_AND_ASSIGN(WidgetObserverView);
+};
+
+/*
+TEST_F(ViewTest, HierarchyObserver) {
+ ObserverView ov;
+ Widget widget(&ov);
+ widget.InitWithNativeViewParent(NULL, gfx::Rect(20, 20, 400, 400));
+
+ // |ov|'s addition to the RootView's hierarchy should have caused these values
+ // to be set.
+ EXPECT_TRUE(ov.view_added());
+ EXPECT_FALSE(ov.view_removed());
+ EXPECT_EQ(&ov, ov.subject_view());
+
+ ov.ResetTestState();
+
+ // Direct descendants.
+ View v2;
+ ov.AddChildView(&v2);
+ EXPECT_TRUE(ov.view_added());
+ EXPECT_FALSE(ov.view_removed());
+ EXPECT_EQ(&v2, ov.subject_view());
+
+ ov.ResetTestState();
+
+ // Nested Views and Widget addition.
+ WidgetObserverView v3;
+ EXPECT_FALSE(v3.in_widget());
+ v2.AddChildView(&v3);
+ EXPECT_TRUE(v3.in_widget());
+ EXPECT_EQ(&widget, v3.GetWidget());
+ EXPECT_TRUE(ov.view_added());
+ EXPECT_FALSE(ov.view_removed());
+ EXPECT_EQ(&v3, ov.subject_view());
+
+ ov.ResetTestState();
+
+ // Removal and Widget removal.
+ ov.RemoveChildView(&v2);
+ EXPECT_FALSE(ov.view_added());
+ EXPECT_TRUE(ov.view_removed());
+ EXPECT_EQ(&v2, ov.subject_view());
+
+ EXPECT_FALSE(v3.in_widget());
+ EXPECT_EQ(NULL, v3.GetWidget());
+}
+*/
+
+TEST_F(ViewTest, Ids) {
+ const int kV1Id = 1;
+ const int kV2Id = 2;
+ const int kV3Id = 3;
+ const int kV4Id = 4;
+ const int kV5Id = 5;
+ const int kGroupId = 1;
+ View v1;
+ v1.set_id(kV1Id);
+ View v2;
+ v2.set_id(kV2Id);
+ View v3;
+ v3.set_id(kV3Id);
+ v3.set_group(kGroupId);
+ View v4;
+ v4.set_id(kV4Id);
+ v4.set_group(kGroupId);
+ v1.AddChildView(&v2);
+ v2.AddChildView(&v3);
+ v2.AddChildView(&v4);
+
+ EXPECT_EQ(&v4, v1.GetViewById(kV4Id));
+ EXPECT_EQ(&v1, v1.GetViewById(kV1Id));
+ EXPECT_EQ(NULL, v1.GetViewById(kV5Id)); // No V5 exists.
+
+ View::ViewVector vec;
+ v1.GetViewsWithGroup(kGroupId, &vec);
+ EXPECT_EQ(2, vec.size());
+ View::ViewVector::const_iterator it = find(vec.begin(), vec.end(), &v3);
+ EXPECT_NE(vec.end(), it);
+ it = find(vec.begin(), vec.end(), &v4);
+ EXPECT_NE(vec.end(), it);
+}
+
+TEST_F(ViewTest, EventHandlers) {
+
+}
+
+TEST_F(ViewTest, Painting) {
+
+}
+
+} // namespace ui
diff --git a/ui/views/views.gyp b/ui/views/views.gyp
new file mode 100644
index 0000000..fa9ad5a
--- /dev/null
+++ b/ui/views/views.gyp
@@ -0,0 +1,186 @@
+# Copyright (c) 2010 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'variables': {
+ 'chromium_code': 1,
+ },
+ 'target_defaults': {
+ 'sources/': [
+ ['exclude', '/(cocoa|gtk|win)/'],
+ ['exclude', '_(cocoa|gtk|linux|mac|posix|skia|win|x)\\.(cc|mm?)$'],
+ ['exclude', '/(gtk|win|x11)_[^/]*\\.cc$'],
+ ],
+ 'conditions': [
+ ['OS=="linux" or OS=="freebsd" or OS=="openbsd"', {'sources/': [
+ ['include', '/gtk/'],
+ ['include', '_(gtk|linux|posix|skia|x)\\.cc$'],
+ ['include', '/(gtk|x11)_[^/]*\\.cc$'],
+ ]}],
+ ['OS=="mac"', {'sources/': [
+ ['include', '/cocoa/'],
+ ['include', '_(cocoa|mac|posix)\\.(cc|mm?)$'],
+ ]}, { # else: OS != "mac"
+ 'sources/': [
+ ['exclude', '\\.mm?$'],
+ ],
+ }],
+ ['OS=="win"', {'sources/': [
+ ['include', '_(win)\\.cc$'],
+ ['include', '/win/'],
+ ['include', '/win_[^/]*\\.cc$'],
+ ]}],
+ ['touchui==0', {'sources/': [
+ ['exclude', 'event_x.cc$'],
+ ['exclude', 'native_menu_x.cc$'],
+ ['exclude', 'native_menu_x.h$'],
+ ['exclude', 'touchui/'],
+ ['exclude', '_(touch)\\.cc$'],
+ ]}],
+ ],
+ },
+ 'targets': [
+ {
+ 'target_name': 'v2',
+ 'type': '<(library)',
+ 'msvs_guid': '70760ECA-4D8B-47A4-ACDC-D3E7F25F0543',
+ 'dependencies': [
+ '<(DEPTH)/app/app.gyp:app_base',
+ '<(DEPTH)/gfx/gfx.gyp:gfx',
+ '<(DEPTH)/skia/skia.gyp:skia',
+ ],
+ 'sources': [
+ 'events/context_menu_controller.h',
+ 'events/drag_controller.h',
+ 'events/event.cc',
+ 'events/event.h',
+ 'events/event_win.cc',
+ 'layout/fill_layout.cc',
+ 'layout/fill_layout.h',
+ 'layout/layout_manager.cc',
+ 'layout/layout_manager.h',
+ 'native_types.h',
+ 'rendering/border.cc',
+ 'rendering/border.h',
+ 'view.cc',
+ 'view.h',
+ 'widget/native_widget.h',
+ 'widget/native_widget_listener.h',
+ 'widget/native_widget_views.cc',
+ 'widget/native_widget_views.h',
+ 'widget/native_widget_win.cc',
+ 'widget/native_widget_win.h',
+ 'widget/root_view.cc',
+ 'widget/root_view.h',
+ 'widget/widget.cc',
+ 'widget/widget.h',
+ 'window/window.cc',
+ 'window/window.h',
+ 'window/native_window.h',
+ 'window/native_window_views.cc',
+ 'window/native_window_views.h',
+ 'window/native_window_win.cc',
+ 'window/native_window_win.h',
+ ],
+ 'include_dirs': [
+ '<(DEPTH)',
+ ],
+ 'conditions': [
+ ['OS=="linux" or OS=="freebsd" or OS=="openbsd"', {
+ 'dependencies': [
+ '<(DEPTH)/build/linux/system.gyp:gtk',
+ '<(DEPTH)/build/linux/system.gyp:x11',
+ '<(DEPTH)/build/linux/system.gyp:xext',
+ ],
+ 'sources!': [
+ ],
+ }],
+ ['OS=="win"', {
+ 'include_dirs': [
+ '<(DEPTH)/third_party/wtl/include',
+ ],
+ }],
+ ],
+ },
+ {
+ 'target_name': 'views_unittests',
+ 'type': 'executable',
+ 'dependencies': [
+ '<(DEPTH)/base/base.gyp:base',
+ '<(DEPTH)/base/base.gyp:test_support_base',
+ '<(DEPTH)/skia/skia.gyp:skia',
+ '<(DEPTH)/testing/gmock.gyp:gmock',
+ '<(DEPTH)/testing/gtest.gyp:gtest',
+ '<(DEPTH)/third_party/icu/icu.gyp:icui18n',
+ '<(DEPTH)/third_party/icu/icu.gyp:icuuc',
+ 'v2',
+ ],
+ 'sources': [
+ 'rendering/border_unittest.cc',
+ 'run_all_unittests.cc',
+ 'view_unittest.cc',
+ 'widget/widget_unittest.cc',
+ ],
+ 'include_dirs': [
+ '<(DEPTH)',
+ ],
+ 'conditions': [
+ ['OS=="linux" or OS=="freebsd" or OS=="openbsd"', {
+ 'dependencies': [
+ '<(DEPTH)/build/linux/system.gyp:gtk',
+ '<(DEPTH)/chrome/chrome.gyp:packed_resources',
+ ],
+ 'conditions': [
+ ['linux_use_tcmalloc==1', {
+ 'dependencies': [
+ '<(DEPTH)/base/allocator/allocator.gyp:allocator',
+ ],
+ }],
+ ],
+ },
+ ],
+ ['OS=="win"', {
+ 'sources': [
+ 'widget/widget.rc',
+ 'widget/widget_resource.h',
+ ],
+ 'link_settings': {
+ 'libraries': [
+ '-limm32.lib',
+ '-loleacc.lib',
+ ]
+ },
+ }],
+ ],
+ },
+ {
+ 'target_name': 'views_demo',
+ 'type': 'executable',
+ 'dependencies': [
+ '<(DEPTH)/skia/skia.gyp:skia',
+ 'v2',
+ ],
+ 'sources': [
+ 'demo/main.cc',
+ ],
+ 'include_dirs': [
+ '<(DEPTH)',
+ ],
+ 'conditions': [
+ ['OS=="win"', {
+ 'sources': [
+ 'widget/widget.rc',
+ 'widget/widget_resource.h',
+ ],
+ }],
+ ],
+ },
+ ],
+}
+
+# Local Variables:
+# tab-width:2
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=2 shiftwidth=2:
diff --git a/ui/views/widget/native_widget.h b/ui/views/widget/native_widget.h
new file mode 100644
index 0000000..f8508a2
--- /dev/null
+++ b/ui/views/widget/native_widget.h
@@ -0,0 +1,69 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_WIDGET_NATIVE_WIDGET_H_
+#define UI_VIEWS_WIDGET_NATIVE_WIDGET_H_
+
+#include "ui/views/native_types.h"
+
+namespace gfx{
+class Path;
+class Rect;
+}
+
+namespace ui {
+namespace internal {
+class NativeWidgetListener;
+}
+class View;
+class Widget;
+
+////////////////////////////////////////////////////////////////////////////////
+// NativeWidget interface
+//
+// An interface implemented by an object that encapsulates rendering, event
+// handling and widget management provided by an underlying native toolkit.
+//
+class NativeWidget {
+ public:
+ virtual ~NativeWidget() {}
+
+ static NativeWidget* CreateNativeWidget(
+ internal::NativeWidgetListener* listener);
+
+ // See Widget for documentation and notes.
+ virtual void InitWithNativeViewParent(gfx::NativeView parent,
+ const gfx::Rect& bounds) = 0;
+ virtual void InitWithWidgetParent(Widget* parent,
+ const gfx::Rect& bounds) = 0;
+ virtual void InitWithViewParent(View* parent, const gfx::Rect& bounds) = 0;
+ virtual void SetNativeWindowProperty(const char* name, void* value) = 0;
+ virtual void* GetNativeWindowProperty(const char* name) const = 0;
+ virtual gfx::Rect GetWindowScreenBounds() const = 0;
+ virtual gfx::Rect GetClientAreaScreenBounds() const = 0;
+ virtual void SetBounds(const gfx::Rect& bounds) = 0;
+ virtual void SetShape(const gfx::Path& shape) = 0;
+ virtual gfx::NativeView GetNativeView() const = 0;
+ virtual void Show() = 0;
+ virtual void Hide() = 0;
+ virtual void Close() = 0;
+ virtual void MoveAbove(NativeWidget* other) = 0;
+ virtual void SetAlwaysOnTop(bool always_on_top) = 0;
+ virtual bool IsVisible() const = 0;
+ virtual bool IsActive() const = 0;
+
+ virtual void SetMouseCapture() = 0;
+ virtual void ReleaseMouseCapture() = 0;
+ virtual bool HasMouseCapture() const = 0;
+ virtual bool ShouldReleaseCaptureOnMouseReleased() const = 0;
+
+ virtual void Invalidate() = 0;
+ virtual void InvalidateRect(const gfx::Rect& invalid_rect) = 0;
+ virtual void Paint() = 0;
+};
+
+} // namespace ui
+
+#endif // UI_VIEWS_WIDGET_NATIVE_WIDGET_H_
+
diff --git a/ui/views/widget/native_widget_listener.h b/ui/views/widget/native_widget_listener.h
new file mode 100644
index 0000000..959c14f
--- /dev/null
+++ b/ui/views/widget/native_widget_listener.h
@@ -0,0 +1,53 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_WIDGET_NATIVE_WIDGET_LISTENER_H_
+#define UI_VIEWS_WIDGET_NATIVE_WIDGET_LISTENER_H_
+
+namespace gfx {
+class Canvas;
+class Point;
+class Size;
+}
+
+namespace ui {
+class KeyEvent;
+class MouseEvent;
+class MouseWheelEvent;
+
+namespace internal {
+
+////////////////////////////////////////////////////////////////////////////////
+// NativeWidgetListener interface
+//
+// An interface implemented by the Widget that handles events sent from a
+// NativeWidget implementation.
+//
+class NativeWidgetListener {
+ public:
+ virtual ~NativeWidgetListener() {}
+
+ virtual void OnClose() = 0;
+
+ virtual void OnDestroy() = 0;
+ virtual void OnDisplayChanged() = 0;
+
+ virtual bool OnKeyEvent(const KeyEvent& event) = 0;
+
+ virtual void OnMouseCaptureLost() = 0;
+
+ virtual bool OnMouseEvent(const MouseEvent& event) = 0;
+ virtual bool OnMouseWheelEvent(const MouseWheelEvent& event) = 0;
+
+ virtual void OnNativeWidgetCreated() = 0;
+
+ virtual void OnPaint(gfx::Canvas* canvas) = 0;
+ virtual void OnSizeChanged(const gfx::Size& size) = 0;
+ virtual void OnWorkAreaChanged() = 0;
+};
+
+} // namespace internal
+} // namespace ui
+
+#endif // UI_VIEWS_WIDGET_NATIVE_WIDGET_LISTENER_H_
diff --git a/ui/views/widget/native_widget_views.cc b/ui/views/widget/native_widget_views.cc
new file mode 100644
index 0000000..edb99fc
--- /dev/null
+++ b/ui/views/widget/native_widget_views.cc
@@ -0,0 +1,10 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+namespace ui {
+namespace internal {
+
+} // namespace internal
+} // namespace ui
+
diff --git a/ui/views/widget/native_widget_views.h b/ui/views/widget/native_widget_views.h
new file mode 100644
index 0000000..766da05
--- /dev/null
+++ b/ui/views/widget/native_widget_views.h
@@ -0,0 +1,15 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_WIDGET_NATIVE_WIDGET_VIEWS_H_
+#define UI_VIEWS_WIDGET_NATIVE_WIDGET_VIEWS_H_
+#pragma once
+
+namespace ui {
+namespace internal {
+
+} // namespace internal
+} // namespace ui
+
+#endif // UI_VIEWS_WIDGET_NATIVE_WIDGET_VIEWS_H_
diff --git a/ui/views/widget/native_widget_win.cc b/ui/views/widget/native_widget_win.cc
new file mode 100644
index 0000000..c5bd930
--- /dev/null
+++ b/ui/views/widget/native_widget_win.cc
@@ -0,0 +1,626 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/widget/native_widget_win.h"
+
+#include "base/scoped_ptr.h"
+#include "gfx/canvas_skia.h"
+#include "gfx/path.h"
+#include "gfx/native_theme_win.h"
+#include "ui/base/system_monitor/system_monitor.h"
+#include "ui/base/view_prop.h"
+#include "ui/views/view.h"
+#include "ui/views/widget/native_widget_listener.h"
+#include "ui/views/widget/widget.h"
+
+namespace ui {
+namespace internal {
+
+namespace {
+
+// Called from NativeWidgetWin::Paint() to asynchronously redraw child windows.
+BOOL CALLBACK EnumChildProcForRedraw(HWND hwnd, LPARAM lparam) {
+ DWORD process_id;
+ GetWindowThreadProcessId(hwnd, &process_id);
+ gfx::Rect invalid_rect = *reinterpret_cast<gfx::Rect*>(lparam);
+
+ RECT window_rect;
+ GetWindowRect(hwnd, &window_rect);
+ invalid_rect.Offset(-window_rect.left, -window_rect.top);
+
+ int flags = RDW_INVALIDATE | RDW_NOCHILDREN | RDW_FRAME;
+ if (process_id == GetCurrentProcessId())
+ flags |= RDW_UPDATENOW;
+ RedrawWindow(hwnd, &invalid_rect.ToRECT(), NULL, flags);
+ return TRUE;
+}
+
+// Links the HWND to its Widget.
+const char* const kNativeWidgetKey = "__VIEWS_NATIVE_WIDGET__";
+
+// A custom MSAA object id used to determine if a screen reader is actively
+// listening for MSAA events.
+const int kMSAAObjectID = 1;
+
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NativeWidgetWin, public:
+
+NativeWidgetWin::NativeWidgetWin(NativeWidgetListener* listener)
+ : listener_(listener),
+ active_mouse_tracking_flags_(0),
+ has_capture_(false) {
+}
+
+NativeWidgetWin::~NativeWidgetWin() {
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NativeWidgetWin, NativeWidget implementation:
+
+void NativeWidgetWin::InitWithNativeViewParent(gfx::NativeView parent,
+ const gfx::Rect& bounds) {
+ WindowImpl::Init(parent, bounds);
+}
+
+void NativeWidgetWin::InitWithWidgetParent(Widget* parent,
+ const gfx::Rect& bounds) {
+ InitWithNativeViewParent(parent->native_widget()->GetNativeView(), bounds);
+}
+
+void NativeWidgetWin::InitWithViewParent(View* parent,
+ const gfx::Rect& bounds) {
+ InitWithWidgetParent(parent->GetWidget(), bounds);
+}
+
+void NativeWidgetWin::SetNativeWindowProperty(const char* name, void* value) {
+ // Remove the existing property (if any).
+ for (ViewProps::iterator i = props_.begin(); i != props_.end(); ++i) {
+ if ((*i)->Key() == name) {
+ props_.erase(i);
+ break;
+ }
+ }
+
+ if (value)
+ props_.push_back(new ViewProp(hwnd(), name, value));
+}
+
+void* NativeWidgetWin::GetNativeWindowProperty(const char* name) const {
+ return ViewProp::GetValue(hwnd(), name);
+}
+
+gfx::Rect NativeWidgetWin::GetWindowScreenBounds() const {
+ RECT r;
+ GetWindowRect(hwnd(), &r);
+ return gfx::Rect(r);
+}
+
+gfx::Rect NativeWidgetWin::GetClientAreaScreenBounds() const {
+ RECT r;
+ GetClientRect(hwnd(), &r);
+ POINT point = { r.left, r.top };
+ ClientToScreen(hwnd(), &point);
+ return gfx::Rect(point.x, point.y, r.right - r.left, r.bottom - r.top);
+}
+
+void NativeWidgetWin::SetBounds(const gfx::Rect& bounds) {
+ SetWindowPos(hwnd(), NULL, bounds.x(), bounds.y(), bounds.width(),
+ bounds.height(), SWP_NOACTIVATE | SWP_NOZORDER);
+}
+
+void NativeWidgetWin::SetShape(const gfx::Path& shape) {
+ SetWindowRgn(hwnd(), shape.CreateNativeRegion(), TRUE);
+}
+
+gfx::NativeView NativeWidgetWin::GetNativeView() const {
+ return hwnd();
+}
+
+void NativeWidgetWin::Show() {
+ if (IsWindow(hwnd()))
+ ShowWindow(hwnd(), SW_SHOWNOACTIVATE);
+ // TODO(beng): move to windowposchanging to trap visibility changes instead.
+ if (IsLayeredWindow())
+ Invalidate();
+}
+
+void NativeWidgetWin::Hide() {
+ if (IsWindow(hwnd())) {
+ // NOTE: Be careful not to activate any windows here (for example, calling
+ // ShowWindow(SW_HIDE) will automatically activate another window). This
+ // code can be called while a window is being deactivated, and activating
+ // another window will screw up the activation that is already in progress.
+ SetWindowPos(hwnd(), NULL, 0, 0, 0, 0,
+ SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOMOVE |
+ SWP_NOREPOSITION | SWP_NOSIZE | SWP_NOZORDER);
+ }
+}
+
+void NativeWidgetWin::Close() {
+ DestroyWindow(hwnd());
+}
+
+void NativeWidgetWin::MoveAbove(NativeWidget* other) {
+ SetWindowPos(hwnd(), other->GetNativeView(), 0, 0, 0, 0,
+ SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
+}
+
+void NativeWidgetWin::SetAlwaysOnTop(bool always_on_top) {
+ DWORD style = always_on_top ? window_ex_style() | WS_EX_TOPMOST
+ : window_ex_style() & ~WS_EX_TOPMOST;
+ set_window_ex_style(style);
+ SetWindowLong(hwnd(), GWL_EXSTYLE, window_ex_style());
+}
+
+bool NativeWidgetWin::IsVisible() const {
+ return !!IsWindowVisible(hwnd());
+}
+
+bool NativeWidgetWin::IsActive() const {
+ WINDOWINFO info;
+ return ::GetWindowInfo(hwnd(), &info) &&
+ ((info.dwWindowStatus & WS_ACTIVECAPTION) != 0);
+}
+
+void NativeWidgetWin::SetMouseCapture() {
+ SetCapture(hwnd());
+ has_capture_ = true;
+}
+
+void NativeWidgetWin::ReleaseMouseCapture() {
+ ReleaseCapture();
+ has_capture_ = false;
+}
+
+bool NativeWidgetWin::HasMouseCapture() const {
+ return has_capture_;
+}
+
+bool NativeWidgetWin::ShouldReleaseCaptureOnMouseReleased() const {
+ return true;
+}
+
+void NativeWidgetWin::Invalidate() {
+ ::InvalidateRect(hwnd(), NULL, FALSE);
+}
+
+void NativeWidgetWin::InvalidateRect(const gfx::Rect& invalid_rect) {
+ // InvalidateRect() expects client coordinates.
+ RECT r = invalid_rect.ToRECT();
+ ::InvalidateRect(hwnd(), &r, FALSE);
+}
+
+void NativeWidgetWin::Paint() {
+ RECT r;
+ GetUpdateRect(hwnd(), &r, FALSE);
+ if (!IsRectEmpty(&r)) {
+ // TODO(beng): WS_EX_TRANSPARENT windows (see WidgetWin::opaque_)
+ // Paint child windows that are in a different process asynchronously.
+ // This prevents a hang in other processes from blocking this process.
+
+ // Calculate the invalid rect in screen coordinates before the first
+ // RedrawWindow() call to the parent HWND, since that will empty update_rect
+ // (which comes from a member variable) in the OnPaint call.
+ gfx::Rect screen_rect = GetWindowScreenBounds();
+ gfx::Rect invalid_screen_rect(r);
+ invalid_screen_rect.Offset(screen_rect.x(), screen_rect.y());
+
+ RedrawWindow(hwnd(), &r, NULL,
+ RDW_INVALIDATE | RDW_UPDATENOW | RDW_NOCHILDREN);
+
+ LPARAM lparam = reinterpret_cast<LPARAM>(&invalid_screen_rect);
+ EnumChildWindows(hwnd(), EnumChildProcForRedraw, lparam);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NativeWidetWin, MessageLoopForUI::Observer implementation
+
+void NativeWidgetWin::WillProcessMessage(const MSG& msg) {
+}
+
+void NativeWidgetWin::DidProcessMessage(const MSG& msg) {
+ // 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
+ // WM_PAINT messages are starved and we get flickery redrawing when resizing
+ // if we do not do this.
+ Paint();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NativeWidgetWin, message handlers:
+
+void NativeWidgetWin::OnActivate(UINT action, BOOL minimized, HWND window) {
+ SetMsgHandled(FALSE);
+}
+
+void NativeWidgetWin::OnActivateApp(BOOL active, DWORD thread_id) {
+ SetMsgHandled(FALSE);
+}
+
+LRESULT NativeWidgetWin::OnAppCommand(HWND window, short app_command,
+ WORD device, int keystate) {
+ SetMsgHandled(FALSE);
+ return 0;
+}
+
+void NativeWidgetWin::OnCancelMode() {
+}
+
+void NativeWidgetWin::OnCaptureChanged(HWND hwnd) {
+ has_capture_ = false;
+ listener_->OnMouseCaptureLost();
+}
+
+void NativeWidgetWin::OnClose() {
+ listener_->OnClose();
+}
+
+void NativeWidgetWin::OnCommand(UINT notification_code, int command_id,
+ HWND window) {
+ SetMsgHandled(FALSE);
+}
+
+LRESULT NativeWidgetWin::OnCreate(CREATESTRUCT* create_struct) {
+ MessageLoopForUI::current()->AddObserver(this);
+ return 0;
+}
+
+void NativeWidgetWin::OnDestroy() {
+ // TODO(beng): drop_target_
+ props_.reset();
+}
+
+void NativeWidgetWin::OnDisplayChange(UINT bits_per_pixel, CSize screen_size) {
+ listener_->OnDisplayChanged();
+}
+
+LRESULT NativeWidgetWin::OnDwmCompositionChanged(UINT message,
+ WPARAM w_param,
+ LPARAM l_param) {
+ SetMsgHandled(FALSE);
+ return 0;
+}
+
+void NativeWidgetWin::OnEndSession(BOOL ending, UINT logoff) {
+ SetMsgHandled(FALSE);
+}
+
+void NativeWidgetWin::OnEnterSizeMove() {
+ SetMsgHandled(FALSE);
+}
+
+LRESULT NativeWidgetWin::OnEraseBkgnd(HDC dc) {
+ // This is needed for magical win32 flicker ju-ju
+ return 1;
+}
+
+void NativeWidgetWin::OnExitMenuLoop(BOOL is_track_popup_menu) {
+ SetMsgHandled(FALSE);
+}
+
+void NativeWidgetWin::OnExitSizeMove() {
+ SetMsgHandled(FALSE);
+}
+
+LRESULT NativeWidgetWin::OnGetObject(UINT message, WPARAM w_param,
+ LPARAM l_param) {
+ return static_cast<LRESULT>(0L);
+}
+
+void NativeWidgetWin::OnGetMinMaxInfo(MINMAXINFO* minmax_info) {
+ SetMsgHandled(FALSE);
+}
+
+void NativeWidgetWin::OnHScroll(int scroll_type, short position,
+ HWND scrollbar) {
+ SetMsgHandled(FALSE);
+}
+
+void NativeWidgetWin::OnInitMenu(HMENU menu) {
+ SetMsgHandled(FALSE);
+}
+
+void NativeWidgetWin::OnInitMenuPopup(HMENU menu, UINT position,
+ BOOL is_system_menu) {
+ SetMsgHandled(FALSE);
+}
+
+LRESULT NativeWidgetWin::OnKeyDown(UINT message, WPARAM w_param,
+ LPARAM l_param) {
+ MSG msg;
+ MakeMSG(&msg, message, w_param, l_param);
+ SetMsgHandled(listener_->OnKeyEvent(KeyEvent(msg)));
+ return 0;
+}
+
+LRESULT NativeWidgetWin::OnKeyUp(UINT message, WPARAM w_param, LPARAM l_param) {
+ MSG msg;
+ MakeMSG(&msg, message, w_param, l_param);
+ SetMsgHandled(listener_->OnKeyEvent(KeyEvent(msg)));
+ return 0;
+}
+
+void NativeWidgetWin::OnKillFocus(HWND focused_window) {
+ // TODO(beng): focus
+ SetMsgHandled(FALSE);
+}
+
+LRESULT NativeWidgetWin::OnMouseActivate(HWND window, UINT hittest_code,
+ UINT message) {
+ SetMsgHandled(FALSE);
+ return MA_ACTIVATE;
+}
+
+LRESULT NativeWidgetWin::OnMouseLeave(UINT message, WPARAM w_param,
+ LPARAM l_param) {
+ // TODO(beng): tooltip
+ MSG msg;
+ MakeMSG(&msg, message, w_param, l_param);
+ SetMsgHandled(listener_->OnMouseEvent(MouseEvent(msg)));
+
+ // Reset our tracking flag so that future mouse movement over this WidgetWin
+ // results in a new tracking session.
+ active_mouse_tracking_flags_ = 0;
+
+ return 0;
+}
+
+void NativeWidgetWin::OnMove(const CPoint& point) {
+ SetMsgHandled(FALSE);
+}
+
+void NativeWidgetWin::OnMoving(UINT param, LPRECT new_bounds) {
+}
+
+LRESULT NativeWidgetWin::OnMouseRange(UINT message, WPARAM w_param,
+ LPARAM l_param) {
+ // TODO(beng): tooltips
+ ProcessMouseRange(message, w_param, l_param, false);
+ return 0;
+}
+
+LRESULT NativeWidgetWin::OnNCActivate(BOOL active) {
+ SetMsgHandled(FALSE);
+ return 0;
+}
+
+LRESULT NativeWidgetWin::OnNCCalcSize(BOOL w_param, LPARAM l_param) {
+ SetMsgHandled(FALSE);
+ return 0;
+}
+
+LRESULT NativeWidgetWin::OnNCHitTest(UINT message, WPARAM w_param,
+ LPARAM l_param) {
+ LRESULT lr = DefWindowProc(hwnd(), message, w_param, l_param);
+ return lr;
+}
+
+LRESULT NativeWidgetWin::OnNCMouseRange(UINT message, WPARAM w_param,
+ LPARAM l_param) {
+ bool processed = ProcessMouseRange(message, w_param, l_param, true);
+ SetMsgHandled(FALSE);
+ return 0;
+}
+
+void NativeWidgetWin::OnNCPaint(HRGN rgn) {
+ SetMsgHandled(FALSE);
+}
+
+LRESULT NativeWidgetWin::OnNCUAHDrawCaption(UINT message,
+ WPARAM w_param,
+ LPARAM l_param) {
+ SetMsgHandled(FALSE);
+ return 0;
+}
+
+LRESULT NativeWidgetWin::OnNCUAHDrawFrame(UINT message,
+ WPARAM w_param,
+ LPARAM l_param) {
+ SetMsgHandled(FALSE);
+ return 0;
+}
+
+LRESULT NativeWidgetWin::OnNotify(int w_param, NMHDR* l_param) {
+ // TODO(beng): tooltips
+ SetMsgHandled(FALSE);
+ return 0;
+}
+
+void NativeWidgetWin::OnPaint(HDC dc) {
+ if (IsLayeredWindow()) {
+ // We need to clip to the dirty rect ourselves.
+ window_contents_->save(SkCanvas::kClip_SaveFlag);
+ RECT r;
+ GetUpdateRect(hwnd(), &r, FALSE);
+ window_contents_->ClipRectInt(r.left, r.top, r.right - r.left,
+ r.bottom - r.top);
+ listener_->OnPaint(window_contents_.get());
+ window_contents_->restore();
+
+ RECT wr;
+ GetWindowRect(hwnd(), &wr);
+ SIZE size = {wr.right - wr.left, wr.bottom - wr.top};
+ POINT position = {wr.left, wr.top};
+ HDC dib_dc = window_contents_->getTopPlatformDevice().getBitmapDC();
+ POINT zero = {0, 0};
+ BLENDFUNCTION blend = {AC_SRC_OVER, 0, 125, AC_SRC_ALPHA};
+ UpdateLayeredWindow(hwnd(), NULL, &position, &size, dib_dc, &zero,
+ RGB(0xFF, 0xFF, 0xFF), &blend, ULW_ALPHA);
+ } else {
+ scoped_ptr<gfx::CanvasPaint> canvas(
+ gfx::CanvasPaint::CreateCanvasPaint(hwnd()));
+ listener_->OnPaint(canvas->AsCanvas());
+ }
+}
+
+LRESULT NativeWidgetWin::OnPowerBroadcast(DWORD power_event, DWORD data) {
+ SystemMonitor* monitor = SystemMonitor::Get();
+ if (monitor)
+ monitor->ProcessWmPowerBroadcastMessage(power_event);
+ SetMsgHandled(FALSE);
+ return 0;
+}
+
+LRESULT NativeWidgetWin::OnReflectedMessage(UINT message, WPARAM w_param,
+ LPARAM l_param) {
+ SetMsgHandled(FALSE);
+ return 0;
+}
+
+void NativeWidgetWin::OnSetFocus(HWND focused_window) {
+ // TODO(beng): focus
+ SetMsgHandled(FALSE);
+}
+
+LRESULT NativeWidgetWin::OnSetIcon(UINT size_type, HICON new_icon) {
+ SetMsgHandled(FALSE);
+ return 0;
+}
+
+LRESULT NativeWidgetWin::OnSetText(const wchar_t* text) {
+ SetMsgHandled(FALSE);
+ return 0;
+}
+
+void NativeWidgetWin::OnSettingChange(UINT flags, const wchar_t* section) {
+ if (flags == SPI_SETWORKAREA)
+ listener_->OnWorkAreaChanged();
+ SetMsgHandled(FALSE);
+}
+
+void NativeWidgetWin::OnSize(UINT param, const CSize& size) {
+ gfx::Size s(size.cx, size.cy);
+ listener_->OnSizeChanged(s);
+ if (IsLayeredWindow()) {
+ window_contents_.reset(
+ new gfx::CanvasSkia(s.width(), s.height(), false));
+ }
+}
+
+void NativeWidgetWin::OnSysCommand(UINT notification_code, CPoint click) {
+ SetMsgHandled(FALSE);
+}
+
+void NativeWidgetWin::OnThemeChanged() {
+ gfx::NativeTheme::instance()->CloseHandles();
+}
+
+void NativeWidgetWin::OnVScroll(int scroll_type, short position,
+ HWND scrollbar) {
+ SetMsgHandled(FALSE);
+}
+
+void NativeWidgetWin::OnWindowPosChanging(WINDOWPOS* window_pos) {
+ SetMsgHandled(FALSE);
+}
+
+void NativeWidgetWin::OnWindowPosChanged(WINDOWPOS* window_pos) {
+ SetMsgHandled(FALSE);
+}
+
+void NativeWidgetWin::OnFinalMessage(HWND window) {
+ delete this;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NativeWidgetWin, WindowImpl overrides:
+
+HICON NativeWidgetWin::GetDefaultWindowIcon() const {
+ return NULL;
+}
+
+LRESULT NativeWidgetWin::OnWndProc(UINT message, WPARAM w_param,
+ LPARAM l_param) {
+ LRESULT result = 0;
+
+ // Otherwise we handle everything else.
+ if (!ProcessWindowMessage(hwnd(), message, w_param, l_param, result))
+ result = DefWindowProc(hwnd(), message, w_param, l_param);
+ if (message == WM_NCDESTROY) {
+ MessageLoopForUI::current()->RemoveObserver(this);
+ OnFinalMessage(hwnd());
+ }
+ return result;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NativeWidgetWin, private:
+
+void NativeWidgetWin::TrackMouseEvents(DWORD mouse_tracking_flags) {
+ // Begin tracking mouse events for this HWND so that we get WM_MOUSELEAVE
+ // when the user moves the mouse outside this HWND's bounds.
+ if (active_mouse_tracking_flags_ == 0 || mouse_tracking_flags & TME_CANCEL) {
+ if (mouse_tracking_flags & TME_CANCEL) {
+ // We're about to cancel active mouse tracking, so empty out the stored
+ // state.
+ active_mouse_tracking_flags_ = 0;
+ } else {
+ active_mouse_tracking_flags_ = mouse_tracking_flags;
+ }
+
+ TRACKMOUSEEVENT tme;
+ tme.cbSize = sizeof(tme);
+ tme.dwFlags = mouse_tracking_flags;
+ tme.hwndTrack = hwnd();
+ tme.dwHoverTime = 0;
+ TrackMouseEvent(&tme);
+ } else if (mouse_tracking_flags != active_mouse_tracking_flags_) {
+ TrackMouseEvents(active_mouse_tracking_flags_ | TME_CANCEL);
+ TrackMouseEvents(mouse_tracking_flags);
+ }
+}
+
+bool NativeWidgetWin::ProcessMouseRange(UINT message, WPARAM w_param,
+ LPARAM l_param, bool non_client) {
+ MSG msg;
+ MakeMSG(&msg, message, w_param, l_param);
+ if (message == WM_MOUSEWHEEL) {
+ // Reroute the mouse-wheel to the window under the mouse pointer if
+ // applicable.
+ // TODO(beng):
+ //if (views::RerouteMouseWheel(hwnd(), w_param, l_param))
+ // return 0;
+ return listener_->OnMouseWheelEvent(MouseWheelEvent(msg));
+ }
+ // Windows only fires WM_MOUSELEAVE events if the application begins
+ // "tracking" mouse events for a given HWND during WM_MOUSEMOVE events.
+ // We need to call |TrackMouseEvents| to listen for WM_MOUSELEAVE.
+ if (!has_capture_)
+ TrackMouseEvents(non_client ? TME_NONCLIENT | TME_LEAVE : TME_LEAVE);
+ return listener_->OnMouseEvent(MouseEvent(msg));
+}
+
+void NativeWidgetWin::MakeMSG(MSG* msg, UINT message, WPARAM w_param,
+ LPARAM l_param) const {
+ msg->hwnd = hwnd();
+ msg->message = message;
+ msg->wParam = w_param;
+ msg->lParam = l_param;
+ msg->time = 0;
+ msg->pt.x = msg->pt.y = 0;
+}
+
+void NativeWidgetWin::CloseNow() {
+ DestroyWindow(hwnd());
+}
+
+bool NativeWidgetWin::IsLayeredWindow() const {
+ return !!(window_ex_style() & WS_EX_LAYERED);
+}
+
+} // namespace internal
+
+////////////////////////////////////////////////////////////////////////////////
+// NativeWidget, public:
+
+// static
+NativeWidget* NativeWidget::CreateNativeWidget(
+ internal::NativeWidgetListener* listener) {
+ return new internal::NativeWidgetWin(listener);
+}
+
+} // namespace ui
diff --git a/ui/views/widget/native_widget_win.h b/ui/views/widget/native_widget_win.h
new file mode 100644
index 0000000..0434a97
--- /dev/null
+++ b/ui/views/widget/native_widget_win.h
@@ -0,0 +1,271 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_WIDGET_NATIVE_WIDGET_WIN_H_
+#define UI_VIEWS_WIDGET_NATIVE_WIDGET_WIN_H_
+
+#include "ui/base/win/window_impl.h"
+#include "base/logging.h"
+#include "base/message_loop.h"
+#include "base/scoped_ptr.h"
+#include "base/scoped_vector.h"
+#include "ui/views/widget/native_widget.h"
+
+namespace gfx {
+class CanvasSkia;
+}
+
+namespace ui {
+class ViewProp;
+namespace internal {
+
+// A Windows message reflected from other windows. This message is sent with the
+// following arguments:
+// HWND - Target window
+// MSG - kReflectedMessage
+// WPARAM - Should be 0
+// LPARAM - Pointer to MSG struct containing the original message.
+const int kReflectedMessage = WM_APP + 3;
+
+// These two messages aren't defined in winuser.h, but they are sent to windows
+// with captions. They appear to paint the window caption and frame.
+// Unfortunately if you override the standard non-client rendering as we do
+// with CustomFrameWindow, sometimes Windows (not deterministically
+// reproducibly but definitely frequently) will send these messages to the
+// window and paint the standard caption/title over the top of the custom one.
+// So we need to handle these messages in CustomFrameWindow to prevent this
+// from happening.
+const int WM_NCUAHDRAWCAPTION = 0xAE;
+const int WM_NCUAHDRAWFRAME = 0xAF;
+
+class NativeWidgetListener;
+
+////////////////////////////////////////////////////////////////////////////////
+// NativeWidgetWin class
+//
+// A NativeWidget implementation that wraps a Win32 HWND.
+//
+class NativeWidgetWin : public NativeWidget,
+ public ui::WindowImpl,
+ public MessageLoopForUI::Observer {
+ public:
+ explicit NativeWidgetWin(NativeWidgetListener* listener);
+ virtual ~NativeWidgetWin();
+
+ private:
+ typedef ScopedVector<ViewProp> ViewProps;
+
+ // Overridden from NativeWidget:
+ virtual void InitWithNativeViewParent(gfx::NativeView parent,
+ const gfx::Rect& bounds);
+ virtual void InitWithWidgetParent(Widget* parent,
+ const gfx::Rect& bounds);
+ virtual void InitWithViewParent(View* parent, const gfx::Rect& bounds);
+ virtual void SetNativeWindowProperty(const char* name, void* value);
+ virtual void* GetNativeWindowProperty(const char* name) const;
+ virtual gfx::Rect GetWindowScreenBounds() const;
+ virtual gfx::Rect GetClientAreaScreenBounds() const;
+ virtual void SetBounds(const gfx::Rect& bounds);
+ virtual void SetShape(const gfx::Path& shape);
+ virtual gfx::NativeView GetNativeView() const;
+ virtual void Show();
+ virtual void Hide();
+ virtual void Close();
+ virtual void MoveAbove(NativeWidget* other);
+ virtual void SetAlwaysOnTop(bool always_on_top);
+ virtual void Invalidate();
+ virtual void InvalidateRect(const gfx::Rect& invalid_rect);
+ virtual void Paint();
+ virtual bool IsVisible() const;
+ virtual bool IsActive() const;
+ virtual void SetMouseCapture();
+ virtual void ReleaseMouseCapture();
+ virtual bool HasMouseCapture() const;
+ virtual bool ShouldReleaseCaptureOnMouseReleased() const;
+
+ // Overridden from MessageLoop::Observer:
+ void WillProcessMessage(const MSG& msg);
+ virtual void DidProcessMessage(const MSG& msg);
+
+ // Message handlers
+ BEGIN_MSG_MAP_EX(NativeWidgetWin)
+ // Range handlers must go first!
+ MESSAGE_RANGE_HANDLER_EX(WM_MOUSEFIRST, WM_MOUSELAST, OnMouseRange)
+ MESSAGE_RANGE_HANDLER_EX(WM_NCMOUSEMOVE, WM_NCMBUTTONDBLCLK, OnNCMouseRange)
+
+ // Reflected message handler
+ MESSAGE_HANDLER_EX(kReflectedMessage, OnReflectedMessage)
+
+ // CustomFrameWindow hacks
+ MESSAGE_HANDLER_EX(WM_NCUAHDRAWCAPTION, OnNCUAHDrawCaption)
+ MESSAGE_HANDLER_EX(WM_NCUAHDRAWFRAME, OnNCUAHDrawFrame)
+
+ // Vista and newer
+ MESSAGE_HANDLER_EX(WM_DWMCOMPOSITIONCHANGED, OnDwmCompositionChanged)
+
+ // Non-atlcrack.h handlers
+ MESSAGE_HANDLER_EX(WM_GETOBJECT, OnGetObject)
+ MESSAGE_HANDLER_EX(WM_NCMOUSELEAVE, OnMouseLeave)
+ MESSAGE_HANDLER_EX(WM_MOUSELEAVE, OnMouseLeave)
+
+ // Key events.
+ MESSAGE_HANDLER_EX(WM_KEYDOWN, OnKeyDown)
+ MESSAGE_HANDLER_EX(WM_KEYUP, OnKeyUp)
+ MESSAGE_HANDLER_EX(WM_SYSKEYDOWN, OnKeyDown);
+ MESSAGE_HANDLER_EX(WM_SYSKEYUP, OnKeyUp);
+
+ // This list is in _ALPHABETICAL_ order! OR I WILL HURT YOU.
+ MSG_WM_ACTIVATE(OnActivate)
+ MSG_WM_ACTIVATEAPP(OnActivateApp)
+ MSG_WM_APPCOMMAND(OnAppCommand)
+ MSG_WM_CANCELMODE(OnCancelMode)
+ MSG_WM_CAPTURECHANGED(OnCaptureChanged)
+ MSG_WM_CLOSE(OnClose)
+ MSG_WM_COMMAND(OnCommand)
+ MSG_WM_CREATE(OnCreate)
+ MSG_WM_DESTROY(OnDestroy)
+ MSG_WM_DISPLAYCHANGE(OnDisplayChange)
+ MSG_WM_ERASEBKGND(OnEraseBkgnd)
+ MSG_WM_ENDSESSION(OnEndSession)
+ MSG_WM_ENTERSIZEMOVE(OnEnterSizeMove)
+ MSG_WM_EXITMENULOOP(OnExitMenuLoop)
+ MSG_WM_EXITSIZEMOVE(OnExitSizeMove)
+ MSG_WM_GETMINMAXINFO(OnGetMinMaxInfo)
+ MSG_WM_HSCROLL(OnHScroll)
+ MSG_WM_INITMENU(OnInitMenu)
+ MSG_WM_INITMENUPOPUP(OnInitMenuPopup)
+ MSG_WM_KILLFOCUS(OnKillFocus)
+ MSG_WM_MOUSEACTIVATE(OnMouseActivate)
+ MSG_WM_MOVE(OnMove)
+ MSG_WM_MOVING(OnMoving)
+ MSG_WM_NCACTIVATE(OnNCActivate)
+ MSG_WM_NCCALCSIZE(OnNCCalcSize)
+ MESSAGE_HANDLER_EX(WM_NCHITTEST, OnNCHitTest)
+ MSG_WM_NCPAINT(OnNCPaint)
+ MSG_WM_NOTIFY(OnNotify)
+ MSG_WM_PAINT(OnPaint)
+ MSG_WM_POWERBROADCAST(OnPowerBroadcast)
+ MSG_WM_SETFOCUS(OnSetFocus)
+ MSG_WM_SETICON(OnSetIcon)
+ MSG_WM_SETTEXT(OnSetText)
+ MSG_WM_SETTINGCHANGE(OnSettingChange)
+ MSG_WM_SIZE(OnSize)
+ MSG_WM_SYSCOMMAND(OnSysCommand)
+ MSG_WM_THEMECHANGED(OnThemeChanged)
+ MSG_WM_VSCROLL(OnVScroll)
+ MSG_WM_WINDOWPOSCHANGING(OnWindowPosChanging)
+ MSG_WM_WINDOWPOSCHANGED(OnWindowPosChanged)
+ END_MSG_MAP()
+
+ virtual void OnActivate(UINT action, BOOL minimized, HWND window);
+ virtual void OnActivateApp(BOOL active, DWORD thread_id);
+ virtual LRESULT OnAppCommand(HWND window, short app_command, WORD device,
+ int keystate);
+ virtual void OnCancelMode();
+ virtual void OnCaptureChanged(HWND hwnd);
+ virtual void OnClose();
+ virtual void OnCommand(UINT notification_code, int command_id, HWND window);
+ virtual LRESULT OnCreate(CREATESTRUCT* create_struct);
+ // WARNING: If you override this be sure and invoke super, otherwise we'll
+ // leak a few things.
+ virtual void OnDestroy();
+ virtual void OnDisplayChange(UINT bits_per_pixel, CSize screen_size);
+ virtual LRESULT OnDwmCompositionChanged(UINT message,
+ WPARAM w_param,
+ LPARAM l_param);
+ virtual void OnEndSession(BOOL ending, UINT logoff);
+ virtual void OnEnterSizeMove();
+ virtual LRESULT OnEraseBkgnd(HDC dc);
+ virtual void OnExitMenuLoop(BOOL is_track_popup_menu);
+ virtual void OnExitSizeMove();
+ virtual LRESULT OnGetObject(UINT message, WPARAM w_param, LPARAM l_param);
+ virtual void OnGetMinMaxInfo(MINMAXINFO* minmax_info);
+ virtual void OnHScroll(int scroll_type, short position, HWND scrollbar);
+ virtual void OnInitMenu(HMENU menu);
+ virtual void OnInitMenuPopup(HMENU menu, UINT position, BOOL is_system_menu);
+ virtual LRESULT OnKeyDown(UINT message, WPARAM w_param, LPARAM l_param);
+ virtual LRESULT OnKeyUp(UINT message, WPARAM w_param, LPARAM l_param);
+ virtual void OnKillFocus(HWND focused_window);
+ virtual LRESULT OnMouseActivate(HWND window, UINT hittest_code, UINT message);
+ virtual LRESULT OnMouseLeave(UINT message, WPARAM w_param, LPARAM l_param);
+ virtual void OnMove(const CPoint& point);
+ virtual void OnMoving(UINT param, LPRECT new_bounds);
+ virtual LRESULT OnMouseRange(UINT message, WPARAM w_param, LPARAM l_param);
+ virtual LRESULT OnNCActivate(BOOL active);
+ virtual LRESULT OnNCCalcSize(BOOL w_param, LPARAM l_param);
+ virtual LRESULT OnNCHitTest(UINT message, WPARAM w_param, LPARAM l_param);
+ virtual LRESULT OnNCMouseRange(UINT message, WPARAM w_param, LPARAM l_param);
+ virtual void OnNCPaint(HRGN rgn);
+ virtual LRESULT OnNCUAHDrawCaption(UINT message,
+ WPARAM w_param,
+ LPARAM l_param);
+ virtual LRESULT OnNCUAHDrawFrame(UINT message, WPARAM w_param,
+ LPARAM l_param);
+ virtual LRESULT OnNotify(int w_param, NMHDR* l_param);
+ virtual void OnPaint(HDC dc);
+ virtual LRESULT OnPowerBroadcast(DWORD power_event, DWORD data);
+ virtual LRESULT OnReflectedMessage(UINT message, WPARAM w_param,
+ LPARAM l_param);
+ virtual void OnSetFocus(HWND focused_window);
+ virtual LRESULT OnSetIcon(UINT size_type, HICON new_icon);
+ virtual LRESULT OnSetText(const wchar_t* text);
+ virtual void OnSettingChange(UINT flags, const wchar_t* section);
+ virtual void OnSize(UINT param, const CSize& size);
+ virtual void OnSysCommand(UINT notification_code, CPoint click);
+ virtual void OnThemeChanged();
+ virtual void OnVScroll(int scroll_type, short position, HWND scrollbar);
+ virtual void OnWindowPosChanging(WINDOWPOS* window_pos);
+ virtual void OnWindowPosChanged(WINDOWPOS* window_pos);
+
+ // Deletes this window as it is destroyed, override to provide different
+ // behavior.
+ virtual void OnFinalMessage(HWND window);
+
+ // Overridden from WindowImpl:
+ virtual HICON GetDefaultWindowIcon() const;
+ virtual LRESULT OnWndProc(UINT message, WPARAM w_param, LPARAM l_param);
+
+ // Start tracking all mouse events so that this window gets sent mouse leave
+ // messages too.
+ void TrackMouseEvents(DWORD mouse_tracking_flags);
+
+ bool ProcessMouseRange(UINT message, WPARAM w_param, LPARAM l_param,
+ bool non_client);
+ void ProcessMouseMoved(const CPoint& point, UINT flags, bool is_nonclient);
+ void ProcessMouseExited();
+
+ // Fills out a MSG struct with the supplied values.
+ void MakeMSG(MSG* msg, UINT message, WPARAM w_param, LPARAM l_param) const;
+
+ void CloseNow();
+
+ bool IsLayeredWindow() const;
+
+ // A listener implementation that handles events received here.
+ NativeWidgetListener* listener_;
+
+ // The flags currently being used with TrackMouseEvent to track mouse
+ // messages. 0 if there is no active tracking. The value of this member is
+ // used when tracking is canceled.
+ DWORD active_mouse_tracking_flags_;
+
+ // True when the HWND has event capture.
+ bool has_capture_;
+
+ // A canvas that contains the window contents in the case of a layered
+ // window.
+ scoped_ptr<gfx::CanvasSkia> window_contents_;
+
+ // Properties associated with this NativeWidget implementation.
+ // TODO(beng): move to Widget.
+ ViewProps props_;
+
+ DISALLOW_COPY_AND_ASSIGN(NativeWidgetWin);
+};
+
+} // namespace internal
+} // namespace ui
+
+#endif // UI_VIEWS_WIDGET_NATIVE_WIDGET_WIN_H_
+
diff --git a/ui/views/widget/root_view.cc b/ui/views/widget/root_view.cc
new file mode 100644
index 0000000..47371cd
--- /dev/null
+++ b/ui/views/widget/root_view.cc
@@ -0,0 +1,145 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/widget/root_view.h"
+
+#include "ui/views/layout/fill_layout.h"
+#include "ui/views/widget/widget.h"
+
+namespace ui {
+namespace internal {
+
+////////////////////////////////////////////////////////////////////////////////
+// RootView, public:
+
+RootView::RootView(Widget* widget, View* contents_view)
+ : widget_(widget),
+ mouse_pressed_handler_(NULL),
+ mouse_move_handler_(NULL) {
+ SetLayoutManager(new FillLayout);
+ AddChildView(contents_view);
+}
+
+RootView::~RootView() {
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// RootView, View overrides:
+
+void RootView::OnViewRemoved(View* parent, View* child) {
+ if (child == mouse_pressed_handler_)
+ mouse_pressed_handler_ = NULL;
+}
+
+bool RootView::OnKeyPressed(const KeyEvent& event) {
+ return true;
+}
+
+bool RootView::OnKeyReleased(const KeyEvent& event) {
+ return true;
+}
+
+bool RootView::OnMouseWheel(const MouseWheelEvent& event) {
+ return true;
+}
+
+bool RootView::OnMousePressed(const MouseEvent& event) {
+ bool handled = false;
+
+ // Find the most View most tightly enclosing the event location that wants to
+ // handle events.
+ mouse_pressed_handler_ = GetViewForPoint(event.location());
+
+ // Walk up the tree from that View until we find one that handles it.
+ while (mouse_pressed_handler_ && mouse_pressed_handler_ != this) {
+ if (!mouse_pressed_handler_->enabled())
+ break;
+
+ MouseEvent target_event(event, this, mouse_pressed_handler_);
+ drag_info_.Reset();
+ bool handled = mouse_pressed_handler_->MousePressed(target_event,
+ &drag_info_);
+ // MousePressed() may have resulted in the handler removing itself from the
+ // hierarchy, which will NULL-out |mouse_pressed_handler_|.
+ if (!mouse_pressed_handler_)
+ break;
+
+ if (handled)
+ return true;
+
+ mouse_pressed_handler_ = mouse_pressed_handler_->parent();
+ }
+ return false;
+}
+
+bool RootView::OnMouseDragged(const MouseEvent& event) {
+ // TODO(beng): Update cursor.
+ if (mouse_pressed_handler_)
+ return mouse_pressed_handler_->MouseDragged(event, &drag_info_);
+ return false;
+}
+
+void RootView::OnMouseReleased(const MouseEvent& event) {
+ // TODO(beng): Update cursor.
+ if (mouse_pressed_handler_) {
+ MouseEvent released_event(event, this, mouse_pressed_handler_);
+ View* mouse_pressed_handler = mouse_pressed_handler_;
+ mouse_pressed_handler_ = NULL;
+ mouse_pressed_handler->MouseReleased(released_event);
+ }
+}
+
+void RootView::OnMouseCaptureLost() {
+ if (mouse_pressed_handler_) {
+ View* mouse_pressed_handler = mouse_pressed_handler_;
+ mouse_pressed_handler_ = NULL;
+ mouse_pressed_handler->OnMouseCaptureLost();
+ }
+}
+
+void RootView::OnMouseMoved(const MouseEvent& event) {
+ // TODO(beng): Update cursor.
+ View* v = GetViewForPoint(event.location());
+ while (v && !v->enabled() && (v != mouse_move_handler_))
+ v = v->parent();
+ if (v && v != this) {
+ if (v != mouse_move_handler_) {
+ OnMouseExited(event);
+ mouse_move_handler_ = v;
+ MouseEvent entered_event(event, this, mouse_move_handler_);
+ mouse_move_handler_->OnMouseEntered(entered_event);
+ }
+ MouseEvent moved_event(event, this, mouse_move_handler_);
+ mouse_move_handler_->OnMouseMoved(moved_event);
+ } else {
+ OnMouseExited(event);
+ }
+}
+
+void RootView::OnMouseExited(const MouseEvent& event) {
+ if (mouse_move_handler_) {
+ MouseEvent exited_event(event, this, mouse_move_handler_);
+ mouse_move_handler_->OnMouseExited(exited_event);
+ mouse_move_handler_ = NULL;
+ }
+}
+
+void RootView::Paint(gfx::Canvas* canvas) {
+ // Public pass-thru to protected base class method.
+ View::Paint(canvas);
+}
+
+void RootView::InvalidateRect(const gfx::Rect& invalid_rect) {
+ widget_->InvalidateRect(invalid_rect);
+}
+
+Widget* RootView::GetWidget() const {
+ return widget_;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// RootView, private:
+
+} // namespace internal
+} // namespace ui
diff --git a/ui/views/widget/root_view.h b/ui/views/widget/root_view.h
new file mode 100644
index 0000000..308717c
--- /dev/null
+++ b/ui/views/widget/root_view.h
@@ -0,0 +1,62 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_WIDGET_ROOT_VIEW_H_
+#define UI_VIEWS_WIDGET_ROOT_VIEW_H_
+#pragma once
+
+#include "ui/views/view.h"
+
+namespace ui {
+namespace internal {
+
+////////////////////////////////////////////////////////////////////////////////
+// RootView class
+//
+// A View subclass that owns a View hierarchy. Used by the Widget to perform
+// View-specific event tracking.
+//
+class RootView : public View {
+ public:
+ RootView(Widget* widget, View* contents_view);
+ virtual ~RootView();
+
+ // Overridden from View:
+ virtual void OnViewRemoved(View* parent, View* child);
+ virtual bool OnKeyPressed(const KeyEvent& event);
+ virtual bool OnKeyReleased(const KeyEvent& event);
+ virtual bool OnMouseWheel(const MouseWheelEvent& event);
+ virtual bool OnMousePressed(const MouseEvent& event);
+ virtual bool OnMouseDragged(const MouseEvent& event);
+ virtual void OnMouseReleased(const MouseEvent& event);
+ virtual void OnMouseCaptureLost();
+ virtual void OnMouseMoved(const MouseEvent& event);
+ virtual void OnMouseExited(const MouseEvent& event);
+ virtual void Paint(gfx::Canvas* canvas);
+ virtual void InvalidateRect(const gfx::Rect& invalid_rect);
+ virtual Widget* GetWidget() const;
+
+ private:
+ Widget* widget_;
+
+ // The View that the mouse was pressed down on. Used to track drag operations
+ // and to target mouse-released events at the correct view.
+ View* mouse_pressed_handler_;
+
+ // The View that the mouse is currently over. Used to track mouse-exited
+ // events as the mouse moves from view to view, and when the mouse leaves the
+ // bounds of the containing Widget.
+ View* mouse_move_handler_;
+
+ // State captured on mouse press that would be useful for a potential drag
+ // operation.
+ DragInfo drag_info_;
+
+ DISALLOW_COPY_AND_ASSIGN(RootView);
+};
+
+} // namespace internal
+} // namespace ui
+
+#endif // UI_VIEWS_WIDGET_ROOT_VIEW_H_
diff --git a/ui/views/widget/widget.cc b/ui/views/widget/widget.cc
new file mode 100644
index 0000000..36af0b1
--- /dev/null
+++ b/ui/views/widget/widget.cc
@@ -0,0 +1,219 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/widget/widget.h"
+
+#include "base/compiler_specific.h"
+#include "base/message_loop.h"
+#include "ui/views/view.h"
+#include "ui/views/widget/native_widget.h"
+#include "ui/views/widget/root_view.h"
+
+namespace ui {
+
+namespace {
+
+// TODO(beng): move to platform file
+int GetHorizontalDragThreshold() {
+ static int threshold = -1;
+ if (threshold == -1)
+ threshold = GetSystemMetrics(SM_CXDRAG) / 2;
+ return threshold;
+}
+
+// TODO(beng): move to platform file
+int GetVerticalDragThreshold() {
+ static int threshold = -1;
+ if (threshold == -1)
+ threshold = GetSystemMetrics(SM_CYDRAG) / 2;
+ return threshold;
+}
+
+bool ExceededDragThreshold(int delta_x, int delta_y) {
+ return (abs(delta_x) > GetHorizontalDragThreshold() ||
+ abs(delta_y) > GetVerticalDragThreshold());
+}
+
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Widget, public:
+
+Widget::Widget(View* contents_view)
+ : ALLOW_THIS_IN_INITIALIZER_LIST(
+ native_widget_(NativeWidget::CreateNativeWidget(this))),
+ ALLOW_THIS_IN_INITIALIZER_LIST(
+ root_view_(new internal::RootView(this, contents_view))),
+ is_mouse_button_pressed_(false),
+ last_mouse_event_was_move_(false),
+ ALLOW_THIS_IN_INITIALIZER_LIST(close_widget_factory_(this)) {
+}
+
+Widget::~Widget() {
+}
+
+void Widget::InitWithNativeViewParent(gfx::NativeView parent,
+ const gfx::Rect& bounds) {
+ native_widget_->InitWithNativeViewParent(parent, bounds);
+}
+
+void Widget::InitWithWidgetParent(Widget* parent, const gfx::Rect& bounds) {
+ native_widget_->InitWithWidgetParent(parent, bounds);
+}
+
+void Widget::InitWithViewParent(View* parent, const gfx::Rect& bounds) {
+ native_widget_->InitWithViewParent(parent, bounds);
+}
+
+gfx::Rect Widget::GetWindowScreenBounds() const {
+ return native_widget_->GetWindowScreenBounds();
+}
+
+gfx::Rect Widget::GetClientAreaScreenBounds() const {
+ return native_widget_->GetClientAreaScreenBounds();
+}
+
+void Widget::SetBounds(const gfx::Rect& bounds) {
+ native_widget_->SetBounds(bounds);
+}
+
+void Widget::SetShape(const gfx::Path& shape) {
+ native_widget_->SetShape(shape);
+}
+
+void Widget::Show() {
+ native_widget_->Show();
+}
+
+void Widget::Hide() {
+ native_widget_->Hide();
+}
+
+void Widget::Close() {
+ native_widget_->Hide();
+
+ if (close_widget_factory_.empty()) {
+ MessageLoop::current()->PostTask(FROM_HERE,
+ close_widget_factory_.NewRunnableMethod(&Widget::CloseNow));
+ }
+}
+
+void Widget::MoveAbove(Widget* other) {
+ native_widget_->MoveAbove(other->native_widget());
+}
+
+void Widget::InvalidateRect(const gfx::Rect& invalid_rect) {
+ native_widget_->InvalidateRect(invalid_rect);
+}
+
+ThemeProvider* Widget::GetThemeProvider() const {
+ return NULL;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Widget, NativeWidgetListener implementation:
+
+void Widget::OnClose() {
+ Close();
+}
+
+void Widget::OnDestroy() {
+ if (delete_on_destroy_)
+ delete this;
+}
+
+void Widget::OnDisplayChanged() {
+ // TODO(beng):
+}
+
+bool Widget::OnKeyEvent(const KeyEvent& event) {
+ // find root view.
+
+ //return root_view_->OnKeyEvent(event);
+ return true;
+}
+
+void Widget::OnMouseCaptureLost() {
+ if (native_widget_->HasMouseCapture()) {
+ if (is_mouse_button_pressed_)
+ root_view_->OnMouseCaptureLost();
+ is_mouse_button_pressed_ = false;
+ }
+}
+
+bool Widget::OnMouseEvent(const MouseEvent& event) {
+ last_mouse_event_was_move_ = false;
+ switch (event.type()) {
+ case Event::ET_MOUSE_PRESSED:
+ if (root_view_->OnMousePressed(event)) {
+ is_mouse_button_pressed_ = true;
+ if (!native_widget_->HasMouseCapture())
+ native_widget_->SetMouseCapture();
+ return true;
+ }
+ return false;
+ case Event::ET_MOUSE_RELEASED:
+ // TODO(beng): NativeWidgetGtk should not call this function if drag data
+ // exists, see comment in this function in WidgetGtk.
+ // Release the capture first, that way we don't get confused if
+ // OnMouseReleased blocks.
+ if (native_widget_->HasMouseCapture() &&
+ native_widget_->ShouldReleaseCaptureOnMouseReleased()) {
+ native_widget_->ReleaseMouseCapture();
+ }
+ is_mouse_button_pressed_ = false;
+ root_view_->OnMouseReleased(event);
+ return true;
+ case Event::ET_MOUSE_MOVED:
+ if (native_widget_->HasMouseCapture() && is_mouse_button_pressed_) {
+ last_mouse_event_was_move_ = false;
+ root_view_->OnMouseDragged(event);
+ } else {
+ gfx::Point screen_loc(event.location());
+ View::ConvertPointToScreen(root_view_.get(), &screen_loc);
+ if (last_mouse_event_was_move_ &&
+ last_mouse_event_position_ == screen_loc) {
+ // Don't generate a mouse event for the same location as the last.
+ return true;
+ }
+ last_mouse_event_position_ = screen_loc;
+ last_mouse_event_was_move_ = true;
+ root_view_->OnMouseMoved(event);
+ }
+ break;
+ case Event::ET_MOUSE_EXITED:
+ root_view_->OnMouseExited(event);
+ return true;
+ }
+ return true;
+}
+
+bool Widget::OnMouseWheelEvent(const MouseWheelEvent& event) {
+ return root_view_->OnMouseWheel(event);
+}
+
+void Widget::OnNativeWidgetCreated() {
+}
+
+void Widget::OnPaint(gfx::Canvas* canvas) {
+ root_view_->Paint(canvas);
+}
+
+void Widget::OnSizeChanged(const gfx::Size& size) {
+ root_view_->SetSize(size);
+}
+
+void Widget::OnWorkAreaChanged() {
+
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Widget, private:
+
+void Widget::CloseNow() {
+ native_widget_->Close();
+}
+
+} // namespace ui
+
diff --git a/ui/views/widget/widget.h b/ui/views/widget/widget.h
new file mode 100644
index 0000000..9a68eab
--- /dev/null
+++ b/ui/views/widget/widget.h
@@ -0,0 +1,131 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_WIDGET_WIDGET_H_
+#define UI_VIEWS_WIDGET_WIDGET_H_
+
+#include "base/logging.h"
+#include "base/scoped_ptr.h"
+#include "base/task.h"
+#include "gfx/point.h"
+#include "ui/views/native_types.h"
+#include "ui/views/widget/native_widget_listener.h"
+
+namespace gfx {
+class Path;
+class Rect;
+}
+
+namespace ui {
+namespace internal {
+class RootView;
+}
+class NativeWidget;
+class ThemeProvider;
+class View;
+
+////////////////////////////////////////////////////////////////////////////////
+// Widget class
+//
+// Encapsulates the platform-specific rendering, event receiving and widget
+// management aspects of the UI framework.
+//
+// Owns a RootView and thus a View hierarchy. Can contain child Widgets.
+// Widget is a platform-independent type that communicates with a platform or
+// context specific NativeWidget implementation.
+//
+// TODO(beng): Consider ownership of this object vs. NativeWidget.
+class Widget : public internal::NativeWidgetListener {
+ public:
+ explicit Widget(View* contents_view);
+ virtual ~Widget();
+
+ bool set_delete_on_destroy(bool delete_on_destroy) {
+ delete_on_destroy_ = delete_on_destroy;
+ }
+
+ // Initialization.
+ void InitWithNativeViewParent(gfx::NativeView parent,
+ const gfx::Rect& bounds);
+ void InitWithWidgetParent(Widget* parent, const gfx::Rect& bounds);
+ void InitWithViewParent(View* parent, const gfx::Rect& bounds);
+
+ // Returns the bounding rect of the Widget in screen coordinates.
+ gfx::Rect GetWindowScreenBounds() const;
+
+ // Returns the bounding rect of the Widget's client area, in screen
+ // coordinates.
+ gfx::Rect GetClientAreaScreenBounds() const;
+
+ // Sets the bounding rect of the Widget, in the coordinate system of its
+ // parent.
+ void SetBounds(const gfx::Rect& bounds);
+
+ void SetShape(const gfx::Path& shape);
+
+ void Show();
+ void Hide();
+
+ void Close();
+
+ void MoveAbove(Widget* other);
+ void SetAlwaysOnTop(bool always_on_top);
+
+ // Causes the specified rectangle to be added to the invalid rectangle for the
+ // Widget.
+ void InvalidateRect(const gfx::Rect& invalid_rect);
+
+ // Returns a ThemeProvider that can be used to provide resources when
+ // rendering Views associated with this Widget.
+ ThemeProvider* GetThemeProvider() const;
+
+ NativeWidget* native_widget() const { return native_widget_.get(); }
+
+ private:
+ // NativeWidgetListener implementation:
+ virtual void OnClose();
+ virtual void OnDestroy();
+ virtual void OnDisplayChanged();
+ virtual bool OnKeyEvent(const KeyEvent& event);
+ virtual void OnMouseCaptureLost();
+ virtual bool OnMouseEvent(const MouseEvent& event);
+ virtual bool OnMouseWheelEvent(const MouseWheelEvent& event);
+ virtual void OnNativeWidgetCreated();
+ virtual void OnPaint(gfx::Canvas* canvas);
+ virtual void OnSizeChanged(const gfx::Size& size);
+ virtual void OnWorkAreaChanged();
+
+ // Causes the Widget to be destroyed immediately.
+ void CloseNow();
+
+ // A NativeWidget implementation. This can be changed dynamically to a
+ // different implementation during the lifetime of the Widget.
+ scoped_ptr<NativeWidget> native_widget_;
+
+ // A RootView that owns the View hierarchy within this Widget.
+ scoped_ptr<internal::RootView> root_view_;
+
+ // True when any mouse button is pressed.
+ bool is_mouse_button_pressed_;
+
+ // The following are used to detect duplicate mouse move events and not
+ // deliver them. Displaying a window may result in the system generating
+ // duplicate move events even though the mouse hasn't moved.
+ bool last_mouse_event_was_move_;
+ gfx::Point last_mouse_event_position_;
+
+ // Handles closing the Widget after a return to the message loop to allow the
+ // stack to unwind.
+ ScopedRunnableMethodFactory<Widget> close_widget_factory_;
+
+ // True if the Widget should be automatically deleted when it is destroyed.
+ bool delete_on_destroy_;
+
+ DISALLOW_COPY_AND_ASSIGN(Widget);
+};
+
+} // namespace ui
+
+#endif // UI_VIEWS_WIDGET_WIDGET_H_
+
diff --git a/ui/views/widget/widget.rc b/ui/views/widget/widget.rc
new file mode 100644
index 0000000..c2bfa98
--- /dev/null
+++ b/ui/views/widget/widget.rc
@@ -0,0 +1,9 @@
+// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+// PARTICULAR PURPOSE.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved
+
+#include "ui/views/widget/widget_resource.h"
+#include <windows.h>
diff --git a/ui/views/widget/widget_resource.h b/ui/views/widget/widget_resource.h
new file mode 100644
index 0000000..aaf3ebc
--- /dev/null
+++ b/ui/views/widget/widget_resource.h
@@ -0,0 +1,11 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_WIDGET_WIDGET_RESOURCE_H_
+#define UI_VIEWS_WIDGET_WIDGET_RESOURCE_H_
+#pragma once
+
+#define IDR_PIXEL_SHADER 100
+
+#endif // UI_VIEWS_WIDGET_WIDGET_RESOURCE_H_
diff --git a/ui/views/widget/widget_unittest.cc b/ui/views/widget/widget_unittest.cc
new file mode 100644
index 0000000..2233e5d
--- /dev/null
+++ b/ui/views/widget/widget_unittest.cc
@@ -0,0 +1,23 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/logging.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace ui {
+
+class WidgetTest : public testing::Test {
+ public:
+ WidgetTest() {}
+ virtual ~WidgetTest() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(WidgetTest);
+};
+
+TEST_F(WidgetTest, Init) {
+}
+
+} // namespace ui
+
diff --git a/ui/views/window/native_window.h b/ui/views/window/native_window.h
new file mode 100644
index 0000000..7a37f38
--- /dev/null
+++ b/ui/views/window/native_window.h
@@ -0,0 +1,3 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
diff --git a/ui/views/window/native_window_views.cc b/ui/views/window/native_window_views.cc
new file mode 100644
index 0000000..7a37f38
--- /dev/null
+++ b/ui/views/window/native_window_views.cc
@@ -0,0 +1,3 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
diff --git a/ui/views/window/native_window_views.h b/ui/views/window/native_window_views.h
new file mode 100644
index 0000000..7a37f38
--- /dev/null
+++ b/ui/views/window/native_window_views.h
@@ -0,0 +1,3 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
diff --git a/ui/views/window/native_window_win.cc b/ui/views/window/native_window_win.cc
new file mode 100644
index 0000000..7a37f38
--- /dev/null
+++ b/ui/views/window/native_window_win.cc
@@ -0,0 +1,3 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
diff --git a/ui/views/window/native_window_win.h b/ui/views/window/native_window_win.h
new file mode 100644
index 0000000..7a37f38
--- /dev/null
+++ b/ui/views/window/native_window_win.h
@@ -0,0 +1,3 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
diff --git a/ui/views/window/window.cc b/ui/views/window/window.cc
new file mode 100644
index 0000000..7a37f38
--- /dev/null
+++ b/ui/views/window/window.cc
@@ -0,0 +1,3 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
diff --git a/ui/views/window/window.h b/ui/views/window/window.h
new file mode 100644
index 0000000..7a37f38
--- /dev/null
+++ b/ui/views/window/window.h
@@ -0,0 +1,3 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.