diff options
author | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-02 22:07:05 +0000 |
---|---|---|
committer | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-02 22:07:05 +0000 |
commit | 14bcec307d7ec6b13e90fe5e5ac8ca5aaa397b4b (patch) | |
tree | 7c88cf92588f0d99a38757f52cc92b47f7e053ef /views/widget | |
parent | 6b8b0f08cfebb37c13f6c835c37d9ed9e982fc37 (diff) | |
download | chromium_src-14bcec307d7ec6b13e90fe5e5ac8ca5aaa397b4b.zip chromium_src-14bcec307d7ec6b13e90fe5e5ac8ca5aaa397b4b.tar.gz chromium_src-14bcec307d7ec6b13e90fe5e5ac8ca5aaa397b4b.tar.bz2 |
Move NonClientView and FrameType logic from Window to Widget.
Also fixes leak of default WidgetDelegate by replacing it with a DefaultWidgetDelegate subclass that overrides DeleteDelegate and deletes itself. This required moving the destruction logic from Window down onto Widget.
BUG=72040
TEST=none
Review URL: http://codereview.chromium.org/7033049
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@87702 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'views/widget')
-rw-r--r-- | views/widget/native_widget.h | 8 | ||||
-rw-r--r-- | views/widget/native_widget_delegate.h | 3 | ||||
-rw-r--r-- | views/widget/native_widget_gtk.cc | 22 | ||||
-rw-r--r-- | views/widget/native_widget_gtk.h | 4 | ||||
-rw-r--r-- | views/widget/native_widget_views.cc | 15 | ||||
-rw-r--r-- | views/widget/native_widget_views.h | 4 | ||||
-rw-r--r-- | views/widget/native_widget_win.cc | 107 | ||||
-rw-r--r-- | views/widget/native_widget_win.h | 9 | ||||
-rw-r--r-- | views/widget/widget.cc | 67 | ||||
-rw-r--r-- | views/widget/widget.h | 60 | ||||
-rw-r--r-- | views/widget/widget_delegate.cc | 4 | ||||
-rw-r--r-- | views/widget/widget_delegate.h | 5 |
12 files changed, 305 insertions, 3 deletions
diff --git a/views/widget/native_widget.h b/views/widget/native_widget.h index f3faba0..6cb4147 100644 --- a/views/widget/native_widget.h +++ b/views/widget/native_widget.h @@ -66,6 +66,14 @@ class NativeWidget { // Initializes the NativeWidget. virtual void InitNativeWidget(const Widget::InitParams& params) = 0; + // Returns a NonClientFrameView for the widget's NonClientView, or NULL if + // the NativeWidget wants no special NonClientFrameView. + virtual NonClientFrameView* CreateNonClientFrameView() = 0; + + virtual void UpdateFrameAfterFrameChange() = 0; + virtual bool ShouldUseNativeFrame() const = 0; + virtual void FrameTypeChanged() = 0; + // Returns the Widget associated with this NativeWidget. This function is // guaranteed to return non-NULL for the lifetime of the NativeWidget. virtual Widget* GetWidget() = 0; diff --git a/views/widget/native_widget_delegate.h b/views/widget/native_widget_delegate.h index 05af457..d39bd58 100644 --- a/views/widget/native_widget_delegate.h +++ b/views/widget/native_widget_delegate.h @@ -31,6 +31,9 @@ class NativeWidgetDelegate { // Called when the native widget is created. virtual void OnNativeWidgetCreated() = 0; + // Called just after the native widget is destroyed. + virtual void OnNativeWidgetDestroyed() = 0; + // Called when the NativeWidget changed size to |new_size|. virtual void OnSizeChanged(const gfx::Size& new_size) = 0; diff --git a/views/widget/native_widget_gtk.cc b/views/widget/native_widget_gtk.cc index c5f926c..392abe8 100644 --- a/views/widget/native_widget_gtk.cc +++ b/views/widget/native_widget_gtk.cc @@ -736,6 +736,27 @@ void NativeWidgetGtk::InitNativeWidget(const Widget::InitParams& params) { } } +NonClientFrameView* NativeWidgetGtk::CreateNonClientFrameView() { + return NULL; +} + +void NativeWidgetGtk::UpdateFrameAfterFrameChange() { + // We currently don't support different frame types on Gtk, so we don't + // need to implement this. + NOTIMPLEMENTED(); +} + +bool NativeWidgetGtk::ShouldUseNativeFrame() const { + return false; +} + +void NativeWidgetGtk::FrameTypeChanged() { + // This is called when the Theme has changed, so forward the event to the root + // widget. + GetWidget()->ThemeChanged(); + GetWidget()->GetRootView()->SchedulePaint(); +} + Widget* NativeWidgetGtk::GetWidget() { return delegate_->AsWidget(); } @@ -1435,6 +1456,7 @@ void NativeWidgetGtk::OnDestroy(GtkWidget* object) { } void NativeWidgetGtk::OnDestroyed(GObject *where_the_object_was) { + delegate_->OnNativeWidgetDestroyed(); if (ownership_ == Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET) delete this; } diff --git a/views/widget/native_widget_gtk.h b/views/widget/native_widget_gtk.h index e6a9951..2603298 100644 --- a/views/widget/native_widget_gtk.h +++ b/views/widget/native_widget_gtk.h @@ -148,6 +148,10 @@ class NativeWidgetGtk : public NativeWidget, // Overridden from NativeWidget: virtual void InitNativeWidget(const Widget::InitParams& params) OVERRIDE; + virtual NonClientFrameView* CreateNonClientFrameView() OVERRIDE; + virtual void UpdateFrameAfterFrameChange() OVERRIDE; + virtual bool ShouldUseNativeFrame() const OVERRIDE; + virtual void FrameTypeChanged() OVERRIDE; virtual Widget* GetWidget() OVERRIDE; virtual const Widget* GetWidget() const OVERRIDE; virtual gfx::NativeView GetNativeView() const OVERRIDE; diff --git a/views/widget/native_widget_views.cc b/views/widget/native_widget_views.cc index 9f26791..d0eebe4 100644 --- a/views/widget/native_widget_views.cc +++ b/views/widget/native_widget_views.cc @@ -48,6 +48,21 @@ void NativeWidgetViews::InitNativeWidget(const Widget::InitParams& params) { // TODO(beng): SetInitParams(). } +NonClientFrameView* NativeWidgetViews::CreateNonClientFrameView() { + return NULL; +} + +void NativeWidgetViews::UpdateFrameAfterFrameChange() { +} + +bool NativeWidgetViews::ShouldUseNativeFrame() const { + NOTIMPLEMENTED(); + return false; +} + +void NativeWidgetViews::FrameTypeChanged() { +} + Widget* NativeWidgetViews::GetWidget() { return delegate_->AsWidget(); } diff --git a/views/widget/native_widget_views.h b/views/widget/native_widget_views.h index 96bdc9a..f6d445d 100644 --- a/views/widget/native_widget_views.h +++ b/views/widget/native_widget_views.h @@ -35,6 +35,10 @@ class NativeWidgetViews : public NativeWidget { protected: // Overridden from NativeWidget: virtual void InitNativeWidget(const Widget::InitParams& params) OVERRIDE; + virtual NonClientFrameView* CreateNonClientFrameView() OVERRIDE; + virtual void UpdateFrameAfterFrameChange() OVERRIDE; + virtual bool ShouldUseNativeFrame() const OVERRIDE; + virtual void FrameTypeChanged() OVERRIDE; virtual Widget* GetWidget() OVERRIDE; virtual const Widget* GetWidget() const OVERRIDE; virtual gfx::NativeView GetNativeView() const OVERRIDE; diff --git a/views/widget/native_widget_win.cc b/views/widget/native_widget_win.cc index 1afb3e5..db9f73a 100644 --- a/views/widget/native_widget_win.cc +++ b/views/widget/native_widget_win.cc @@ -37,6 +37,7 @@ #include "views/widget/native_widget_delegate.h" #include "views/widget/root_view.h" #include "views/widget/widget_delegate.h" +#include "views/window/native_frame_view.h" #include "views/window/native_window_win.h" #pragma comment(lib, "dwmapi.lib") @@ -167,6 +168,21 @@ void SetChildBounds(HWND child_window, actual_bounds.height(), flags); } +// Callback used to notify child windows that the top level window received a +// DWMCompositionChanged message. +BOOL CALLBACK SendDwmCompositionChanged(HWND window, LPARAM param) { + SendMessage(window, WM_DWMCOMPOSITIONCHANGED, 0, 0); + return TRUE; +} + +// Tells the window its frame (non-client area) has changed. +void SendFrameChanged(HWND window) { + SetWindowPos(window, NULL, 0, 0, 0, 0, + SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOCOPYBITS | + SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOREPOSITION | + SWP_NOSENDCHANGING | SWP_NOSIZE | SWP_NOZORDER); +} + // Links the HWND to its NativeWidget. const char* const kNativeWidgetKey = "__VIEWS_NATIVE_WIDGET__"; @@ -275,6 +291,49 @@ void NativeWidgetWin::InitNativeWidget(const Widget::InitParams& params) { WindowImpl::Init(parent, params.bounds); } +NonClientFrameView* NativeWidgetWin::CreateNonClientFrameView() { + return GetWidget()->ShouldUseNativeFrame() ? + new NativeFrameView(GetWidget()) : NULL; +} + +void NativeWidgetWin::UpdateFrameAfterFrameChange() { + // We've either gained or lost a custom window region, so reset it now. + ResetWindowRegion(true); +} + +bool NativeWidgetWin::ShouldUseNativeFrame() const { + return IsAeroGlassEnabled(); +} + +void NativeWidgetWin::FrameTypeChanged() { + // Called when the frame type could possibly be changing (theme change or + // DWM composition change). + if (base::win::GetVersion() >= base::win::VERSION_VISTA) { + // We need to toggle the rendering policy of the DWM/glass frame as we + // change from opaque to glass. "Non client rendering enabled" means that + // the DWM's glass non-client rendering is enabled, which is why + // DWMNCRP_ENABLED is used for the native frame case. _DISABLED means the + // DWM doesn't render glass, and so is used in the custom frame case. + DWMNCRENDERINGPOLICY policy = GetWidget()->ShouldUseNativeFrame() ? + DWMNCRP_ENABLED : DWMNCRP_DISABLED; + DwmSetWindowAttribute(GetNativeView(), DWMWA_NCRENDERING_POLICY, + &policy, sizeof(DWMNCRENDERINGPOLICY)); + } + + // Send a frame change notification, since the non-client metrics have + // changed. + SendFrameChanged(GetNativeView()); + + // Update the non-client view with the correct frame view for the active frame + // type. + GetWidget()->non_client_view()->UpdateFrame(); + + // WM_DWMCOMPOSITIONCHANGED is only sent to top level windows, however we want + // to notify our children too, since we can have MDI child windows who need to + // update their appearance. + EnumChildWindows(GetNativeView(), &SendDwmCompositionChanged, NULL); +} + Widget* NativeWidgetWin::GetWidget() { return delegate_->AsWidget(); } @@ -1241,7 +1300,9 @@ void NativeWidgetWin::OnSettingChange(UINT flags, const wchar_t* section) { } void NativeWidgetWin::OnSize(UINT param, const CSize& size) { - SetMsgHandled(FALSE); + // ResetWindowRegion is going to trigger WM_NCPAINT. By doing it after we've + // invoked OnSize we ensure the RootView has been laid out. + ResetWindowRegion(false); } void NativeWidgetWin::OnSysCommand(UINT notification_code, CPoint click) { @@ -1275,6 +1336,7 @@ void NativeWidgetWin::OnWindowPosChanged(WINDOWPOS* window_pos) { } void NativeWidgetWin::OnFinalMessage(HWND window) { + delegate_->OnNativeWidgetDestroyed(); if (ownership_ == Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET) delete this; } @@ -1478,6 +1540,49 @@ void NativeWidgetWin::ClientAreaSizeChanged() { } } +void NativeWidgetWin::ResetWindowRegion(bool force) { + // A native frame uses the native window region, and we don't want to mess + // with it. + if (GetWidget()->ShouldUseNativeFrame()) { + if (force) + SetWindowRgn(NULL, TRUE); + return; + } + + // Changing the window region is going to force a paint. Only change the + // window region if the region really differs. + HRGN current_rgn = CreateRectRgn(0, 0, 0, 0); + int current_rgn_result = GetWindowRgn(GetNativeView(), current_rgn); + + CRect window_rect; + GetWindowRect(&window_rect); + HRGN new_region; + if (IsMaximized()) { + HMONITOR monitor = + MonitorFromWindow(GetNativeView(), MONITOR_DEFAULTTONEAREST); + MONITORINFO mi; + mi.cbSize = sizeof mi; + GetMonitorInfo(monitor, &mi); + CRect work_rect = mi.rcWork; + work_rect.OffsetRect(-window_rect.left, -window_rect.top); + new_region = CreateRectRgnIndirect(&work_rect); + } else { + gfx::Path window_mask; + GetWidget()->non_client_view()->GetWindowMask( + gfx::Size(window_rect.Width(), window_rect.Height()), &window_mask); + new_region = window_mask.CreateNativeRegion(); + } + + if (current_rgn_result == ERROR || !EqualRgn(current_rgn, new_region)) { + // SetWindowRgn takes ownership of the HRGN created by CreateNativeRegion. + SetWindowRgn(new_region, TRUE); + } else { + DeleteObject(new_region); + } + + DeleteObject(current_rgn); +} + gfx::AcceleratedWidget NativeWidgetWin::GetAcceleratedWidget() { #if defined(VIEWS_COMPOSITOR) return hwnd(); diff --git a/views/widget/native_widget_win.h b/views/widget/native_widget_win.h index 40f4c84..7dd4995 100644 --- a/views/widget/native_widget_win.h +++ b/views/widget/native_widget_win.h @@ -176,6 +176,10 @@ class NativeWidgetWin : public ui::WindowImpl, // Overridden from NativeWidget: virtual void InitNativeWidget(const Widget::InitParams& params) OVERRIDE; + virtual NonClientFrameView* CreateNonClientFrameView() OVERRIDE; + virtual void UpdateFrameAfterFrameChange() OVERRIDE; + virtual bool ShouldUseNativeFrame() const OVERRIDE; + virtual void FrameTypeChanged() OVERRIDE; virtual Widget* GetWidget() OVERRIDE; virtual const Widget* GetWidget() const OVERRIDE; virtual gfx::NativeView GetNativeView() const OVERRIDE; @@ -475,6 +479,11 @@ class NativeWidgetWin : public ui::WindowImpl, // or subsequently. void ClientAreaSizeChanged(); + // Resets the window region for the current widget bounds if necessary. + // If |force| is true, the window region is reset to NULL even for native + // frame windows. + void ResetWindowRegion(bool force); + // Overridden from NativeWidget. virtual gfx::AcceleratedWidget GetAcceleratedWidget() OVERRIDE; diff --git a/views/widget/widget.cc b/views/widget/widget.cc index bc84fb0..e2b2202 100644 --- a/views/widget/widget.cc +++ b/views/widget/widget.cc @@ -14,6 +14,7 @@ #include "views/widget/root_view.h" #include "views/widget/native_widget.h" #include "views/widget/widget_delegate.h" +#include "views/window/custom_frame_view.h" namespace views { @@ -22,6 +23,22 @@ namespace { bool use_pure_views = false; } +// A default implementation of WidgetDelegate, used by Widget when no +// WidgetDelegate is supplied. +class DefaultWidgetDelegate : public WidgetDelegate { + public: + DefaultWidgetDelegate() {} + virtual ~DefaultWidgetDelegate() {} + + // Overridden from WidgetDelegate: + virtual void DeleteDelegate() OVERRIDE { + delete this; + } + + private: + DISALLOW_COPY_AND_ASSIGN(DefaultWidgetDelegate); +}; + //////////////////////////////////////////////////////////////////////////////// // Widget, InitParams: @@ -73,10 +90,13 @@ Widget::Widget() : is_mouse_button_pressed_(false), last_mouse_event_was_move_(false), native_widget_(NULL), + type_(InitParams::TYPE_WINDOW), widget_delegate_(NULL), + non_client_view_(NULL), dragged_view_(NULL), ownership_(InitParams::NATIVE_WIDGET_OWNS_WIDGET), - is_secondary_widget_(true) { + is_secondary_widget_(true), + frame_type_(FRAME_TYPE_DEFAULT) { } Widget::~Widget() { @@ -104,7 +124,9 @@ Widget* Widget::GetWidgetForNativeView(gfx::NativeView native_view) { } void Widget::Init(const InitParams& params) { - widget_delegate_ = params.delegate ? params.delegate : new WidgetDelegate; + type_ = params.type; + widget_delegate_ = + params.delegate ? params.delegate : new DefaultWidgetDelegate; ownership_ = params.ownership; native_widget_ = params.native_widget ? params.native_widget @@ -114,6 +136,10 @@ void Widget::Init(const InitParams& params) { if (params.type == InitParams::TYPE_MENU) is_mouse_button_pressed_ = native_widget_->IsMouseButtonDown(); native_widget_->InitNativeWidget(params); + if (type_ == InitParams::TYPE_WINDOW) { + non_client_view_ = new NonClientView; + non_client_view_->SetFrameView(CreateNonClientFrameView()); + } } // Unconverted methods (see header) -------------------------------------------- @@ -381,6 +407,38 @@ void Widget::SetFocusTraversableParentView(View* parent_view) { root_view_->SetFocusTraversableParentView(parent_view); } +void Widget::UpdateFrameAfterFrameChange() { + native_widget_->UpdateFrameAfterFrameChange(); +} + +NonClientFrameView* Widget::CreateNonClientFrameView() { + NonClientFrameView* frame_view = widget_delegate_->CreateNonClientFrameView(); + if (!frame_view) + frame_view = native_widget_->CreateNonClientFrameView(); + return frame_view ? frame_view : new CustomFrameView(this); +} + +bool Widget::ShouldUseNativeFrame() const { + if (frame_type_ != FRAME_TYPE_DEFAULT) + return frame_type_ == FRAME_TYPE_FORCE_NATIVE; + return native_widget_->ShouldUseNativeFrame(); +} + +void Widget::DebugToggleFrameType() { + if (frame_type_ == FRAME_TYPE_DEFAULT) { + frame_type_ = ShouldUseNativeFrame() ? FRAME_TYPE_FORCE_CUSTOM : + FRAME_TYPE_FORCE_NATIVE; + } else { + frame_type_ = frame_type_ == FRAME_TYPE_FORCE_CUSTOM ? + FRAME_TYPE_FORCE_NATIVE : FRAME_TYPE_FORCE_CUSTOM; + } + FrameTypeChanged(); +} + +void Widget::FrameTypeChanged() { + native_widget_->FrameTypeChanged(); +} + void Widget::NotifyAccessibilityEvent( View* view, ui::AccessibilityTypes::Event event_type, @@ -417,6 +475,11 @@ void Widget::OnNativeWidgetCreated() { EnsureCompositor(); } +void Widget::OnNativeWidgetDestroyed() { + widget_delegate_->DeleteDelegate(); + widget_delegate_ = NULL; +} + void Widget::OnSizeChanged(const gfx::Size& new_size) { root_view_->SetSize(new_size); } diff --git a/views/widget/widget.h b/views/widget/widget.h index 912cc76..19952eb 100644 --- a/views/widget/widget.h +++ b/views/widget/widget.h @@ -15,6 +15,8 @@ #include "ui/gfx/rect.h" #include "views/focus/focus_manager.h" #include "views/widget/native_widget_delegate.h" +#include "views/window/client_view.h" +#include "views/window/non_client_view.h" #if defined(OS_WIN) // Windows headers define macros for these function names which screw with us. @@ -46,6 +48,7 @@ namespace views { class DefaultThemeProvider; class InputMethod; class NativeWidget; +class NonClientFrameView; class TooltipManager; class View; class WidgetDelegate; @@ -82,6 +85,12 @@ class RootView; class Widget : public internal::NativeWidgetDelegate, public FocusTraversable { public: + enum FrameType { + FRAME_TYPE_DEFAULT, // Use whatever the default would be. + FRAME_TYPE_FORCE_CUSTOM, // Force the custom frame. + FRAME_TYPE_FORCE_NATIVE // Force the native frame. + }; + struct InitParams { enum Type { TYPE_WINDOW, // A Window, like a frame window. @@ -354,6 +363,44 @@ class Widget : public internal::NativeWidgetDelegate, void SetFocusTraversableParent(FocusTraversable* parent); void SetFocusTraversableParentView(View* parent_view); + // Updates the frame after an event caused it to be changed. + virtual void UpdateFrameAfterFrameChange(); + + void set_frame_type(FrameType frame_type) { frame_type_ = frame_type; } + FrameType frame_type() const { return frame_type_; } + + // Creates an appropriate NonClientFrameView for this widget. The + // WidgetDelegate is given the first opportunity to create one, followed by + // the NativeWidget implementation. If both return NULL, a default one is + // created. + virtual NonClientFrameView* CreateNonClientFrameView(); + + // Whether we should be using a native frame. + bool ShouldUseNativeFrame() const; + + // Forces the frame into the alternate frame type (custom or native) depending + // on its current state. + void DebugToggleFrameType(); + + // Tell the window that something caused the frame type to change. + void FrameTypeChanged(); + + NonClientView* non_client_view() { + return const_cast<NonClientView*>( + const_cast<const Widget*>(this)->non_client_view()); + } + const NonClientView* non_client_view() const { + return non_client_view_; + } + + ClientView* client_view() { + return const_cast<ClientView*>( + const_cast<const Widget*>(this)->client_view()); + } + const ClientView* client_view() const { + return non_client_view()->client_view(); + } + const ui::Compositor* compositor() const { return compositor_.get(); } ui::Compositor* compositor() { return compositor_.get(); } @@ -375,6 +422,7 @@ class Widget : public internal::NativeWidgetDelegate, virtual void OnNativeFocus(gfx::NativeView focused_view) OVERRIDE; virtual void OnNativeBlur(gfx::NativeView focused_view) OVERRIDE; virtual void OnNativeWidgetCreated() OVERRIDE; + virtual void OnNativeWidgetDestroyed() OVERRIDE; virtual void OnSizeChanged(const gfx::Size& new_size) OVERRIDE; virtual bool HasFocusManager() const OVERRIDE; virtual bool OnNativeWidgetPaintAccelerated( @@ -430,6 +478,8 @@ class Widget : public internal::NativeWidgetDelegate, NativeWidget* native_widget_; + InitParams::Type type_; + // Non-owned pointer to the Widget's delegate. May be NULL if no delegate is // being used. WidgetDelegate* widget_delegate_; @@ -439,6 +489,12 @@ class Widget : public internal::NativeWidgetDelegate, // this and tooltip_manager_. scoped_ptr<internal::RootView> root_view_; + // The View that provides the non-client area of the window (title bar, + // window controls, sizing borders etc). To use an implementation other than + // the default, this class must be sub-classed and this value set to the + // desired implementation before calling |InitWindow()|. + NonClientView* non_client_view_; + // The focus manager keeping track of focus for this Widget and any of its // children. NULL for non top-level widgets. // WARNING: RootView's destructor calls into the FocusManager. As such, this @@ -461,6 +517,10 @@ class Widget : public internal::NativeWidgetDelegate, // See set_is_secondary_widget(). bool is_secondary_widget_; + // The current frame type in use by this window. Defaults to + // FRAME_TYPE_DEFAULT. + FrameType frame_type_; + DISALLOW_COPY_AND_ASSIGN(Widget); }; diff --git a/views/widget/widget_delegate.cc b/views/widget/widget_delegate.cc index 5e86035..fa91e7b 100644 --- a/views/widget/widget_delegate.cc +++ b/views/widget/widget_delegate.cc @@ -140,5 +140,9 @@ ClientView* WidgetDelegate::CreateClientView(Window* window) { return new ClientView(window, GetContentsView()); } +NonClientFrameView* WidgetDelegate::CreateNonClientFrameView() { + return NULL; +} + } // namespace views diff --git a/views/widget/widget_delegate.h b/views/widget/widget_delegate.h index a6aab4e..dac0253 100644 --- a/views/widget/widget_delegate.h +++ b/views/widget/widget_delegate.h @@ -20,6 +20,7 @@ class Rect; namespace views { class ClientView; class DialogDelegate; +class NonClientFrameView; class View; class Window; @@ -139,6 +140,10 @@ class WidgetDelegate { // of the window. virtual ClientView* CreateClientView(Window* window); + // Called by the Widget to create the NonClient Frame View for this widget. + // Return NULL to use the default one. + virtual NonClientFrameView* CreateNonClientFrameView(); + Window* window() const { return window_; } protected: |