blob: 1b23449ceb8e2c257cd40c375154a5fa93d1a26e [file] [log] [blame]
// Copyright 2012 The Chromium Authors
// 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 <utility>
#include <vector>
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/types/pass_key.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/base/models/image_model.h"
#include "ui/base/mojom/ui_base_types.mojom-shared.h"
#include "ui/base/mojom/window_show_state.mojom-forward.h"
#include "ui/views/metadata/view_factory.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget.h"
class AutoPipSettingView;
class DesktopMediaPickerDialogView;
class DigitalIdentityMultiStepDialogDelegate;
class ExtensionsMenuCoordinator;
class ExternalProtocolNoHandlersTelSchemeDialog;
class ForceInstalledDeprecatedAppsDialogView;
class ForceInstalledPreinstalledDeprecatedAppDialogView;
class HoverDetectionBubbleView;
class ImmersiveModeControllerMacInteractiveTest;
class JavaScriptTabModalDialogViewViews;
class LoginHandlerViewsDialog;
class MediaGalleriesDialogTest;
class MediaGalleriesDialogViews;
class MessageBoxDialog;
class OverlayWindowWidgetDelegate;
class ParentAccessView;
class PresentationReceiverWindowView;
class PrivacySandboxDialog;
class ProcessSharingInfobarDelegate;
class ProfilePickerView;
class SSLClientCertificateSelector;
class ScheduledRebootDialog;
class ScreenCaptureNotificationUIViews;
class SearchEngineChoiceDialog;
class ShareThisTabDialogView;
class SigninViewControllerDelegateViews;
class TabModalConfirmDialogViews;
class TestBaseWidgetDelegate;
class UpdateRecommendedMessageBox;
class WebDialogBrowserTest;
FORWARD_DECLARE_TEST(AcceleratorCommandsFullscreenBrowserTest,
ToggleFullscreen);
FORWARD_DECLARE_TEST(TabStripScrollContainerTest, AnchoredWidgetHidesOnScroll);
#if !BUILDFLAG(IS_CHROMEOS)
class DownloadBubbleContentsViewTest;
class DownloadBubbleSecurityViewTest;
class DownloadToolbarUIController;
#endif
namespace arc {
class ArcTaskWindowBuilder;
class ArcVmDataMigrationConfirmationDialog;
} // namespace arc
namespace ash {
class AccessibilityPanel;
class ActiveSessionAuthControllerImpl;
class AmbientWidgetDelegate;
class AppListView;
class AppsCollectionsDismissDialog;
class AssistantWebContainerView;
class AuthDialogContentsViewPixelTest;
class AuthDialogContentsViewTest;
class BootingAnimationController;
class CaptureModeSessionFocusCycler;
class ClientControlledStateTestWidgetDelegate;
class ConnectionErrorDialogDelegateView;
class DeferredUpdateDialog;
class DeskButtonWidgetDelegateView;
class DisclaimerView;
class DockedMagnifierTest;
class DropSenderView;
class DropTargetView;
class ExitWarningWidgetDelegateView;
class FrameCaptionButtonContainerViewTest;
class FrameSizeButtonTestWidgetDelegate;
class GuestSessionConfirmationDialog;
class HotseatWidgetDelegateView;
class IdleAppNameNotificationDelegateView;
class InSessionAuthDialog;
class InSessionAuthDialogControllerImpl;
class InformedRestoreController;
class KioskExternalUpdateNotificationView;
class LayoutWidgetDelegateView;
class LocalAuthenticationWithPinControllerImpl;
class LockDebugView;
class LockDebugViewDataDispatcherTransformer;
class LockScreen;
class LoginShelfWidgetDelegate;
class LoginTestBase;
class LoginTestWidgetDelegate;
class MahiPanelWidget;
class MaximizeDelegateView;
class NonClientFrameViewAshTestWidgetDelegate;
class PipTest;
class QuickInsertSubmenuView;
class QuickInsertView;
class ResizableWidgetDelegate;
class RootWindowControllerTest;
class ShelfNavigationWidgetDelegate;
class ShelfWidgetDelegateView;
class ShellTest;
class SimpleWebViewDialog;
class StatusAreaWidgetDelegate;
class StuckWidgetDelegate;
class SystemDialogDelegateView;
class SystemUIComponentsStyleViewerView;
class TestChildModalParent;
class TestTextInputView;
class TestWidgetBuilderDelegate;
class TestWidgetDelegateAsh;
class TestWindow;
class VirtualTrackpadView;
class WallpaperWidgetDelegate;
class WideFrameView;
class WidgetWithSystemUIComponentView;
class WindowCycleView;
FORWARD_DECLARE_TEST(ExtendedDesktopTest, SystemModal);
FORWARD_DECLARE_TEST(MruWindowTrackerOrderTest, Basic);
FORWARD_DECLARE_TEST(ShellTest, CreateWindowWithPreferredSize);
namespace hud_display {
class HUDDisplayView;
}
namespace sharesheet {
class TestWidgetDelegate;
}
namespace shell {
class ToplevelWindow;
}
} // namespace ash
namespace autofill {
class PopupBaseView;
namespace payments {
class PaymentsWindowUserConsentDialogView;
}
} // namespace autofill
namespace constrained_window {
class BrowserModalHelper;
}
namespace content {
class ShellPlatformDelegate;
}
namespace crostini {
class AppRestartDialog;
}
namespace exo {
class ShellSurfaceBase;
}
namespace extensions {
class WebFileHandlersPermissionHandler;
}
namespace eye_dropper {
class EyeDropperView;
}
namespace gfx {
class Rect;
}
namespace glic {
class GlicWidgetDelegate;
}
namespace javascript_dialogs {
class AppModalDialogViewViews;
}
namespace message_center {
class MessagePopupView;
}
namespace native_app_window {
class NativeAppWindowViews;
}
namespace plus_addresses {
class PlusAddressCreationDialogDelegate;
}
namespace remoting {
class MessageBoxCore;
}
namespace ui::ime {
class CandidateViewTest;
}
namespace views {
class BubbleDialogDelegate;
class BubbleDialogModelHost;
class ClientView;
class DefaultWidgetDelegate;
class DialogDelegate;
class FocusTraversalTest;
class MoveTestWidgetDelegate;
class NonClientFrameView;
class ShapedWidgetDelegate;
class TableViewFocusTest;
class View;
class WebDialogView;
FORWARD_DECLARE_TEST(BubbleUmaLoggerTest, LogMetricFromDelegate);
FORWARD_DECLARE_TEST(FocusManagerTest, AdvanceFocusStaysInWidget);
FORWARD_DECLARE_TEST(NativeWidgetAuraTest, TestPropertiesWhenAddedToLayout);
FORWARD_DECLARE_TEST(NativeWidgetAuraTest, TransientChildModalWindowVisibility);
FORWARD_DECLARE_TEST(NativeViewHostAuraTest,
FocusManagerUpdatedDuringDestruction);
namespace borealis {
class BorealisDisallowedDialog;
class BorealisLaunchErrorDialog;
} // namespace borealis
namespace examples {
class ExamplesWindowContents;
}
namespace test {
FORWARD_DECLARE_TEST(DesktopWidgetTest, LockPaintAsActiveAndCloseParent);
}
} // namespace views
namespace web_app {
class IsolatedWebAppInstallerViewController;
class SubAppsInstallDialogController;
} // namespace web_app
namespace webid {
class AccountSelectionModalView;
} // namespace webid
namespace views {
namespace test {
class GetNativeThemeFromDestructorView;
class TestingWidgetDelegateView;
FORWARD_DECLARE_TEST(WidgetOwnsNativeWidgetTest, WidgetDelegateView);
} // namespace test
using TitleChangedCallback = base::RepeatingCallback<void()>;
using AccessibleTitleChangedCallback = base::RepeatingCallback<void()>;
// 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.
// TODO(b:387350163): Investigate if NonClientFrameView can handle these
// changes in a more granular way.
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.
std::u16string accessible_title;
// Whether the window should display controls for the user to minimize,
// maximize, resize it, or go into fullscreen.
bool can_fullscreen = false;
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.
ui::ImageModel icon;
// The widget's app icon, a larger icon used for task bar and Alt-Tab.
ui::ImageModel app_icon;
// The widget's initially focused view, if any. This can only be set before
// this WidgetDelegate is used to initialize a Widget.
std::optional<View*> initially_focused_view;
// This is used by modal dialogs to override and constrain desired bounds
// calculations.
// TODO(pbos): Consider if we could express bounds constraints in views and
// keep them in sync rather than constrained_window owning the calculation
// here. Considering this wasn't very expedient at the time.
base::RepeatingCallback<gfx::Rect()> desired_bounds_delegate;
// 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::mojom::ModalType modal_type = ui::mojom::ModalType::kNone;
// 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?
std::u16string title;
// If set to true, force using desktop widget (DesktopNativeWidgetAura).
// Otherwise, widget type is determined automatically.
// This is used for child widgets on Desktop Aura (i.e. Windows and Linux)
// when they need to be rendered beyond their parent window's boundary.
// This setting has no effect on other platforms (e.g. ChromeOS or macOS).
bool use_desktop_widget_override = false;
};
class OwnedByWidgetPassKey {
private:
// DO NOT ADD TO THIS LIST!
// These existing cases are "grandfathered in", but there shouldn't be more.
// See comments atop `SetOwnedByWidget()`.
friend class ::AutoPipSettingView;
friend class ::DigitalIdentityMultiStepDialogDelegate;
#if !BUILDFLAG(IS_CHROMEOS)
friend class ::DownloadBubbleContentsViewTest;
friend class ::DownloadBubbleSecurityViewTest;
friend class ::DownloadToolbarUIController;
#endif
friend class ::ExtensionsMenuCoordinator;
friend class ::ExternalProtocolNoHandlersTelSchemeDialog;
friend class ::ForceInstalledDeprecatedAppsDialogView;
friend class ::ForceInstalledPreinstalledDeprecatedAppDialogView;
friend class ::HoverDetectionBubbleView;
friend class ::LoginHandlerViewsDialog;
friend class ::MediaGalleriesDialogTest;
friend class ::MessageBoxDialog;
friend class ::OverlayWindowWidgetDelegate;
friend class ::ParentAccessView;
friend class ::PrivacySandboxDialog;
friend class ::ProcessSharingInfobarDelegate;
friend class ::ProfilePickerView;
friend class ::ScheduledRebootDialog;
friend class ::SearchEngineChoiceDialog;
friend class ::TabModalConfirmDialogViews;
friend class ::TestBaseWidgetDelegate;
friend class ::UpdateRecommendedMessageBox;
friend class ::WebDialogBrowserTest;
FRIEND_TEST_ALL_PREFIXES(::TabStripScrollContainerTest,
AnchoredWidgetHidesOnScroll);
friend class ::arc::ArcTaskWindowBuilder;
friend class ::arc::ArcVmDataMigrationConfirmationDialog;
friend class ::ash::AccessibilityPanel;
friend class ::ash::ActiveSessionAuthControllerImpl;
friend class ::ash::AmbientWidgetDelegate;
friend class ::ash::AuthDialogContentsViewPixelTest;
friend class ::ash::AuthDialogContentsViewTest;
friend class ::ash::BootingAnimationController;
friend class ::ash::CaptureModeSessionFocusCycler;
friend class ::ash::DeferredUpdateDialog;
friend class ::ash::DisclaimerView;
friend class ::ash::GuestSessionConfirmationDialog;
friend class ::ash::InSessionAuthDialog;
friend class ::ash::InSessionAuthDialogControllerImpl;
friend class ::ash::LocalAuthenticationWithPinControllerImpl;
friend class ::ash::LockDebugView;
friend class ::ash::LockDebugViewDataDispatcherTransformer;
friend class ::ash::LockScreen;
friend class ::ash::LoginShelfWidgetDelegate;
friend class ::ash::LoginTestBase;
friend class ::ash::LoginTestWidgetDelegate;
friend class ::ash::MahiPanelWidget;
friend class ::ash::ShelfNavigationWidgetDelegate;
friend class ::ash::ShelfWidgetDelegateView;
friend class ::ash::ShellTest;
friend class ::ash::SimpleWebViewDialog;
friend class ::ash::StatusAreaWidgetDelegate;
friend class ::ash::StuckWidgetDelegate;
friend class ::ash::SystemUIComponentsStyleViewerView;
friend class ::ash::VirtualTrackpadView;
friend class ::ash::hud_display::HUDDisplayView;
friend class ::constrained_window::BrowserModalHelper;
friend class ::content::ShellPlatformDelegate;
friend class ::crostini::AppRestartDialog;
friend class ::exo::ShellSurfaceBase;
friend class ::extensions::WebFileHandlersPermissionHandler;
friend class ::javascript_dialogs::AppModalDialogViewViews;
friend class ::remoting::MessageBoxCore;
friend class BubbleDialogModelHost;
friend class FocusTraversalTest;
FRIEND_TEST_ALL_PREFIXES(BubbleUmaLoggerTest, LogMetricFromDelegate);
friend class borealis::BorealisDisallowedDialog;
friend class borealis::BorealisLaunchErrorDialog;
friend class ::web_app::IsolatedWebAppInstallerViewController;
friend class ::web_app::SubAppsInstallDialogController;
friend class ::webid::AccountSelectionModalView;
OwnedByWidgetPassKey() = default;
};
class RegisterWillCloseCallbackPassKey {
private:
// DO NOT ADD TO THIS LIST!
// These existing cases are "grandfathered in", but there shouldn't be more.
// See comments atop `RegisterWindowWillCloseCallback()`.
friend class ::JavaScriptTabModalDialogViewViews;
friend class ::autofill::payments::PaymentsWindowUserConsentDialogView;
friend class DialogDelegate;
friend class WebDialogView;
RegisterWillCloseCallbackPassKey() = default;
};
class RegisterDeleteCallbackPassKey {
private:
// DO NOT ADD TO THIS LIST!
// These existing cases are "grandfathered in", but there shouldn't be more.
// See comments atop `RegisterDeleteDelegateCallback()`.
friend class ::DesktopMediaPickerDialogView;
friend class ::MediaGalleriesDialogViews;
friend class ::PresentationReceiverWindowView;
friend class ::SSLClientCertificateSelector;
friend class ::ScreenCaptureNotificationUIViews;
friend class ::ShareThisTabDialogView;
friend class ::SigninViewControllerDelegateViews;
friend class ::ash::InformedRestoreController;
friend class ::glic::GlicWidgetDelegate;
friend class ::native_app_window::NativeAppWindowViews;
friend class ::plus_addresses::PlusAddressCreationDialogDelegate;
friend class ::remoting::MessageBoxCore;
friend class DefaultWidgetDelegate;
friend class TableViewFocusTest;
FRIEND_TEST_ALL_PREFIXES(FocusManagerTest, AdvanceFocusStaysInWidget);
FRIEND_TEST_ALL_PREFIXES(NativeWidgetAuraTest,
TestPropertiesWhenAddedToLayout);
FRIEND_TEST_ALL_PREFIXES(NativeWidgetAuraTest,
TransientChildModalWindowVisibility);
FRIEND_TEST_ALL_PREFIXES(test::DesktopWidgetTest,
LockPaintAsActiveAndCloseParent);
RegisterDeleteCallbackPassKey() = default;
};
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 when 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 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.
//
// DEPRECATED. Don't use this. See Widget::MakeCloseSynchronous().
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.
// This has side-effect on Windows. A resizable Windows cannot be translucent,
// i.e. Widget::InitParam::WindowOpacity must be kInferred or kOpaque,
// otherwise it draws nothing.
virtual bool CanResize() const;
// Returns true if the window can go into fullscreen.
virtual bool CanFullscreen() 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::mojom::ModalType::kNone (not modal).
virtual ui::mojom::ModalType GetModalType() const;
virtual ax::mojom::Role GetAccessibleWindowRole();
// Returns the title to be read with screen readers.
virtual std::u16string GetAccessibleWindowTitle() const;
// Returns the text to be displayed in the window title.
virtual std::u16string 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 ui::ImageModel GetWindowAppIcon();
// Returns the icon to be displayed in the window.
virtual ui::ImageModel GetWindowIcon();
// Returns true if a window icon should be shown.
virtual 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;
// Returns true if the widget should save its placement and state.
virtual bool ShouldSaveWindowPlacement() 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::mojom::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::mojom::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();
// TODO (kylixrd): Rename this API once Widget ceases to "own" WidgetDelegate.
// Update the comment below to match the new state of things.
// Called when removed from a Widget. This first runs callbacks registered
// through RegisterDeleteDelegateCallback() and then either deletes `this` or
// not depending on SetOwnedByWidget(). If `this` is owned by Widget then the
// delegate is destructed at the end.
void DeleteDelegate();
// When the ownership of the Widget is CLIENT_OWNS_WIDGET and the client also
// owns the delegate, this function will be called when the Widget has
// transitioned to a "zombie" state. It is safe to delete the Widget from
// within this function.
//
// The "zombie" state is when the Widget is "alive" but the underlying
// NativeWidget has been destroyed. Thus the Widget instance is still valid,
// but it is functionally "dead", aka. "undead". The Widget (and underlying
// NativeWidget) have can handle being in this state. Most Widget APIs will
// not crash while in this state, but they may also do nothing meaningful.
// Call Widget::IsClosed() to determine whether the Widget is in a usable
// state. Widgets in the "zombie" state cannot be resurrected and must be
// deleted or a new instance created.
virtual void WidgetIsZombie(Widget* widget) {}
// 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) {}
// Called when the widget wants to resize itself.
// Default origin is the widget origin.
// Default size is the ContentsView's PreferredSize.
gfx::Rect GetDesiredWidgetBounds();
// Setters for data parameters of the WidgetDelegate. If you use these
// setters, there is no need to override the corresponding virtual getters.
void SetAccessibleWindowRole(ax::mojom::Role role);
void SetAccessibleTitle(std::u16string title);
void SetCanFullscreen(bool can_fullscreen);
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(ui::ImageModel icon);
void SetAppIcon(ui::ImageModel icon);
void SetInitiallyFocusedView(View* initially_focused_view);
void SetModalType(ui::mojom::ModalType modal_type);
void SetShowCloseButton(bool show_close_button);
void SetShowIcon(bool show_icon);
void SetShowTitle(bool show_title);
void SetTitle(const std::u16string& title);
void SetTitle(int title_message_id);
#if defined(USE_AURA)
void SetCenterTitle(bool center_title);
#endif
// DEPRECATED: Instead of having the Widget own the Delegate, the client
// should directly own both (note: this implies the Widget is using the
// CLIENT_OWNS_WIDGET ownership model and the Delegate is not also a View),
// and should delete the delegate after deleting the Widget.
void SetOwnedByWidget(OwnedByWidgetPassKey);
template <typename T>
T* SetContentsView(std::unique_ptr<T> contents) {
T* raw_contents = contents.get();
SetContentsViewImpl(std::move(contents));
return raw_contents;
}
// A convenience wrapper that does all three of SetCanMaximize,
// SetCanMinimize, and SetCanResize.
void SetHasWindowSizeControls(bool has_controls);
void RegisterWidgetInitializedCallback(base::OnceClosure callback);
void RegisterWindowClosingCallback(base::OnceClosure callback);
// DEPRECATED: Instead of using this to perform actions just before close, use
// the CLIENT_OWNS_WIDGET ownership model for the Widget, then call
// `Widget::MakeCloseSynchronous()` with a client callback that will do the
// desired "on close" actions and delete the Widget.
void RegisterWindowWillCloseCallback(RegisterWillCloseCallbackPassKey,
base::OnceClosure callback);
// DEPRECATED: This is unnecessary if the client directly owns the Delegate
// (see comments on `SetOwnedByWidget()` above), since then it can do any
// necessary cleanup directly before deleting the Delegate. Many callers also
// use this for similar purposes to `RegisterWindowWillCloseCallback()`, e.g.
// notifying someone of a dialog result; in this sort of case,
// `Widget::MakeCloseSynchronous()` is similarly useful.
void RegisterDeleteDelegateCallback(RegisterDeleteCallbackPassKey,
base::OnceClosure callback);
void SetClientViewFactory(ClientViewFactory factory);
void SetNonClientFrameViewFactory(NonClientFrameViewFactory factory);
void SetOverlayViewFactory(OverlayViewFactory factory);
// 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;
}
// Rotates focus for panes contained in the current widget from the provided
// view. If wrapping is enabled, rotation will continue after reaching the
// end. This method will return true if a rotation was performed and false
// otherwise.
// If the provided |focused_view| is not included by the widget's panes,
// the method will not perform any rotation unless |enable_wrapping| is
// set to true.
virtual bool RotatePaneFocusFromView(views::View* focused_view,
bool forward,
bool enable_wrapping);
void SetTitleChangedCallback(TitleChangedCallback callback);
void SetAccessibleTitleChangedCallback(
AccessibleTitleChangedCallback callback);
bool owned_by_widget() const { return owned_by_widget_; }
void set_internal_name(std::string name) { params_.internal_name = name; }
std::string internal_name() const { return params_.internal_name; }
void set_use_desktop_widget_override(bool use_desktop_widget_override) {
params_.use_desktop_widget_override = use_desktop_widget_override;
}
bool use_desktop_widget_override() {
return params_.use_desktop_widget_override;
}
bool has_desired_bounds_delegate() const {
return static_cast<bool>(params_.desired_bounds_delegate);
}
void set_desired_bounds_delegate(
base::RepeatingCallback<gfx::Rect()> desired_bounds_delegate) {
params_.desired_bounds_delegate = std::move(desired_bounds_delegate);
}
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;
// Assign the widget associated with this delegate and return a `WeakPtr`
// to this object. Since the delegate is not necessarily owned by
// `Widget` it can be destroyed and the `Widget` needs to have a `WeakPtr`
// to this object. This `WeakPtr` is valid until `DeleteDelegate` is called
// which must be called in order to destroy this delegate.
base::WeakPtr<WidgetDelegate> AttachWidgetAndGetHandle(Widget* widget);
// 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 WidgetInitialized();
void WidgetDestroying();
void WindowWillClose();
void SetContentsViewImpl(std::unique_ptr<View> contents);
// The Widget that was initialized with this instance as its WidgetDelegate,
// if any.
raw_ptr<Widget, AcrossTasksDanglingUntriaged> widget_ = nullptr;
Params params_;
raw_ptr<View, AcrossTasksDanglingUntriaged> default_contents_view_ = nullptr;
bool contents_view_taken_ = false;
bool can_activate_ = true;
raw_ptr<View, AcrossTasksDanglingUntriaged> unowned_contents_view_ = nullptr;
std::unique_ptr<View> owned_contents_view_;
// 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;
// Managed by Widget. Ensures |this| outlives its Widget.
bool can_delete_this_ = true;
// This is stored as a unique_ptr 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_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_;
TitleChangedCallback title_changed_callback_;
AccessibleTitleChangedCallback accessible_title_changed_callback_;
base::WeakPtrFactory<WidgetDelegate> weak_ptr_factory_{this};
};
// 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.
//
// DEPRECATED: Using this class makes it more challenging to reason about object
// ownership/lifetimes and promotes writing "fat" views that also contain
// business logic. Instead, use DialogModel if possible; otherwise, use separate
// subclasses of WidgetDelegate and View to handle those interfaces' respective
// concerns.
class VIEWS_EXPORT WidgetDelegateView : public WidgetDelegate, public View {
METADATA_HEADER(WidgetDelegateView, View)
public:
// Not named `PassKey` as `View::PassKey` already exists in this hierarchy.
using WdvPassKey = base::PassKey<WidgetDelegateView>;
// For use with std::make_unique<>(). Callers still must be in the friend list
// below, just as with the private constructor.
explicit WidgetDelegateView(WdvPassKey) {}
WidgetDelegateView(const WidgetDelegateView&) = delete;
WidgetDelegateView& operator=(const WidgetDelegateView&) = delete;
~WidgetDelegateView() override;
// WidgetDelegate:
Widget* GetWidget() override;
const Widget* GetWidget() const override;
View* GetContentsView() override;
private:
// DO NOT ADD TO THIS LIST!
// These existing cases are "grandfathered in", but there shouldn't be more.
// See comments atop class.
friend class ::ImmersiveModeControllerMacInteractiveTest;
friend class ::PresentationReceiverWindowView;
friend class ::ProfilePickerView;
friend class ::ScreenCaptureNotificationUIViews;
FRIEND_TEST_ALL_PREFIXES(::AcceleratorCommandsFullscreenBrowserTest,
ToggleFullscreen);
friend class ::ash::AppListView;
friend class ::ash::AppsCollectionsDismissDialog;
friend class ::ash::AssistantWebContainerView;
friend class ::ash::ClientControlledStateTestWidgetDelegate;
friend class ::ash::ConnectionErrorDialogDelegateView;
friend class ::ash::DeskButtonWidgetDelegateView;
friend class ::ash::DockedMagnifierTest;
friend class ::ash::DropSenderView;
friend class ::ash::DropTargetView;
friend class ::ash::ExitWarningWidgetDelegateView;
friend class ::ash::FrameCaptionButtonContainerViewTest;
friend class ::ash::FrameSizeButtonTestWidgetDelegate;
friend class ::ash::HotseatWidgetDelegateView;
friend class ::ash::IdleAppNameNotificationDelegateView;
friend class ::ash::KioskExternalUpdateNotificationView;
friend class ::ash::LayoutWidgetDelegateView;
friend class ::ash::MaximizeDelegateView;
friend class ::ash::NonClientFrameViewAshTestWidgetDelegate;
friend class ::ash::PipTest;
friend class ::ash::QuickInsertSubmenuView;
friend class ::ash::QuickInsertView;
friend class ::ash::ResizableWidgetDelegate;
friend class ::ash::RootWindowControllerTest;
friend class ::ash::ShellTest;
friend class ::ash::SystemDialogDelegateView;
friend class ::ash::SystemUIComponentsStyleViewerView;
friend class ::ash::TestChildModalParent;
friend class ::ash::TestTextInputView;
friend class ::ash::TestWidgetBuilderDelegate;
friend class ::ash::TestWidgetDelegateAsh;
friend class ::ash::TestWindow;
friend class ::ash::WallpaperWidgetDelegate;
friend class ::ash::WideFrameView;
friend class ::ash::WidgetWithSystemUIComponentView;
friend class ::ash::WindowCycleView;
FRIEND_TEST_ALL_PREFIXES(::ash::ExtendedDesktopTest, SystemModal);
FRIEND_TEST_ALL_PREFIXES(::ash::MruWindowTrackerOrderTest, Basic);
FRIEND_TEST_ALL_PREFIXES(::ash::ShellTest, CreateWindowWithPreferredSize);
friend class ::ash::sharesheet::TestWidgetDelegate;
friend class ::ash::shell::ToplevelWindow;
friend class ::autofill::PopupBaseView;
friend class ::eye_dropper::EyeDropperView;
friend class ::message_center::MessagePopupView;
friend class ::native_app_window::NativeAppWindowViews;
friend class ::ui::ime::CandidateViewTest;
friend class MoveTestWidgetDelegate;
friend class ShapedWidgetDelegate;
FRIEND_TEST_ALL_PREFIXES(NativeViewHostAuraTest,
FocusManagerUpdatedDuringDestruction);
friend class examples::ExamplesWindowContents;
friend class test::GetNativeThemeFromDestructorView;
friend class test::TestingWidgetDelegateView;
FRIEND_TEST_ALL_PREFIXES(test::WidgetOwnsNativeWidgetTest,
WidgetDelegateView);
WidgetDelegateView();
static WdvPassKey CreatePassKey() { return WdvPassKey(); }
};
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_