blob: 0fab70037a4447e41e5848b3b762c4492ae89926 [file] [log] [blame]
// Copyright (c) 2012 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_DELEGATE_H_
#define UI_VIEWS_WIDGET_WIDGET_DELEGATE_H_
#include <memory>
#include <string>
#include <vector>
#include "base/macros.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/base/ui_base_types.h"
#include "ui/views/metadata/metadata_header_macros.h"
#include "ui/views/metadata/view_factory.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget.h"
namespace gfx {
class ImageSkia;
class Rect;
} // namespace gfx
namespace views {
class BubbleDialogDelegate;
class ClientView;
class DialogDelegate;
class NonClientFrameView;
class View;
// Handles events on Widgets in context-specific ways.
class VIEWS_EXPORT WidgetDelegate {
public:
using ClientViewFactory =
base::OnceCallback<std::unique_ptr<ClientView>(Widget*)>;
using OverlayViewFactory = base::OnceCallback<std::unique_ptr<View>()>;
// NonClientFrameViewFactory is a RepeatingCallback because the
// NonClientFrameView is rebuilt on Aura platforms when WindowTreeHost
// properties that might affect its appearance change. Rebuilding the entire
// NonClientFrameView is a pretty big hammer for that but it's the one we
// have.
using NonClientFrameViewFactory =
base::RepeatingCallback<std::unique_ptr<NonClientFrameView>(Widget*)>;
struct Params {
Params();
~Params();
// The window's role. Useful values include kWindow (a plain window),
// kDialog (a dialog), and kAlertDialog (a high-priority dialog whose body
// is read when it appears). Using a role outside this set is not likely to
// work across platforms.
ax::mojom::Role accessible_role = ax::mojom::Role::kWindow;
// The accessible title for the window, often more descriptive than the
// plain title. If no accessible title is present the result of
// GetWindowTitle() will be used.
base::string16 accessible_title;
// Whether the window should display controls for the user to minimize,
// maximize, or resize it.
bool can_maximize = false;
bool can_minimize = false;
bool can_resize = false;
#if defined(USE_AURA)
// Whether to center the widget's title within the frame.
bool center_title = false;
#endif
// Controls focus traversal past the first/last focusable view.
// If true, focus moves out of this Widget and to this Widget's toplevel
// Widget; if false, focus cycles within this Widget.
bool focus_traverses_out = false;
// Controls whether the user can traverse a Widget's views using up/down
// and left/right arrow keys in addition to TAB. Applies only to the
// current widget so can be set independently even on widgets that share a
// focus manager.
bool enable_arrow_key_traversal = false;
// The widget's icon, if any.
gfx::ImageSkia icon;
// The widget's initially focused view, if any. This can only be set before
// this WidgetDelegate is used to initialize a Widget.
base::Optional<View*> initially_focused_view;
// The widget's internal name, used to identify it in window-state
// restoration (if this widget participates in that) and in debugging
// contexts. Never displayed to the user, and not translated.
std::string internal_name;
// The widget's modality type. Note that MODAL_TYPE_SYSTEM does not work at
// all on Mac.
ui::ModalType modal_type = ui::MODAL_TYPE_NONE;
// Whether this WidgetDelegate should delete itself when the Widget for
// which it is the delegate is about to be destroyed.
// See https://crbug.com/1119898 for more details.
bool owned_by_widget = false;
// Whether to show a close button in the widget frame.
bool show_close_button = true;
// Whether to show the widget's icon.
// TODO(ellyjones): What if this was implied by !icon.isNull()?
bool show_icon = false;
// Whether to display the widget's title in the frame.
bool show_title = true;
// The widget's title, if any.
// TODO(ellyjones): Should it be illegal to have show_title && !title?
base::string16 title;
};
WidgetDelegate();
WidgetDelegate(const WidgetDelegate&) = delete;
WidgetDelegate& operator=(const WidgetDelegate&) = delete;
virtual ~WidgetDelegate();
// Sets the return value of CanActivate(). Default is true.
void SetCanActivate(bool can_activate);
// Called whenever the widget's position changes.
virtual void OnWidgetMove();
// Called with the display changes (color depth or resolution).
virtual void OnDisplayChanged();
// Called when the work area (the desktop area minus task bars,
// menu bars, etc.) changes in size.
virtual void OnWorkAreaChanged();
// Called when the widget's initialization is beginning, right after the
// ViewsDelegate decides to use this WidgetDelegate for a Widget.
virtual void OnWidgetInitializing() {}
// Called when the widget's initialization is complete.
virtual void OnWidgetInitialized() {}
// Called when the window has been requested to close, after all other checks
// have run. Returns whether the window should be allowed to close (default is
// true).
//
// Can be used as an alternative to specifying a custom ClientView with
// the CanClose() method, or in widget types which do not support a
// ClientView.
virtual bool OnCloseRequested(Widget::ClosedReason close_reason);
// Returns the view that should have the focus when the widget is shown. If
// nullptr no view is focused.
virtual View* GetInitiallyFocusedView();
bool HasConfiguredInitiallyFocusedView() const;
virtual BubbleDialogDelegate* AsBubbleDialogDelegate();
virtual DialogDelegate* AsDialogDelegate();
// Returns true if the window can be resized.
virtual bool CanResize() const;
// Returns true if the window can be maximized.
virtual bool CanMaximize() const;
// Returns true if the window can be minimized.
virtual bool CanMinimize() const;
// Returns true if the window can be activated.
virtual bool CanActivate() const;
// Returns the modal type that applies to the widget. Default is
// ui::MODAL_TYPE_NONE (not modal).
virtual ui::ModalType GetModalType() const;
virtual ax::mojom::Role GetAccessibleWindowRole();
// Returns the title to be read with screen readers.
virtual base::string16 GetAccessibleWindowTitle() const;
// Returns the text to be displayed in the window title.
virtual base::string16 GetWindowTitle() const;
// Returns true if the window should show a title in the title bar.
virtual bool ShouldShowWindowTitle() const;
// Returns true if the window should show a close button in the title bar.
virtual bool ShouldShowCloseButton() const;
// Returns the app icon for the window. On Windows, this is the ICON_BIG used
// in Alt-Tab list and Win7's taskbar.
virtual gfx::ImageSkia GetWindowAppIcon();
// Returns the icon to be displayed in the window.
virtual gfx::ImageSkia GetWindowIcon();
// Returns true if a window icon should be shown.
bool ShouldShowWindowIcon() const;
// Execute a command in the window's controller. Returns true if the command
// was handled, false if it was not.
virtual bool ExecuteWindowsCommand(int command_id);
// Returns the window's name identifier. Used to identify this window for
// state restoration.
virtual std::string GetWindowName() const;
// Saves the window's bounds and "show" state. By default this uses the
// process' local state keyed by window name (See GetWindowName above). This
// behavior can be overridden to provide additional functionality.
virtual void SaveWindowPlacement(const gfx::Rect& bounds,
ui::WindowShowState show_state);
// Retrieves the window's bounds and "show" states.
// This behavior can be overridden to provide additional functionality.
virtual bool GetSavedWindowPlacement(const Widget* widget,
gfx::Rect* bounds,
ui::WindowShowState* show_state) const;
// Hooks for the end of the Widget/Window lifecycle. As of this writing, these
// callbacks happen like so:
// 1. Client code calls Widget::CloseWithReason()
// 2. WidgetDelegate::WindowWillClose() is called
// 3. NativeWidget teardown (maybe async) starts OR the operating system
// abruptly closes the backing native window
// 4. WidgetDelegate::WindowClosing() is called
// 5. NativeWidget teardown completes, Widget teardown starts
// 6. WidgetDelegate::DeleteDelegate() is called
// 7. Widget teardown finishes, Widget is deleted
// At step 3, the "maybe async" is controlled by whether the close is done via
// Close() or CloseNow().
// Important note: for OS-initiated window closes, steps 1 and 2 don't happen
// - i.e, WindowWillClose() is never invoked.
//
// The default implementations of both of these call the callbacks described
// below. It is better to use those callback mechanisms than to override one
// of these methods.
virtual void WindowClosing();
// It should not be necessary to override this method in new code; instead,
// consider using either SetOwnedByWidget() if you need that ownership
// behavior, or RegisterDeleteDelegateCallback() if you need to attach
// behavior before deletion but want the default deletion behavior.
virtual void DeleteDelegate();
// Called when the user begins/ends to change the bounds of the window.
virtual void OnWindowBeginUserBoundsChange() {}
virtual void OnWindowEndUserBoundsChange() {}
// Returns the Widget associated with this delegate.
virtual Widget* GetWidget();
virtual const Widget* GetWidget() const;
// Get the view that is contained within this widget.
//
// WARNING: This method has unusual ownership behavior:
// * If the returned view is owned_by_client(), then the returned pointer is
// never an owning pointer;
// * If the returned view is !owned_by_client() (the default & the
// recommendation), then the returned pointer is *sometimes* an owning
// pointer and sometimes not. Specifically, it is an owning pointer exactly
// once, when this method is being used to construct the ClientView, which
// takes ownership of the ContentsView() when !owned_by_client().
//
// Apart from being difficult to reason about this introduces a problem: a
// WidgetDelegate can't know whether it owns its contents view or not, so
// constructing a WidgetDelegate which one does not then use to construct a
// Widget (often done in tests) leaks memory in a way that can't be locally
// fixed.
//
// TODO(ellyjones): This is not tenable - figure out how this should work and
// replace it.
virtual View* GetContentsView();
// Returns ownership of the contents view, which means something similar to
// but not the same as C++ ownership in the unique_ptr sense. The caller
// takes on responsibility for either destroying the returned View (if it
// is !owned_by_client()) or not (if it is owned_by_client()). Since this
// returns a raw pointer, this method serves only as a declaration of intent
// by the caller.
//
// It is only legal to call this method one time on a given WidgetDelegate
// instance.
//
// In future, this method will begin returning a unique_ptr<View> instead,
// and will eventually be renamed to TakeContentsView() once WidgetDelegate
// no longer retains any reference to the contents view internally.
View* TransferOwnershipOfContentsView();
// Called by the Widget to create the Client View used to host the contents
// of the widget.
virtual ClientView* CreateClientView(Widget* widget);
// Called by the Widget to create the NonClient Frame View for this widget.
// Return NULL to use the default one.
virtual std::unique_ptr<NonClientFrameView> CreateNonClientFrameView(
Widget* widget);
// Called by the Widget to create the overlay View for this widget. Return
// NULL for no overlay. The overlay View will fill the Widget and sit on top
// of the ClientView and NonClientFrameView (both visually and wrt click
// targeting).
virtual View* CreateOverlayView();
// Returns true if window has a hit-test mask.
virtual bool WidgetHasHitTestMask() const;
// Provides the hit-test mask if HasHitTestMask above returns true.
virtual void GetWidgetHitTestMask(SkPath* mask) const;
// Returns true if event handling should descend into |child|.
// |location| is in terms of the Window.
virtual bool ShouldDescendIntoChildForEventHandling(
gfx::NativeView child,
const gfx::Point& location);
// Populates |panes| with accessible panes in this window that can
// be cycled through with keyboard focus.
virtual void GetAccessiblePanes(std::vector<View*>* panes) {}
// Setters for data parameters of the WidgetDelegate. If you use these
// setters, there is no need to override the corresponding virtual getters.
void SetAccessibleRole(ax::mojom::Role role);
void SetAccessibleTitle(base::string16 title);
void SetCanMaximize(bool can_maximize);
void SetCanMinimize(bool can_minimize);
void SetCanResize(bool can_resize);
void SetFocusTraversesOut(bool focus_traverses_out);
void SetEnableArrowKeyTraversal(bool enable_arrow_key_traversal);
void SetIcon(const gfx::ImageSkia& icon);
void SetInitiallyFocusedView(View* initially_focused_view);
void SetModalType(ui::ModalType modal_type);
void SetOwnedByWidget(bool delete_self);
void SetShowCloseButton(bool show_close_button);
void SetShowIcon(bool show_icon);
void SetShowTitle(bool show_title);
void SetTitle(const base::string16& title);
void SetTitle(int title_message_id);
#if defined(USE_AURA)
void SetCenterTitle(bool center_title);
#endif
template <typename T>
T* SetContentsView(std::unique_ptr<T> contents) {
DCHECK(!contents->owned_by_client());
T* raw_contents = contents.get();
SetContentsViewImpl(contents.release());
return raw_contents;
}
template <typename T>
T* SetContentsView(T* contents) {
DCHECK(contents->owned_by_client());
SetContentsViewImpl(contents);
return contents;
}
// A convenience wrapper that does all three of SetCanMaximize,
// SetCanMinimize, and SetCanResize.
void SetHasWindowSizeControls(bool has_controls);
void RegisterWidgetInitializingCallback(base::OnceClosure callback);
void RegisterWidgetInitializedCallback(base::OnceClosure callback);
void RegisterWindowWillCloseCallback(base::OnceClosure callback);
void RegisterWindowClosingCallback(base::OnceClosure callback);
void RegisterDeleteDelegateCallback(base::OnceClosure callback);
void SetClientViewFactory(ClientViewFactory factory);
void SetNonClientFrameViewFactory(NonClientFrameViewFactory factory);
void SetOverlayViewFactory(OverlayViewFactory factory);
// Called to notify the WidgetDelegate of changes to the state of its Widget.
// It is not usually necessary to call these from client code.
void WidgetInitializing(Widget* widget);
void WidgetInitialized();
void WidgetDestroying();
void WindowWillClose();
// Returns true if the title text should be centered.
bool ShouldCenterWindowTitleText() const;
bool focus_traverses_out() const { return params_.focus_traverses_out; }
bool enable_arrow_key_traversal() const {
return params_.enable_arrow_key_traversal;
}
bool owned_by_widget() const { return params_.owned_by_widget; }
void set_internal_name(std::string name) { params_.internal_name = name; }
std::string internal_name() const { return params_.internal_name; }
private:
// We're using a vector of OnceClosures instead of a OnceCallbackList because
// most of the clients of WidgetDelegate don't have a convenient place to
// store the CallbackLists' subscription objects.
using ClosureVector = std::vector<base::OnceClosure>;
friend class Widget;
void SetContentsViewImpl(View* contents);
// The Widget that was initialized with this instance as its WidgetDelegate,
// if any.
Widget* widget_ = nullptr;
Params params_;
View* default_contents_view_ = nullptr;
bool contents_view_taken_ = false;
bool can_activate_ = true;
View* unowned_contents_view_ = nullptr;
std::unique_ptr<View> owned_contents_view_;
// Managed by Widget. Ensures |this| outlives its Widget.
bool can_delete_this_ = true;
// The first two are stored as unique_ptrs to make it easier to check in the
// registration methods whether a callback is being registered too late in the
// WidgetDelegate's lifecycle.
std::unique_ptr<ClosureVector> widget_initializing_callbacks_;
std::unique_ptr<ClosureVector> widget_initialized_callbacks_;
ClosureVector window_will_close_callbacks_;
ClosureVector window_closing_callbacks_;
ClosureVector delete_delegate_callbacks_;
ClientViewFactory client_view_factory_;
NonClientFrameViewFactory non_client_frame_view_factory_;
OverlayViewFactory overlay_view_factory_;
};
// A WidgetDelegate implementation that is-a View. Used to override GetWidget()
// to call View's GetWidget() for the common case where a WidgetDelegate
// implementation is-a View. Note that WidgetDelegateView is not owned by
// view's hierarchy and is expected to be deleted on DeleteDelegate call.
class VIEWS_EXPORT WidgetDelegateView : public WidgetDelegate, public View {
public:
METADATA_HEADER(WidgetDelegateView);
WidgetDelegateView();
WidgetDelegateView(const WidgetDelegateView&) = delete;
WidgetDelegateView& operator=(const WidgetDelegateView&) = delete;
~WidgetDelegateView() override;
// WidgetDelegate:
Widget* GetWidget() override;
const Widget* GetWidget() const override;
View* GetContentsView() override;
};
BEGIN_VIEW_BUILDER(VIEWS_EXPORT, WidgetDelegateView, View)
END_VIEW_BUILDER
} // namespace views
DEFINE_VIEW_BUILDER(VIEWS_EXPORT, WidgetDelegateView)
#endif // UI_VIEWS_WIDGET_WIDGET_DELEGATE_H_