summaryrefslogtreecommitdiff
path: root/chromium/ui/views/widget
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2021-10-26 13:57:00 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2021-11-02 11:31:01 +0000
commit1943b3c2a1dcee36c233724fc4ee7613d71b9cf6 (patch)
tree8c1b5f12357025c197da5427ae02cfdc2f3570d6 /chromium/ui/views/widget
parent21ba0c5d4bf8fba15dddd97cd693bad2358b77fd (diff)
downloadqtwebengine-chromium-1943b3c2a1dcee36c233724fc4ee7613d71b9cf6.tar.gz
BASELINE: Update Chromium to 94.0.4606.111
Change-Id: I924781584def20fc800bedf6ff41fdb96c438193 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/ui/views/widget')
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_capture_client.cc1
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.cc30
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc49
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.h4
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_screen_x11.cc2
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host.cc9
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.cc28
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h6
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_linux_interactive_uitest.cc11
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc21
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h11
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform_unittest.cc6
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc70
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h43
-rw-r--r--chromium/ui/views/widget/drop_helper.cc14
-rw-r--r--chromium/ui/views/widget/drop_helper.h12
-rw-r--r--chromium/ui/views/widget/native_widget_aura.cc30
-rw-r--r--chromium/ui/views/widget/native_widget_aura.h6
-rw-r--r--chromium/ui/views/widget/native_widget_aura_unittest.cc25
-rw-r--r--chromium/ui/views/widget/native_widget_delegate.h6
-rw-r--r--chromium/ui/views/widget/native_widget_mac.h17
-rw-r--r--chromium/ui/views/widget/native_widget_mac.mm36
-rw-r--r--chromium/ui/views/widget/native_widget_mac_unittest.mm21
-rw-r--r--chromium/ui/views/widget/native_widget_private.h4
-rw-r--r--chromium/ui/views/widget/root_view.cc4
-rw-r--r--chromium/ui/views/widget/widget.cc171
-rw-r--r--chromium/ui/views/widget/widget.h39
-rw-r--r--chromium/ui/views/widget/widget_delegate.cc33
-rw-r--r--chromium/ui/views/widget/widget_delegate.h45
-rw-r--r--chromium/ui/views/widget/widget_delegate_unittest.cc25
-rw-r--r--chromium/ui/views/widget/widget_hwnd_utils.cc3
-rw-r--r--chromium/ui/views/widget/widget_interactive_uitest.cc21
-rw-r--r--chromium/ui/views/widget/widget_observer.h1
-rw-r--r--chromium/ui/views/widget/widget_unittest.cc93
-rw-r--r--chromium/ui/views/widget/window_reorderer.cc2
35 files changed, 656 insertions, 243 deletions
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_capture_client.cc b/chromium/ui/views/widget/desktop_aura/desktop_capture_client.cc
index d437e382af5..93a726143bb 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_capture_client.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_capture_client.cc
@@ -4,6 +4,7 @@
#include "ui/views/widget/desktop_aura/desktop_capture_client.h"
+#include "base/containers/cxx20_erase.h"
#include "ui/aura/client/capture_client_observer.h"
#include "ui/aura/env.h"
#include "ui/aura/window.h"
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.cc b/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.cc
index cb7cea0d488..9307934a4ae 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.cc
@@ -43,15 +43,12 @@ ui::mojom::DragOperation DesktopDragDropClientWin::StartDragAndDrop(
int allowed_operations,
ui::mojom::DragEventSource source) {
drag_drop_in_progress_ = true;
+ gfx::Point touch_screen_point;
if (source == ui::mojom::DragEventSource::kTouch) {
- gfx::Point screen_point = display::win::ScreenWin::DIPToScreenPoint(
- {screen_location.x(), screen_location.y()});
- // Send a mouse down and mouse move before do drag drop runs its own event
- // loop. This is required for ::DoDragDrop to start the drag.
- ui::SendMouseEvent(screen_point,
- MOUSEEVENTF_RIGHTDOWN | MOUSEEVENTF_ABSOLUTE);
- ui::SendMouseEvent(screen_point, MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE);
- desktop_host_->SetInTouchDrag(true);
+ touch_screen_point =
+ screen_location + source_window->GetBoundsInScreen().OffsetFromOrigin();
+ source_window->GetHost()->ConvertDIPToPixels(&touch_screen_point);
+ desktop_host_->StartTouchDrag(touch_screen_point);
// Gesture state gets left in a state where you can't start
// another drag, unless it's cleaned up. Cleaning it up before starting
// drag drop also fixes an issue with getting two kGestureScrollBegin events
@@ -68,9 +65,11 @@ ui::mojom::DragOperation DesktopDragDropClientWin::StartDragAndDrop(
DWORD effect;
- // Disable hang watching until the end of the function since the user can take
- // unbounded time to complete the drag. (http://crbug.com/806174)
- base::IgnoreHangsInScope disabler;
+ // Never consider the current scope as hung. The hang watching deadline (if
+ // any) is not valid since the user can take unbounded time to complete the
+ // drag. (http://crbug.com/806174)
+ base::HangWatcher::InvalidateActiveExpectations();
+
base::TimeTicks start_time = base::TimeTicks::Now();
HRESULT result = ::DoDragDrop(
@@ -87,8 +86,8 @@ ui::mojom::DragOperation DesktopDragDropClientWin::StartDragAndDrop(
// it's called when it gets a mouse move event as well. (::DoDragDrop
// doesn't support touch, so Chrome synthesizes mouse events from touch
// events during drag drop.)
- // In the touch failure case, when ::DoDragDrop blocks waiting for a right
- // mouse button down event to start the drag, it only calls
+ // In the touch failure case, when ::DoDragDrop blocks waiting for a mouse
+ // button down event to start the drag, it only calls
// QueryContinueDrag once, when it gets an event that terminates the blocked
// drag drop, e.g., a swipe gesture from outside the Chrome window. So, we
// detect the failure case when a drag drop lasts more than one second, and
@@ -98,7 +97,10 @@ ui::mojom::DragOperation DesktopDragDropClientWin::StartDragAndDrop(
drag_source_->num_query_continues() > 1 ||
(base::TimeTicks::Now() - start_time <
base::TimeDelta::FromSeconds(1)));
- desktop_host_->SetInTouchDrag(false);
+ desktop_host_->FinishTouchDrag(touch_screen_point);
+ // Move the mouse cursor to where the drag drop started, to avoid issues
+ // when the drop is outside of the Chrome window.
+ ::SetCursorPos(touch_screen_point.x(), touch_screen_point.y());
}
drag_source_copy->set_data(nullptr);
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc b/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
index de5ad7a0142..841458639c0 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
@@ -68,6 +68,7 @@
#include "ui/wm/core/visibility_controller.h"
#include "ui/wm/core/window_animations.h"
#include "ui/wm/core/window_modality_controller.h"
+#include "ui/wm/core/window_util.h"
#include "ui/wm/public/activation_client.h"
#if defined(OS_WIN)
@@ -110,8 +111,7 @@ class DesktopNativeWidgetTopLevelHandler : public aura::WindowObserver {
#if defined(OS_WIN)
// For menus, on Windows versions that support drop shadow remove
// the standard frame in order to keep just the shadow.
- if (::features::IsFormControlsRefreshEnabled() &&
- init_params.type == Widget::InitParams::TYPE_MENU)
+ if (init_params.type == Widget::InitParams::TYPE_MENU)
init_params.remove_standard_frame = true;
#endif
init_params.bounds = bounds;
@@ -404,7 +404,18 @@ void DesktopNativeWidgetAura::HandleActivationChanged(bool active) {
: focus_manager->GetStoredFocusView();
if (!view_for_activation || !view_for_activation->GetWidget()) {
view_for_activation = GetWidget()->GetRootView();
+ activation_client->ActivateWindow(content_window_);
} else if (view_for_activation == focus_manager->GetStoredFocusView()) {
+ // Update activation before restoring focus to prevent race condition.
+ // RestoreFocusedView() will activate the widget if Widget::IsActive()
+ // is false. Note that IsActive() checks ActivationClient for active
+ // widget, if ActivationClient is updated after focus, we risk running
+ // into an infinite loop.
+ // In practice, infinite loop does not happen because the window tree
+ // host avoids re-entrance to Activate() when the OS's window is active.
+ // But this is still a risk when two DNWAs both try to activate itself.
+ activation_client->ActivateWindow(
+ view_for_activation->GetWidget()->GetNativeView());
// When desktop native widget has modal transient child, we don't
// restore focused view here, as the modal transient child window will
// get activated and focused. Thus, we are not left with multiple
@@ -418,8 +429,7 @@ void DesktopNativeWidgetAura::HandleActivationChanged(bool active) {
restore_focus_on_activate_ = false;
}
}
- activation_client->ActivateWindow(
- view_for_activation->GetWidget()->GetNativeView());
+
// Refreshes the focus info to IMF in case that IMF cached the old info
// about focused text input client when it was "inactive".
GetInputMethod()->OnFocus();
@@ -580,8 +590,8 @@ void DesktopNativeWidgetAura::InitNativeWidget(Widget::InitParams params) {
if (params.type != Widget::InitParams::TYPE_TOOLTIP) {
tooltip_manager_ = std::make_unique<TooltipManagerAura>(GetWidget());
tooltip_controller_ = std::make_unique<corewm::TooltipController>(
-
- desktop_window_tree_host_->CreateTooltip());
+ desktop_window_tree_host_->CreateTooltip(),
+ wm::GetActivationClient(host_->window()));
wm::SetTooltipClient(host_->window(), tooltip_controller_.get());
host_->window()->AddPreTargetHandler(tooltip_controller_.get());
}
@@ -739,6 +749,14 @@ void DesktopNativeWidgetAura::SetWindowIcons(const gfx::ImageSkia& window_icon,
app_icon);
}
+const gfx::ImageSkia* DesktopNativeWidgetAura::GetWindowIcon() {
+ return nullptr;
+}
+
+const gfx::ImageSkia* DesktopNativeWidgetAura::GetWindowAppIcon() {
+ return nullptr;
+}
+
void DesktopNativeWidgetAura::InitModalType(ui::ModalType modal_type) {
// 99% of the time, we should not be asked to create a
// DesktopNativeWidgetAura that is modal. We only support window modal
@@ -836,7 +854,7 @@ bool DesktopNativeWidgetAura::IsVisible() const {
void DesktopNativeWidgetAura::Activate() {
if (content_window_) {
- bool was_active = IsActive();
+ bool was_tree_active = desktop_window_tree_host_->IsActive();
desktop_window_tree_host_->Activate();
// If the whole window tree host was already active,
@@ -846,7 +864,7 @@ void DesktopNativeWidgetAura::Activate() {
// since if client code is calling Widget::Activate() they probably
// want that particular widget to be activated, not just something
// within that widget hierarchy.
- if (was_active && focus_client_->GetFocusedWindow() != content_window_)
+ if (was_tree_active && focus_client_->GetFocusedWindow() != content_window_)
focus_client_->FocusWindow(content_window_);
}
}
@@ -857,7 +875,8 @@ void DesktopNativeWidgetAura::Deactivate() {
}
bool DesktopNativeWidgetAura::IsActive() const {
- return content_window_ && desktop_window_tree_host_->IsActive();
+ return content_window_ && desktop_window_tree_host_->IsActive() &&
+ wm::IsActiveWindow(content_window_);
}
void DesktopNativeWidgetAura::SetZOrderLevel(ui::ZOrderLevel order) {
@@ -907,7 +926,8 @@ void DesktopNativeWidgetAura::Restore() {
desktop_window_tree_host_->Restore();
}
-void DesktopNativeWidgetAura::SetFullscreen(bool fullscreen) {
+void DesktopNativeWidgetAura::SetFullscreen(bool fullscreen,
+ const base::TimeDelta& delay) {
if (content_window_)
desktop_window_tree_host_->SetFullscreen(fullscreen);
}
@@ -1273,9 +1293,12 @@ ui::mojom::DragOperation DesktopNativeWidgetAura::OnPerformDrop(
aura::client::DragDropDelegate::DropCallback
DesktopNativeWidgetAura::GetDropCallback(const ui::DropTargetEvent& event) {
- // TODO(crbug.com/1197505): Return drop callback.
- NOTREACHED();
- return base::NullCallback();
+ DCHECK(drop_helper_);
+ if (ShouldActivate())
+ Activate();
+
+ return drop_helper_->GetDropCallback(event.data(), event.location(),
+ last_drop_operation_);
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.h b/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.h
index 8dd86cd6e28..661b6cd232b 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.h
+++ b/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.h
@@ -138,6 +138,8 @@ class VIEWS_EXPORT DesktopNativeWidgetAura
bool SetWindowTitle(const std::u16string& title) override;
void SetWindowIcons(const gfx::ImageSkia& window_icon,
const gfx::ImageSkia& app_icon) override;
+ const gfx::ImageSkia* GetWindowIcon() override;
+ const gfx::ImageSkia* GetWindowAppIcon() override;
void InitModalType(ui::ModalType modal_type) override;
gfx::Rect GetWindowBoundsInScreen() const override;
gfx::Rect GetClientAreaBoundsInScreen() const override;
@@ -167,7 +169,7 @@ class VIEWS_EXPORT DesktopNativeWidgetAura
bool IsMaximized() const override;
bool IsMinimized() const override;
void Restore() override;
- void SetFullscreen(bool fullscreen) override;
+ void SetFullscreen(bool fullscreen, const base::TimeDelta& delay) override;
bool IsFullscreen() const override;
void SetCanAppearInExistingFullscreenSpaces(
bool can_appear_in_existing_fullscreen_spaces) override;
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_screen_x11.cc b/chromium/ui/views/widget/desktop_aura/desktop_screen_x11.cc
index 956c0824a45..ac6e5399e39 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_screen_x11.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_screen_x11.cc
@@ -100,7 +100,7 @@ gfx::NativeWindow DesktopScreenX11::GetLocalProcessWindowAtPoint(
}
int DesktopScreenX11::GetNumDisplays() const {
- return int{x11_display_manager_->displays().size()};
+ return static_cast<int>(x11_display_manager_->displays().size());
}
const std::vector<display::Display>& DesktopScreenX11::GetAllDisplays() const {
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host.cc b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host.cc
index 047f9a9523d..493674eea83 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host.cc
@@ -4,6 +4,7 @@
#include "ui/views/widget/desktop_aura/desktop_window_tree_host.h"
+#include "build/build_config.h"
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h"
#include "ui/display/screen.h"
@@ -12,7 +13,15 @@
namespace views {
void DesktopWindowTreeHost::SetBoundsInDIP(const gfx::Rect& bounds) {
+#if defined(OS_WIN)
+ // The window parameter is intentionally passed as nullptr on Windows because
+ // a non-null window parameter causes errors when restoring windows to saved
+ // positions in variable-DPI situations. See https://crbug.com/1224715 for
+ // details.
+ aura::Window* root = nullptr;
+#else
aura::Window* root = AsWindowTreeHost()->window();
+#endif
const gfx::Rect bounds_in_pixels =
display::Screen::GetScreen()->DIPToScreenRectInWindow(root, bounds);
AsWindowTreeHost()->SetBoundsInPixels(bounds_in_pixels);
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.cc b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.cc
index 7f7d82f5186..6e09038a0ff 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.cc
@@ -19,6 +19,7 @@
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/events/event.h"
+#include "ui/platform_window/extensions/desk_extension.h"
#include "ui/platform_window/extensions/wayland_extension.h"
#include "ui/platform_window/extensions/x11_extension.h"
#include "ui/platform_window/platform_window_init_properties.h"
@@ -159,12 +160,22 @@ base::OnceClosure DesktopWindowTreeHostLinux::DisableEventListening() {
}
ui::WaylandExtension* DesktopWindowTreeHostLinux::GetWaylandExtension() {
- return ui::GetWaylandExtension(*(platform_window()));
+ return platform_window() ? ui::GetWaylandExtension(*(platform_window()))
+ : nullptr;
}
const ui::WaylandExtension* DesktopWindowTreeHostLinux::GetWaylandExtension()
const {
- return ui::GetWaylandExtension(*(platform_window()));
+ return platform_window() ? ui::GetWaylandExtension(*(platform_window()))
+ : nullptr;
+}
+
+ui::DeskExtension* DesktopWindowTreeHostLinux::GetDeskExtension() {
+ return ui::GetDeskExtension(*(platform_window()));
+}
+
+const ui::DeskExtension* DesktopWindowTreeHostLinux::GetDeskExtension() const {
+ return ui::GetDeskExtension(*(platform_window()));
}
void DesktopWindowTreeHostLinux::Init(const Widget::InitParams& params) {
@@ -216,11 +227,6 @@ Widget::MoveLoopResult DesktopWindowTreeHostLinux::RunMoveLoop(
}
void DesktopWindowTreeHostLinux::DispatchEvent(ui::Event* event) {
- // The input can be disabled and the widget marked as non-active in case of
- // opened file-dialogs.
- if (event->IsKeyEvent() && !native_widget_delegate()->AsWidget()->IsActive())
- return;
-
// In Windows, the native events sent to chrome are separated into client
// and non-client versions of events, which we record on our LocatedEvent
// structures. On X11/Wayland, we emulate the concept of non-client. Before we
@@ -295,11 +301,13 @@ void DesktopWindowTreeHostLinux::OnActivationChanged(bool active) {
}
ui::X11Extension* DesktopWindowTreeHostLinux::GetX11Extension() {
- return ui::GetX11Extension(*(platform_window()));
+ return platform_window() ? ui::GetX11Extension(*(platform_window()))
+ : nullptr;
}
const ui::X11Extension* DesktopWindowTreeHostLinux::GetX11Extension() const {
- return ui::GetX11Extension(*(platform_window()));
+ return platform_window() ? ui::GetX11Extension(*(platform_window()))
+ : nullptr;
}
#if BUILDFLAG(USE_ATK)
@@ -312,7 +320,7 @@ bool DesktopWindowTreeHostLinux::OnAtkKeyEvent(AtkKeyEventStruct* atk_event,
}
#endif
-bool DesktopWindowTreeHostLinux::IsOverrideRedirect(bool is_tiling_wm) const {
+bool DesktopWindowTreeHostLinux::IsOverrideRedirect() const {
// BrowserDesktopWindowTreeHostLinux implements this for browser windows.
return false;
}
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h
index 49c2776892f..dec3dd21f77 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h
+++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h
@@ -24,6 +24,7 @@ class ScopedWindowTargeter;
} // namespace aura
namespace ui {
+class DeskExtension;
class X11Extension;
class WaylandExtension;
} // namespace ui
@@ -73,6 +74,9 @@ class VIEWS_EXPORT DesktopWindowTreeHostLinux
ui::WaylandExtension* GetWaylandExtension();
const ui::WaylandExtension* GetWaylandExtension() const;
+ ui::DeskExtension* GetDeskExtension();
+ const ui::DeskExtension* GetDeskExtension() const;
+
protected:
// Overridden from DesktopWindowTreeHost:
void Init(const Widget::InitParams& params) override;
@@ -115,7 +119,7 @@ class VIEWS_EXPORT DesktopWindowTreeHostLinux
#if BUILDFLAG(USE_ATK)
bool OnAtkKeyEvent(AtkKeyEventStruct* atk_key_event, bool transient) override;
#endif
- bool IsOverrideRedirect(bool is_tiling_wm) const override;
+ bool IsOverrideRedirect() const override;
// Enables event listening after closing |dialog|.
void EnableEventListening();
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_linux_interactive_uitest.cc b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_linux_interactive_uitest.cc
index 6567106c963..fc19ea7df85 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_linux_interactive_uitest.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_linux_interactive_uitest.cc
@@ -45,7 +45,6 @@ bool IsNonClientComponent(int hittest) {
default:
return false;
}
- return true;
}
#if defined(USE_X11)
@@ -72,10 +71,12 @@ void DispatchMouseMotionEvent(DesktopWindowTreeHostLinux* desktop_host,
.detail = x11::Motion::Normal,
.root = connection->default_root(),
.event = static_cast<x11::Window>(desktop_host->GetAcceleratedWidget()),
- .root_x = point_in_screen.x(),
- .root_y = point_in_screen.y(),
- .event_x = point_in_screen.x() - bounds_in_screen.x(),
- .event_y = point_in_screen.y() - bounds_in_screen.y(),
+ .root_x = static_cast<int16_t>(point_in_screen.x()),
+ .root_y = static_cast<int16_t>(point_in_screen.y()),
+ .event_x =
+ static_cast<int16_t>(point_in_screen.x() - bounds_in_screen.x()),
+ .event_y =
+ static_cast<int16_t>(point_in_screen.y() - bounds_in_screen.y()),
.same_screen = true,
};
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc
index a250b77813f..51c32303d2f 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc
@@ -129,10 +129,9 @@ ui::PlatformWindowInitProperties ConvertWidgetInitParamsToInitProperties(
ui::OzonePlatform::GetInstance()
->GetPlatformProperties()
.set_parent_for_non_top_level_windows) {
- // If the parent has not been provided, but there is context, use the
- // context's widget as the parent of a new platform window.
- if (params.context && params.context->GetHost() &&
- !properties.parent_widget) {
+ // If context has been set, use that as the parent_widget so that Wayland
+ // creates a correct hierarchy of windows.
+ if (params.context && params.context->GetHost()) {
properties.parent_widget =
params.context->GetHost()->GetAcceleratedWidget();
}
@@ -221,9 +220,8 @@ void DesktopWindowTreeHostPlatform::Init(const Widget::InitParams& params) {
// Disable compositing on tooltips as a workaround for
// https://crbug.com/442111.
- CreateCompositor(viz::FrameSinkId(),
- params.force_software_compositing ||
- params.type == Widget::InitParams::TYPE_TOOLTIP);
+ CreateCompositor(params.force_software_compositing ||
+ params.type == Widget::InitParams::TYPE_TOOLTIP);
WindowTreeHost::OnAcceleratedWidgetAvailable();
InitHost();
@@ -748,8 +746,9 @@ void DesktopWindowTreeHostPlatform::OnClosed() {
}
void DesktopWindowTreeHostPlatform::OnWindowStateChanged(
+ ui::PlatformWindowState old_state,
ui::PlatformWindowState new_state) {
- bool was_minimized = old_state_ == ui::PlatformWindowState::kMinimized;
+ bool was_minimized = old_state == ui::PlatformWindowState::kMinimized;
bool is_minimized = new_state == ui::PlatformWindowState::kMinimized;
// Propagate minimization/restore to compositor to avoid drawing 'blank'
@@ -765,8 +764,6 @@ void DesktopWindowTreeHostPlatform::OnWindowStateChanged(
}
}
- old_state_ = new_state;
-
// Now that we have different window properties, we may need to relayout the
// window. (The windows code doesn't need this because their window change is
// synchronous.)
@@ -810,6 +807,10 @@ SkPath DesktopWindowTreeHostPlatform::GetWindowMaskForWindowShapeInPixels() {
return window_mask;
}
+absl::optional<ui::MenuType> DesktopWindowTreeHostPlatform::GetMenuType() {
+ return GetContentWindow()->GetProperty(aura::client::kMenuType);
+}
+
void DesktopWindowTreeHostPlatform::OnWorkspaceChanged() {
OnHostWorkspaceChanged();
}
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h
index b904b4f41cc..d1e8528638c 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h
+++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h
@@ -119,13 +119,15 @@ class VIEWS_EXPORT DesktopWindowTreeHostPlatform
// PlatformWindowDelegate:
void OnClosed() override;
- void OnWindowStateChanged(ui::PlatformWindowState new_state) override;
+ void OnWindowStateChanged(ui::PlatformWindowState old_state,
+ ui::PlatformWindowState new_state) override;
void OnCloseRequest() override;
void OnWillDestroyAcceleratedWidget() override;
void OnActivationChanged(bool active) override;
absl::optional<gfx::Size> GetMinimumSizeForWindow() override;
absl::optional<gfx::Size> GetMaximumSizeForWindow() override;
SkPath GetWindowMaskForWindowShapeInPixels() override;
+ absl::optional<ui::MenuType> GetMenuType() override;
// ui::WorkspaceExtensionDelegate:
void OnWorkspaceChanged() override;
@@ -140,8 +142,6 @@ class VIEWS_EXPORT DesktopWindowTreeHostPlatform
return desktop_native_widget_aura_;
}
- ui::PlatformWindowState window_show_state() { return old_state_; }
-
// These are not general purpose methods and must be used with care. Please
// make sure you understand the rounding direction before using.
gfx::Rect ToDIPRect(const gfx::Rect& rect_in_pixels) const;
@@ -180,11 +180,6 @@ class VIEWS_EXPORT DesktopWindowTreeHostPlatform
DesktopWindowTreeHostPlatform* window_parent_ = nullptr;
std::set<DesktopWindowTreeHostPlatform*> window_children_;
- // Keep track of PlatformWindow state so that we would react correctly and set
- // visibility only if the window was minimized or was unminimized from the
- // normal state.
- ui::PlatformWindowState old_state_ = ui::PlatformWindowState::kUnknown;
-
// Used for tab dragging in move loop requests.
WindowMoveClientPlatform window_move_client_;
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform_unittest.cc b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform_unittest.cc
index 51cbb691d8e..40dff77d828 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform_unittest.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform_unittest.cc
@@ -162,12 +162,14 @@ TEST_F(DesktopWindowTreeHostPlatformTest,
EXPECT_TRUE(widget->GetNativeWindow()->IsVisible());
// Pretend a PlatformWindow enters the minimized state.
- host_platform->OnWindowStateChanged(ui::PlatformWindowState::kMinimized);
+ host_platform->OnWindowStateChanged(ui::PlatformWindowState::kUnknown,
+ ui::PlatformWindowState::kMinimized);
EXPECT_FALSE(widget->GetNativeWindow()->IsVisible());
// Pretend a PlatformWindow exits the minimized state.
- host_platform->OnWindowStateChanged(ui::PlatformWindowState::kNormal);
+ host_platform->OnWindowStateChanged(ui::PlatformWindowState::kMinimized,
+ ui::PlatformWindowState::kNormal);
EXPECT_TRUE(widget->GetNativeWindow()->IsVisible());
}
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
index fb8bbb639f6..042fb2b5d16 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
@@ -66,6 +66,14 @@ namespace views {
namespace {
+// While the mouse is locked we want the invisible mouse to stay within the
+// confines of the screen so we keep it in a capture region the size of the
+// screen. However, on windows when the mouse hits the edge of the screen some
+// events trigger and cause strange issues to occur. To stop those events from
+// occurring we add a small border around the edge of the capture region.
+// This constant controls how many pixels wide that border is.
+const int kMouseCaptureRegionBorder = 5;
+
gfx::Size GetExpandedWindowSize(bool is_translucent, gfx::Size size) {
if (!is_translucent || !ui::win::IsAeroGlassEnabled())
return size;
@@ -80,6 +88,24 @@ void InsetBottomRight(gfx::Rect* rect, const gfx::Vector2d& vector) {
rect->Inset(0, 0, vector.x(), vector.y());
}
+// Updates the cursor clip region. Used for mouse locking.
+void UpdateMouseLockRegion(aura::Window* window, bool locked) {
+ if (!locked) {
+ ::ClipCursor(nullptr);
+ return;
+ }
+
+ RECT window_rect =
+ display::Screen::GetScreen()
+ ->DIPToScreenRectInWindow(window, window->GetBoundsInScreen())
+ .ToRECT();
+ window_rect.left += kMouseCaptureRegionBorder;
+ window_rect.right -= kMouseCaptureRegionBorder;
+ window_rect.top += kMouseCaptureRegionBorder;
+ window_rect.bottom -= kMouseCaptureRegionBorder;
+ ::ClipCursor(&window_rect);
+}
+
} // namespace
DEFINE_UI_CLASS_PROPERTY_KEY(aura::Window*, kContentWindowForRootWindow, NULL)
@@ -124,10 +150,20 @@ aura::Window* DesktopWindowTreeHostWin::GetContentWindowForHWND(HWND hwnd) {
return host ? host->window()->GetProperty(kContentWindowForRootWindow) : NULL;
}
-void DesktopWindowTreeHostWin::SetInTouchDrag(bool in_touch_drag) {
- in_touch_drag_ = in_touch_drag;
+void DesktopWindowTreeHostWin::StartTouchDrag(gfx::Point screen_point) {
+ // Send a mouse down and mouse move before do drag drop runs its own event
+ // loop. This is required for ::DoDragDrop to start the drag.
+ ui::SendMouseEvent(screen_point, MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_ABSOLUTE);
+ ui::SendMouseEvent(screen_point, MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE);
+ in_touch_drag_ = true;
}
+void DesktopWindowTreeHostWin::FinishTouchDrag(gfx::Point screen_point) {
+ if (in_touch_drag_) {
+ in_touch_drag_ = false;
+ ui::SendMouseEvent(screen_point, MOUSEEVENTF_LEFTUP | MOUSEEVENTF_ABSOLUTE);
+ }
+}
////////////////////////////////////////////////////////////////////////////////
// DesktopWindowTreeHostWin, DesktopWindowTreeHost implementation:
@@ -155,7 +191,7 @@ void DesktopWindowTreeHostWin::Init(const Widget::InitParams& params) {
gfx::Rect pixel_bounds =
display::win::ScreenWin::DIPToScreenRect(nullptr, params.bounds);
message_handler_->Init(parent_hwnd, pixel_bounds);
- CreateCompositor(viz::FrameSinkId(), params.force_software_compositing);
+ CreateCompositor(params.force_software_compositing);
OnAcceleratedWidgetAvailable();
InitHost();
window()->Show();
@@ -663,6 +699,16 @@ DesktopWindowTreeHostWin::RequestUnadjustedMovement() {
return message_handler_->RegisterUnadjustedMouseEvent();
}
+void DesktopWindowTreeHostWin::LockMouse(aura::Window* window) {
+ UpdateMouseLockRegion(window, true /*locked*/);
+ WindowTreeHost::LockMouse(window);
+}
+
+void DesktopWindowTreeHostWin::UnlockMouse(aura::Window* window) {
+ UpdateMouseLockRegion(window, false /*locked*/);
+ WindowTreeHost::UnlockMouse(window);
+}
+
////////////////////////////////////////////////////////////////////////////////
// DesktopWindowTreeHostWin, wm::AnimationHost implementation:
@@ -892,10 +938,6 @@ void DesktopWindowTreeHostWin::HandleWorkAreaChanged() {
GetWidget()->widget_delegate()->OnWorkAreaChanged();
}
-void DesktopWindowTreeHostWin::HandleVisibilityChanging(bool visible) {
- native_widget_delegate_->OnNativeWidgetVisibilityChanging(visible);
-}
-
void DesktopWindowTreeHostWin::HandleVisibilityChanged(bool visible) {
native_widget_delegate_->OnNativeWidgetVisibilityChanged(visible);
}
@@ -987,7 +1029,6 @@ void DesktopWindowTreeHostWin::HandleTouchEvent(ui::TouchEvent* event) {
// by the time we attempt to process them.
if (!GetWidget()->GetNativeView())
return;
-
if (in_touch_drag_) {
POINT event_point;
event_point.x = event->location().x();
@@ -999,10 +1040,19 @@ void DesktopWindowTreeHostWin::HandleTouchEvent(ui::TouchEvent* event) {
if (event->type() == ui::ET_TOUCH_MOVED) {
ui::SendMouseEvent(screen_point, MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE);
} else if (event->type() == ui::ET_TOUCH_RELEASED) {
- ui::SendMouseEvent(screen_point,
- MOUSEEVENTF_RIGHTUP | MOUSEEVENTF_ABSOLUTE);
+ FinishTouchDrag(screen_point);
}
}
+ // TODO(crbug.com/229301) Calling ::SetCursorPos for ui::ET_TOUCH_PRESSED
+ // events here would fix web ui tab strip drags when the cursor is not over
+ // the Chrome window - The TODO is to figure out if that's reasonable, since
+ // it would change the cursor pos on every touch event. Or figure out if there
+ // is a less intrusive way of fixing the cursor position. If we can do that,
+ // we can remove the call to ::SetCursorPos in
+ // DesktopDragDropClientWin::StartDragAndDrop. Note that calling SetCursorPos
+ // at the start of StartDragAndDrop breaks touch drag and drop, so it has to
+ // be called some time before we get to StartDragAndDrop.
+
// Currently we assume the window that has capture gets touch events too.
aura::WindowTreeHost* host =
aura::WindowTreeHost::GetForAcceleratedWidget(GetCapture());
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
index 07078cbdf22..db129908916 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
+++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
@@ -59,11 +59,35 @@ class VIEWS_EXPORT DesktopWindowTreeHostWin
// A way of converting an HWND into a content window.
static aura::Window* GetContentWindowForHWND(HWND hwnd);
- // Set to true when DesktopDragDropClientWin starts a touch-initiated drag
- // drop and false when it finishes. While in touch drag, if pointer events are
- // received, the equivalent mouse events are generated, because ole32
- // ::DoDragDrop does not seem to handle pointer events.
- void SetInTouchDrag(bool in_touch_drag);
+ // When DesktopDragDropClientWin starts a touch-initiated drag, it calls
+ // this method to record that we're in touch drag mode, and synthesizes
+ // right mouse button down and move events to get ::DoDragDrop started.
+ void StartTouchDrag(gfx::Point screen_point);
+
+ // If in touch drag mode, this method synthesizes a left mouse button up
+ // event to match the left mouse button down event in StartTouchDrag. It
+ // also restores the cursor pos to where the drag started, to avoid leaving
+ // the cursor outside the Chrome window doing the drag drop. This allows
+ // subsequent touch drag drops to succeed. Touch drag drop requires that
+ // the cursor be over the same window as the touch drag point.
+ // This needs to be called in two cases:
+ // 1. The normal case is that ::DoDragDrop starts, we get touch move events,
+ // which we turn into mouse move events, and then we get a touch release
+ // event. Calling FinishTouchDragIfInDrag generates a mouse up, which stops
+ // the drag drop.
+ // 2. ::DoDragDrop exits immediately, w/o us handling any touch events. In
+ // this case, FinishTouchDragIfInDrag makes sure we have a mouse button up to
+ // match the mouse button down, because we won't get a touch release event. We
+ // don't know for sure if ::DoDragDrop exited immediately, other than by
+ // checking if `in_touch_drag_` has been set to false.
+ //
+ // So, we always call FinishTouchDragIfInDrag after ::DoDragDrop exits, to
+ // make sure it gets called, and we make it handle getting called multiple
+ // times. Most of the time, FinishTouchDrag will have already been called when
+ // we get a touch release event, in which case the second call needs to be a
+ // noop, which is accomplished by checking if `in_touch_drag_` is already
+ // false.
+ void FinishTouchDrag(gfx::Point screen_point);
protected:
// Overridden from DesktopWindowTreeHost:
@@ -152,6 +176,8 @@ class VIEWS_EXPORT DesktopWindowTreeHostWin
const gfx::Point& location_in_pixels) override;
std::unique_ptr<aura::ScopedEnableUnadjustedMouseEvents>
RequestUnadjustedMovement() override;
+ void LockMouse(aura::Window* window) override;
+ void UnlockMouse(aura::Window* window) override;
// Overridden from aura::client::AnimationHost
void SetHostTransitionOffsets(
@@ -200,7 +226,6 @@ class VIEWS_EXPORT DesktopWindowTreeHostWin
void HandleEndWMSizeMove() override;
void HandleMove() override;
void HandleWorkAreaChanged() override;
- void HandleVisibilityChanging(bool visible) override;
void HandleVisibilityChanged(bool visible) override;
void HandleWindowMinimizedOrRestored(bool restored) override;
void HandleClientSizeChanged(const gfx::Size& new_size) override;
@@ -316,6 +341,12 @@ class VIEWS_EXPORT DesktopWindowTreeHostWin
// when that stat is no longer tracked.
gfx::Point occluded_window_mouse_event_loc_;
+ // Set to true when DesktopDragDropClientWin starts a touch-initiated drag
+ // drop and false when it finishes. While in touch drag, if touch move events
+ // are received, the equivalent mouse events are generated, because ole32
+ // ::DoDragDrop does not seem to handle touch events. WinRT drag drop does
+ // support touch, but we've been unable to use it in Chrome. See
+ // https://crbug.com/1236783 for more info.
bool in_touch_drag_ = false;
// The z-order level of the window; the window exhibits "always on top"
diff --git a/chromium/ui/views/widget/drop_helper.cc b/chromium/ui/views/widget/drop_helper.cc
index ce8f2d7741a..207276dee55 100644
--- a/chromium/ui/views/widget/drop_helper.cc
+++ b/chromium/ui/views/widget/drop_helper.cc
@@ -6,6 +6,7 @@
#include <memory>
#include <set>
+#include <utility>
#include "base/bind.h"
#include "base/callback.h"
@@ -14,6 +15,7 @@
#include "build/build_config.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/base/dragdrop/mojom/drag_drop_types.mojom.h"
+#include "ui/views/view.h"
#include "ui/views/widget/widget.h"
namespace views {
@@ -102,7 +104,7 @@ DragOperation DropHelper::OnDrop(const OSExchangeData& data,
return drop_view->OnPerformDrop(drop_event);
}
-View::DropCallback DropHelper::GetDropCallback(
+DropHelper::DropCallback DropHelper::GetDropCallback(
const OSExchangeData& data,
const gfx::Point& root_view_location,
int drag_operation) {
@@ -121,7 +123,15 @@ View::DropCallback DropHelper::GetDropCallback(
View::ConvertPointToTarget(root_view, drop_view, &view_location);
ui::DropTargetEvent drop_event(data, gfx::PointF(view_location),
gfx::PointF(view_location), drag_operation);
- return drop_view->GetDropCallback(drop_event);
+
+ auto drop_view_cb = drop_view->GetDropCallback(drop_event);
+ return base::BindOnce(
+ [](View::DropCallback drop_cb, const ui::DropTargetEvent& event,
+ std::unique_ptr<ui::OSExchangeData> data,
+ ui::mojom::DragOperation& output_drag_op) {
+ std::move(drop_cb).Run(event, output_drag_op);
+ },
+ std::move(drop_view_cb));
}
View* DropHelper::CalculateTargetView(const gfx::Point& root_view_location,
diff --git a/chromium/ui/views/widget/drop_helper.h b/chromium/ui/views/widget/drop_helper.h
index f361de1408a..d991dc129e5 100644
--- a/chromium/ui/views/widget/drop_helper.h
+++ b/chromium/ui/views/widget/drop_helper.h
@@ -5,6 +5,7 @@
#ifndef UI_VIEWS_WIDGET_DROP_HELPER_H_
#define UI_VIEWS_WIDGET_DROP_HELPER_H_
+#include <memory>
#include "base/callback_forward.h"
#include "base/macros.h"
@@ -32,6 +33,11 @@ class RootView;
// then either OnDragExit or OnDrop when the drop is done.
class VIEWS_EXPORT DropHelper {
public:
+ using DropCallback =
+ base::OnceCallback<void(const ui::DropTargetEvent& event,
+ std::unique_ptr<ui::OSExchangeData> data,
+ ui::mojom::DragOperation& output_drag_op)>;
+
explicit DropHelper(View* root_view);
~DropHelper();
@@ -76,9 +82,9 @@ class VIEWS_EXPORT DropHelper {
// Invoked when the user drops data on the root view during a drag and drop
// operation, but the drop is held because of DataTransferPolicController.
- View::DropCallback GetDropCallback(const OSExchangeData& data,
- const gfx::Point& root_view_location,
- int drag_operation);
+ DropCallback GetDropCallback(const OSExchangeData& data,
+ const gfx::Point& root_view_location,
+ int drag_operation);
// Calculates the target view for a drop given the specified location in
// the coordinate system of the rootview. This tries to avoid continually
diff --git a/chromium/ui/views/widget/native_widget_aura.cc b/chromium/ui/views/widget/native_widget_aura.cc
index 3b63e2b9883..c2ca1c6bf4a 100644
--- a/chromium/ui/views/widget/native_widget_aura.cc
+++ b/chromium/ui/views/widget/native_widget_aura.cc
@@ -256,7 +256,7 @@ void NativeWidgetAura::InitNativeWidget(Widget::InitParams params) {
// Wait to set the bounds until we have a parent. That way we can know our
// true state/bounds (the LayoutManager may enforce a particular
// state/bounds).
- if (IsMaximized())
+ if (IsMaximized() || IsMinimized())
SetRestoreBounds(window_, window_bounds);
else
SetBounds(window_bounds);
@@ -456,6 +456,14 @@ void NativeWidgetAura::SetWindowIcons(const gfx::ImageSkia& window_icon,
AssignIconToAuraWindow(window_, window_icon, app_icon);
}
+const gfx::ImageSkia* NativeWidgetAura::GetWindowIcon() {
+ return window_->GetProperty(aura::client::kWindowIconKey);
+}
+
+const gfx::ImageSkia* NativeWidgetAura::GetWindowAppIcon() {
+ return window_->GetProperty(aura::client::kAppIconKey);
+}
+
void NativeWidgetAura::InitModalType(ui::ModalType modal_type) {
if (modal_type != ui::MODAL_TYPE_NONE)
window_->SetProperty(aura::client::kModalKey, modal_type);
@@ -597,8 +605,11 @@ void NativeWidgetAura::Show(ui::WindowShowState show_state,
if (!window_)
return;
- if (show_state == ui::SHOW_STATE_MAXIMIZED && !restore_bounds.IsEmpty())
+ if ((show_state == ui::SHOW_STATE_MAXIMIZED ||
+ show_state == ui::SHOW_STATE_MINIMIZED) &&
+ !restore_bounds.IsEmpty()) {
SetRestoreBounds(window_, restore_bounds);
+ }
if (show_state == ui::SHOW_STATE_MAXIMIZED ||
show_state == ui::SHOW_STATE_FULLSCREEN) {
window_->SetProperty(aura::client::kShowStateKey, show_state);
@@ -700,7 +711,8 @@ void NativeWidgetAura::Restore() {
window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
}
-void NativeWidgetAura::SetFullscreen(bool fullscreen) {
+void NativeWidgetAura::SetFullscreen(bool fullscreen,
+ const base::TimeDelta& delay) {
if (!window_ || IsFullscreen() == fullscreen)
return; // Nothing to do.
@@ -723,10 +735,8 @@ void NativeWidgetAura::SetOpacity(float opacity) {
void NativeWidgetAura::SetAspectRatio(const gfx::SizeF& aspect_ratio) {
DCHECK(!aspect_ratio.IsEmpty());
if (window_) {
- // aura::client::kAspectRatio is owned, which allows for passing in this
- // raw pointer.
- window_->SetProperty(aura::client::kAspectRatio,
- new gfx::SizeF(aspect_ratio));
+ // aura::client::kAspectRatio is owned, which allows for passing by value.
+ window_->SetProperty(aura::client::kAspectRatio, gfx::SizeF(aspect_ratio));
}
}
@@ -1103,9 +1113,9 @@ ui::mojom::DragOperation NativeWidgetAura::OnPerformDrop(
aura::client::DragDropDelegate::DropCallback NativeWidgetAura::GetDropCallback(
const ui::DropTargetEvent& event) {
- // TODO(crbug.com/1197506): Return async drop callback function.
- NOTIMPLEMENTED();
- return base::NullCallback();
+ DCHECK(drop_helper_);
+ return drop_helper_->GetDropCallback(event.data(), event.location(),
+ last_drop_operation_);
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/chromium/ui/views/widget/native_widget_aura.h b/chromium/ui/views/widget/native_widget_aura.h
index db6effaafce..fac71091f08 100644
--- a/chromium/ui/views/widget/native_widget_aura.h
+++ b/chromium/ui/views/widget/native_widget_aura.h
@@ -23,7 +23,7 @@
#include "ui/wm/public/activation_delegate.h"
#if defined(OS_MAC)
-#error This file must not be included on macOS; Chromium Mac doesn't use Aura.
+#error "This file must not be included on macOS; Chromium Mac doesn't use Aura."
#endif
namespace aura {
@@ -97,6 +97,8 @@ class VIEWS_EXPORT NativeWidgetAura : public internal::NativeWidgetPrivate,
bool SetWindowTitle(const std::u16string& title) override;
void SetWindowIcons(const gfx::ImageSkia& window_icon,
const gfx::ImageSkia& app_icon) override;
+ const gfx::ImageSkia* GetWindowIcon() override;
+ const gfx::ImageSkia* GetWindowAppIcon() override;
void InitModalType(ui::ModalType modal_type) override;
gfx::Rect GetWindowBoundsInScreen() const override;
gfx::Rect GetClientAreaBoundsInScreen() const override;
@@ -126,7 +128,7 @@ class VIEWS_EXPORT NativeWidgetAura : public internal::NativeWidgetPrivate,
bool IsMaximized() const override;
bool IsMinimized() const override;
void Restore() override;
- void SetFullscreen(bool fullscreen) override;
+ void SetFullscreen(bool fullscreen, const base::TimeDelta& delay) override;
bool IsFullscreen() const override;
void SetCanAppearInExistingFullscreenSpaces(
bool can_appear_in_existing_fullscreen_spaces) override;
diff --git a/chromium/ui/views/widget/native_widget_aura_unittest.cc b/chromium/ui/views/widget/native_widget_aura_unittest.cc
index 4f442a6697e..a1f27a016fb 100644
--- a/chromium/ui/views/widget/native_widget_aura_unittest.cc
+++ b/chromium/ui/views/widget/native_widget_aura_unittest.cc
@@ -793,5 +793,30 @@ TEST_F(NativeWidgetAuraTest, TransientChildModalWindowVisibility) {
EXPECT_TRUE(child.IsVisible());
}
+// Tests that widgets that are created minimized have the correct restore
+// bounds.
+TEST_F(NativeWidgetAuraTest, MinimizedWidgetRestoreBounds) {
+ const gfx::Rect restore_bounds(300, 300);
+
+ Widget widget;
+ Widget::InitParams params(Widget::InitParams::TYPE_WINDOW);
+ params.context = root_window();
+ params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ params.show_state = ui::SHOW_STATE_MINIMIZED;
+ params.bounds = restore_bounds;
+
+ widget.Init(std::move(params));
+ widget.Show();
+
+ aura::Window* window = widget.GetNativeWindow();
+ EXPECT_EQ(ui::SHOW_STATE_MINIMIZED,
+ window->GetProperty(aura::client::kShowStateKey));
+ EXPECT_EQ(restore_bounds,
+ *window->GetProperty(aura::client::kRestoreBoundsKey));
+
+ widget.Restore();
+ EXPECT_EQ(restore_bounds, window->bounds());
+}
+
} // namespace
} // namespace views
diff --git a/chromium/ui/views/widget/native_widget_delegate.h b/chromium/ui/views/widget/native_widget_delegate.h
index 12e70210788..fbfefa1e8e5 100644
--- a/chromium/ui/views/widget/native_widget_delegate.h
+++ b/chromium/ui/views/widget/native_widget_delegate.h
@@ -49,9 +49,6 @@ class VIEWS_EXPORT NativeWidgetDelegate {
// Returns true if the window can be activated.
virtual bool CanActivate() const = 0;
- // Returns true if the window should paint as active.
- virtual bool ShouldPaintAsActive() const = 0;
-
// Returns true if the native widget has been initialized.
virtual bool IsNativeWidgetInitialized() const = 0;
@@ -63,9 +60,6 @@ class VIEWS_EXPORT NativeWidgetDelegate {
virtual void OnNativeFocus() = 0;
virtual void OnNativeBlur() = 0;
- // Called when the window is about to be shown/hidden.
- virtual void OnNativeWidgetVisibilityChanging(bool visible) = 0;
-
// Called when the window is shown/hidden.
virtual void OnNativeWidgetVisibilityChanged(bool visible) = 0;
diff --git a/chromium/ui/views/widget/native_widget_mac.h b/chromium/ui/views/widget/native_widget_mac.h
index 088c98a89b7..ae792308167 100644
--- a/chromium/ui/views/widget/native_widget_mac.h
+++ b/chromium/ui/views/widget/native_widget_mac.h
@@ -8,7 +8,6 @@
#include <memory>
#include <string>
-#include "base/macros.h"
#include "ui/base/ime/input_method_delegate.h"
#include "ui/base/window_open_disposition.h"
#include "ui/gfx/native_widget_types.h"
@@ -26,16 +25,17 @@ class CreateWindowParams;
class NativeWidgetNSWindow;
class ValidateUserInterfaceItemResult;
} // namespace mojom
+
class ApplicationHost;
class NativeWidgetNSWindowBridge;
} // namespace remote_cocoa
namespace views {
namespace test {
-class HitTestNativeWidgetMac;
class MockNativeWidgetMac;
-class WidgetTest;
+class NativeWidgetMacTest;
} // namespace test
+
class NativeWidgetMacNSWindowHost;
class VIEWS_EXPORT NativeWidgetMac : public internal::NativeWidgetPrivate,
@@ -43,6 +43,8 @@ class VIEWS_EXPORT NativeWidgetMac : public internal::NativeWidgetPrivate,
public ui::internal::InputMethodDelegate {
public:
explicit NativeWidgetMac(internal::NativeWidgetDelegate* delegate);
+ NativeWidgetMac(const NativeWidgetMac&) = delete;
+ NativeWidgetMac& operator=(const NativeWidgetMac&) = delete;
~NativeWidgetMac() override;
// Informs |delegate_| that the native widget is about to be destroyed.
@@ -128,6 +130,8 @@ class VIEWS_EXPORT NativeWidgetMac : public internal::NativeWidgetPrivate,
bool SetWindowTitle(const std::u16string& title) override;
void SetWindowIcons(const gfx::ImageSkia& window_icon,
const gfx::ImageSkia& app_icon) override;
+ const gfx::ImageSkia* GetWindowIcon() override;
+ const gfx::ImageSkia* GetWindowAppIcon() override;
void InitModalType(ui::ModalType modal_type) override;
gfx::Rect GetWindowBoundsInScreen() const override;
gfx::Rect GetClientAreaBoundsInScreen() const override;
@@ -157,7 +161,7 @@ class VIEWS_EXPORT NativeWidgetMac : public internal::NativeWidgetPrivate,
bool IsMaximized() const override;
bool IsMinimized() const override;
void Restore() override;
- void SetFullscreen(bool fullscreen) override;
+ void SetFullscreen(bool fullscreen, const base::TimeDelta& delay) override;
bool IsFullscreen() const override;
void SetCanAppearInExistingFullscreenSpaces(
bool can_appear_in_existing_fullscreen_spaces) override;
@@ -256,8 +260,7 @@ class VIEWS_EXPORT NativeWidgetMac : public internal::NativeWidgetPrivate,
private:
friend class test::MockNativeWidgetMac;
- friend class test::HitTestNativeWidgetMac;
- friend class views::test::WidgetTest;
+ friend class views::test::NativeWidgetMacTest;
class ZoomFocusMonitor;
internal::NativeWidgetDelegate* delegate_;
@@ -279,8 +282,6 @@ class VIEWS_EXPORT NativeWidgetMac : public internal::NativeWidgetPrivate,
std::unique_ptr<ZoomFocusMonitor> zoom_focus_monitor_;
// Held while this widget is active if it's a child.
std::unique_ptr<Widget::PaintAsActiveLock> parent_key_lock_;
-
- DISALLOW_COPY_AND_ASSIGN(NativeWidgetMac);
};
} // namespace views
diff --git a/chromium/ui/views/widget/native_widget_mac.mm b/chromium/ui/views/widget/native_widget_mac.mm
index 51358d11989..1a066e4e40c 100644
--- a/chromium/ui/views/widget/native_widget_mac.mm
+++ b/chromium/ui/views/widget/native_widget_mac.mm
@@ -11,24 +11,24 @@
#include <utility>
#include "base/base64.h"
-#include "base/bind.h"
+#include "base/callback.h"
#include "base/mac/scoped_nsobject.h"
#include "base/no_destructor.h"
#include "base/strings/sys_string_conversions.h"
-#include "base/threading/thread_task_runner_handle.h"
#include "components/crash/core/common/crash_key.h"
#import "components/remote_cocoa/app_shim/bridged_content_view.h"
#import "components/remote_cocoa/app_shim/native_widget_mac_nswindow.h"
#import "components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h"
#import "components/remote_cocoa/app_shim/views_nswindow_delegate.h"
-#import "ui/base/cocoa/constrained_window/constrained_window_animation.h"
#import "ui/base/cocoa/window_size_constants.h"
#include "ui/base/ime/init/input_method_factory.h"
#include "ui/base/ime/input_method.h"
#include "ui/compositor/layer.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
+#include "ui/events/gestures/gesture_recognizer.h"
#include "ui/events/gestures/gesture_recognizer_impl_mac.h"
+#include "ui/events/gestures/gesture_types.h"
#include "ui/gfx/font_list.h"
#import "ui/gfx/mac/coordinate_conversion.h"
#include "ui/native_theme/native_theme.h"
@@ -37,6 +37,7 @@
#import "ui/views/cocoa/native_widget_mac_ns_window_host.h"
#include "ui/views/cocoa/text_input_host.h"
#include "ui/views/widget/drop_helper.h"
+#include "ui/views/widget/native_widget_delegate.h"
#include "ui/views/widget/widget_aura_utils.h"
#include "ui/views/widget/widget_delegate.h"
#include "ui/views/window/native_frame_view.h"
@@ -158,14 +159,6 @@ void NativeWidgetMac::OnWindowKeyStatusChanged(
if (is_key) {
widget->OnNativeFocus();
widget->GetFocusManager()->RestoreFocusedView();
- if (NativeWidgetMacNSWindowHost* parent_host = ns_window_host_->parent()) {
- // Unclear under what circumstances this would be null, but speculatively
- // working around https://crbug/1050430
- if (Widget* top_widget =
- parent_host->native_widget_mac()->GetTopLevelWidget()) {
- parent_key_lock_ = top_widget->LockPaintAsActive();
- }
- }
} else {
widget->OnNativeBlur();
widget->GetFocusManager()->StoreFocusedView(true);
@@ -412,6 +405,15 @@ void NativeWidgetMac::InitModalType(ui::ModalType modal_type) {
// Everything happens upon show.
}
+const gfx::ImageSkia* NativeWidgetMac::GetWindowIcon() {
+ NOTIMPLEMENTED_LOG_ONCE();
+ return nullptr;
+}
+const gfx::ImageSkia* NativeWidgetMac::GetWindowAppIcon() {
+ NOTIMPLEMENTED_LOG_ONCE();
+ return nullptr;
+}
+
gfx::Rect NativeWidgetMac::GetWindowBoundsInScreen() const {
return ns_window_host_ ? ns_window_host_->GetWindowBoundsInScreen()
: gfx::Rect();
@@ -644,10 +646,11 @@ void NativeWidgetMac::Restore() {
GetNSWindowMojo()->SetMiniaturized(false);
}
-void NativeWidgetMac::SetFullscreen(bool fullscreen) {
+void NativeWidgetMac::SetFullscreen(bool fullscreen,
+ const base::TimeDelta& delay) {
if (!ns_window_host_)
return;
- ns_window_host_->SetFullscreen(fullscreen);
+ ns_window_host_->SetFullscreen(fullscreen, delay);
}
bool NativeWidgetMac::IsFullscreen() const {
@@ -899,9 +902,10 @@ void NativeWidgetMac::OnDidChangeFocus(View* focused_before,
ui::TextInputClient* new_text_input_client =
input_method->GetTextInputClient();
- // Sanity check: When focus moves away from the widget (i.e. |focused_now|
- // is nil), then the textInputClient will be cleared.
- DCHECK(!!focused_now || !new_text_input_client);
+ // Sanity check: For a top level widget, when focus moves away from the widget
+ // (i.e. |focused_now| is nil), then the textInputClient will be cleared.
+ DCHECK(!!focused_now || !new_text_input_client ||
+ !GetWidget()->is_top_level());
if (ns_window_host_) {
ns_window_host_->text_input_host()->SetTextInputClient(
new_text_input_client);
diff --git a/chromium/ui/views/widget/native_widget_mac_unittest.mm b/chromium/ui/views/widget/native_widget_mac_unittest.mm
index cb78da742ed..4ff63b522fb 100644
--- a/chromium/ui/views/widget/native_widget_mac_unittest.mm
+++ b/chromium/ui/views/widget/native_widget_mac_unittest.mm
@@ -198,6 +198,10 @@ class NativeWidgetMacTest : public WidgetTest {
return widget;
}
+ FocusManager* GetFocusManager(NativeWidgetMac* native_widget) const {
+ return native_widget->focus_manager_;
+ }
+
private:
DISALLOW_COPY_AND_ASSIGN(NativeWidgetMacTest);
};
@@ -2354,6 +2358,23 @@ TEST_F(NativeWidgetMacTest, InitCallback) {
widget_c->CloseNow();
}
+TEST_F(NativeWidgetMacTest, FocusManagerChangeOnReparentNativeView) {
+ WidgetAutoclosePtr toplevel(CreateTopLevelPlatformWidget());
+ Widget* child = CreateChildPlatformWidget(toplevel->GetNativeView());
+ WidgetAutoclosePtr target_toplevel(CreateTopLevelPlatformWidget());
+ EXPECT_EQ(child->GetFocusManager(), toplevel->GetFocusManager());
+ EXPECT_NE(child->GetFocusManager(), target_toplevel->GetFocusManager());
+ NativeWidgetMac* child_native_widget =
+ static_cast<NativeWidgetMac*>(child->native_widget());
+ EXPECT_EQ(GetFocusManager(child_native_widget), child->GetFocusManager());
+
+ Widget::ReparentNativeView(child->GetNativeView(),
+ target_toplevel->GetNativeView());
+ EXPECT_EQ(child->GetFocusManager(), target_toplevel->GetFocusManager());
+ EXPECT_NE(child->GetFocusManager(), toplevel->GetFocusManager());
+ EXPECT_EQ(GetFocusManager(child_native_widget), child->GetFocusManager());
+}
+
} // namespace test
} // namespace views
diff --git a/chromium/ui/views/widget/native_widget_private.h b/chromium/ui/views/widget/native_widget_private.h
index 5738ffb8604..80635de4196 100644
--- a/chromium/ui/views/widget/native_widget_private.h
+++ b/chromium/ui/views/widget/native_widget_private.h
@@ -160,6 +160,8 @@ class VIEWS_EXPORT NativeWidgetPrivate : public NativeWidget {
// app switching UI.
virtual void SetWindowIcons(const gfx::ImageSkia& window_icon,
const gfx::ImageSkia& app_icon) = 0;
+ virtual const gfx::ImageSkia* GetWindowIcon() = 0;
+ virtual const gfx::ImageSkia* GetWindowAppIcon() = 0;
// Initializes the modal type of the window to |modal_type|. Called from
// NativeWidgetDelegate::OnNativeWidgetCreated() before the widget is
@@ -195,7 +197,7 @@ class VIEWS_EXPORT NativeWidgetPrivate : public NativeWidget {
virtual bool IsMaximized() const = 0;
virtual bool IsMinimized() const = 0;
virtual void Restore() = 0;
- virtual void SetFullscreen(bool fullscreen) = 0;
+ virtual void SetFullscreen(bool fullscreen, const base::TimeDelta& delay) = 0;
virtual bool IsFullscreen() const = 0;
virtual void SetCanAppearInExistingFullscreenSpaces(
bool can_appear_in_existing_fullscreen_spaces) = 0;
diff --git a/chromium/ui/views/widget/root_view.cc b/chromium/ui/views/widget/root_view.cc
index 14e2830ae4d..48ec8693ef5 100644
--- a/chromium/ui/views/widget/root_view.cc
+++ b/chromium/ui/views/widget/root_view.cc
@@ -209,7 +209,7 @@ RootView::RootView(Widget* widget)
RootView::~RootView() {
// If we have children remove them explicitly so to make sure a remove
// notification is sent for each one of them.
- RemoveAllChildViews(true);
+ RemoveAllChildViews();
}
// Tree operations -------------------------------------------------------------
@@ -221,7 +221,7 @@ void RootView::SetContentsView(View* contents_view) {
// Widget pointer is valid.
SetUseDefaultFillLayout(true);
if (!children().empty())
- RemoveAllChildViews(true);
+ RemoveAllChildViews();
AddChildView(contents_view);
}
diff --git a/chromium/ui/views/widget/widget.cc b/chromium/ui/views/widget/widget.cc
index 0dcab77ec0d..37047c631af 100644
--- a/chromium/ui/views/widget/widget.cc
+++ b/chromium/ui/views/widget/widget.cc
@@ -8,6 +8,7 @@
#include <utility>
#include "base/auto_reset.h"
+#include "base/bind.h"
#include "base/check_op.h"
#include "base/containers/adapters.h"
#include "base/feature_list.h"
@@ -22,6 +23,7 @@
#include "ui/base/ime/input_method.h"
#include "ui/base/l10n/l10n_font_util.h"
#include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/base/models/image_model.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/color/color_provider_manager.h"
#include "ui/compositor/compositor.h"
@@ -35,6 +37,7 @@
#include "ui/views/focus/focus_manager.h"
#include "ui/views/focus/focus_manager_factory.h"
#include "ui/views/focus/widget_focus_manager.h"
+#include "ui/views/image_model_utils.h"
#include "ui/views/views_delegate.h"
#include "ui/views/views_features.h"
#include "ui/views/widget/any_widget_observer_singleton.h"
@@ -186,15 +189,23 @@ Widget::Widget(InitParams params) {
Widget::~Widget() {
if (widget_delegate_)
widget_delegate_->WidgetDestroying();
- DestroyRootView();
if (ownership_ == InitParams::WIDGET_OWNS_NATIVE_WIDGET) {
delete native_widget_;
+ DCHECK(native_widget_destroyed_);
} else {
// TODO(crbug.com/937381): Revert to DCHECK once we figure out the reason.
CHECK(native_widget_destroyed_)
<< "Destroying a widget with a live native widget. "
<< "Widget probably should use WIDGET_OWNS_NATIVE_WIDGET ownership.";
}
+ // Destroy RootView after the native widget, so in case the WidgetDelegate is
+ // a View in the RootView hierarchy it gets destroyed as a WidgetDelegate
+ // first.
+ // This makes destruction order for WidgetDelegate consistent between
+ // different Widget/NativeWidget ownership models (WidgetDelegate is always
+ // deleted before here, which may have removed it as a View from the
+ // View hierarchy).
+ DestroyRootView();
}
// static
@@ -276,8 +287,26 @@ void Widget::ReparentNativeView(gfx::NativeView native_view,
Widget* child_widget = GetWidgetForNativeView(native_view);
Widget* parent_widget =
new_parent ? GetWidgetForNativeView(new_parent) : nullptr;
- if (child_widget)
+ if (child_widget) {
child_widget->parent_ = parent_widget;
+
+ // Release the paint-as-active lock on the old parent.
+ bool has_lock_on_parent = !!child_widget->parent_paint_as_active_lock_;
+ child_widget->parent_paint_as_active_lock_.reset();
+ child_widget->parent_paint_as_active_subscription_ =
+ base::CallbackListSubscription();
+
+ // Lock and subscribe to parent's paint-as-active.
+ if (parent_widget) {
+ if (has_lock_on_parent)
+ child_widget->parent_paint_as_active_lock_ =
+ parent_widget->LockPaintAsActive();
+ child_widget->parent_paint_as_active_subscription_ =
+ parent_widget->RegisterPaintAsActiveChangedCallback(
+ base::BindRepeating(&Widget::OnParentShouldPaintAsActiveChanged,
+ base::Unretained(child_widget)));
+ }
+ }
}
// static
@@ -321,6 +350,14 @@ void Widget::Init(InitParams params) {
parent_ = params.parent ? GetWidgetForNativeView(params.parent) : nullptr;
+ // Subscripbe to parent's paint-as-active change.
+ if (parent_) {
+ parent_paint_as_active_subscription_ =
+ parent_->RegisterPaintAsActiveChangedCallback(
+ base::BindRepeating(&Widget::OnParentShouldPaintAsActiveChanged,
+ base::Unretained(this)));
+ }
+
params.child |= (params.type == InitParams::TYPE_CONTROL);
is_top_level_ = !params.child;
@@ -425,10 +462,14 @@ void Widget::ShowEmojiPanel() {
// Unconverted methods (see header) --------------------------------------------
gfx::NativeView Widget::GetNativeView() const {
+ if (native_widget_destroyed_)
+ return gfx::kNullNativeView;
return native_widget_->GetNativeView();
}
gfx::NativeWindow Widget::GetNativeWindow() const {
+ if (native_widget_destroyed_)
+ return gfx::kNullNativeWindow;
return native_widget_->GetNativeWindow();
}
@@ -469,7 +510,8 @@ void Widget::ViewHierarchyChanged(const ViewHierarchyChangedDetails& details) {
FocusManager* focus_manager = GetFocusManager();
if (focus_manager)
focus_manager->ViewRemoved(details.child);
- native_widget_->ViewRemoved(details.child);
+ if (!native_widget_destroyed_)
+ native_widget_->ViewRemoved(details.child);
}
}
@@ -480,11 +522,11 @@ void Widget::NotifyNativeViewHierarchyWillChange() {
// to avoid these redundant steps and to avoid accessing deleted views
// that may have been in focus.
ClearFocusFromWidget();
- native_widget_->OnNativeViewHierarchyChanged();
+ native_widget_->OnNativeViewHierarchyWillChange();
}
void Widget::NotifyNativeViewHierarchyChanged() {
- native_widget_->OnNativeViewHierarchyWillChange();
+ native_widget_->OnNativeViewHierarchyChanged();
root_view_->NotifyNativeViewHierarchyChanged();
}
@@ -505,7 +547,10 @@ const Widget* Widget::GetTopLevelWidget() const {
// property is gone after gobject gets deleted. Short circuit here
// for toplevel so that InputMethod can remove itself from
// focus manager.
- return is_top_level() ? this : native_widget_->GetTopLevelWidget();
+ if (is_top_level())
+ return this;
+ return native_widget_destroyed_ ? nullptr
+ : native_widget_->GetTopLevelWidget();
}
Widget* Widget::GetPrimaryWindowWidget() {
@@ -769,12 +814,12 @@ bool Widget::IsMinimized() const {
return native_widget_->IsMinimized();
}
-void Widget::SetFullscreen(bool fullscreen) {
+void Widget::SetFullscreen(bool fullscreen, base::TimeDelta delay) {
if (IsFullscreen() == fullscreen)
return;
auto weak_ptr = GetWeakPtr();
- native_widget_->SetFullscreen(fullscreen);
+ native_widget_->SetFullscreen(fullscreen, delay);
if (!weak_ptr)
return;
@@ -826,15 +871,13 @@ const ui::ThemeProvider* Widget::GetThemeProvider() const {
const ui::ColorProvider* Widget::GetColorProvider() const {
auto color_scheme = GetNativeTheme()->GetDefaultSystemColorScheme();
- auto theme_name = GetNativeTheme()->GetNativeThemeName();
return ui::ColorProviderManager::Get().GetColorProviderFor(
{(color_scheme == ui::NativeTheme::ColorScheme::kDark)
? ui::ColorProviderManager::ColorMode::kDark
: ui::ColorProviderManager::ColorMode::kLight,
(color_scheme == ui::NativeTheme::ColorScheme::kPlatformHighContrast)
? ui::ColorProviderManager::ContrastMode::kHigh
- : ui::ColorProviderManager::ContrastMode::kNormal,
- std::move(theme_name)});
+ : ui::ColorProviderManager::ContrastMode::kNormal});
}
FocusManager* Widget::GetFocusManager() {
@@ -895,6 +938,11 @@ void Widget::RunShellDrag(View* view,
}
void Widget::SchedulePaintInRect(const gfx::Rect& rect) {
+ // This happens when DestroyRootView removes all children from the
+ // RootView which triggers a SchedulePaint that ends up here. This happens
+ // after in ~Widget after native_widget_ is destroyed.
+ if (native_widget_destroyed_)
+ return;
native_widget_->SchedulePaintInRect(rect);
}
@@ -935,8 +983,32 @@ void Widget::UpdateWindowTitle() {
void Widget::UpdateWindowIcon() {
if (non_client_view_)
non_client_view_->UpdateWindowIcon();
- native_widget_->SetWindowIcons(widget_delegate_->GetWindowIcon(),
- widget_delegate_->GetWindowAppIcon());
+
+ gfx::ImageSkia window_icon = GetImageSkiaFromImageModel(
+ widget_delegate_->GetWindowIcon(), GetNativeTheme());
+
+ // In general, icon information is read from a |widget_delegate_| and then
+ // passed to |native_widget_|. On ChromeOS, for lacros-chrome to support the
+ // initial window state as minimized state, a valid icon is added to
+ // |native_widget_| earlier stage of widget initialization. See
+ // https://crbug.com/1189981. As only lacros-chrome on ChromeOS supports this
+ // behavior other overrides of |native_widget_| will always have no icon
+ // information. This is also true for |app_icon| referred below.
+ if (window_icon.isNull()) {
+ const gfx::ImageSkia* icon = native_widget_->GetWindowIcon();
+ if (icon && !icon->isNull())
+ window_icon = *icon;
+ }
+
+ gfx::ImageSkia app_icon = GetImageSkiaFromImageModel(
+ widget_delegate_->GetWindowAppIcon(), GetNativeTheme());
+ if (app_icon.isNull()) {
+ const gfx::ImageSkia* icon = native_widget_->GetWindowAppIcon();
+ if (icon && !icon->isNull())
+ app_icon = *icon;
+ }
+
+ native_widget_->SetWindowIcons(window_icon, app_icon);
}
FocusTraversable* Widget::GetFocusTraversable() {
@@ -1009,14 +1081,20 @@ void Widget::FrameTypeChanged() {
}
const ui::Compositor* Widget::GetCompositor() const {
+ if (native_widget_destroyed_)
+ return nullptr;
return native_widget_->GetCompositor();
}
const ui::Layer* Widget::GetLayer() const {
+ if (native_widget_destroyed_)
+ return nullptr;
return native_widget_->GetLayer();
}
void Widget::ReorderNativeViews() {
+ if (native_widget_destroyed_)
+ return;
native_widget_->ReorderNativeViews();
}
@@ -1059,6 +1137,8 @@ bool Widget::HasCapture() {
}
TooltipManager* Widget::GetTooltipManager() {
+ if (native_widget_destroyed_)
+ return nullptr;
return native_widget_->GetTooltipManager();
}
@@ -1117,8 +1197,11 @@ base::CallbackListSubscription Widget::RegisterPaintAsActiveChangedCallback(
std::unique_ptr<Widget::PaintAsActiveLock> Widget::LockPaintAsActive() {
const bool was_paint_as_active = ShouldPaintAsActive();
++paint_as_active_refcount_;
- if (ShouldPaintAsActive() != was_paint_as_active)
+ if (ShouldPaintAsActive() != was_paint_as_active) {
paint_as_active_callbacks_.Notify();
+ if (parent() && !parent_paint_as_active_lock_)
+ parent_paint_as_active_lock_ = parent()->LockPaintAsActive();
+ }
return std::make_unique<PaintAsActiveLockImpl>(
weak_ptr_factory_.GetWeakPtr());
}
@@ -1128,7 +1211,32 @@ base::WeakPtr<Widget> Widget::GetWeakPtr() {
}
bool Widget::ShouldPaintAsActive() const {
- return native_widget_active_ || paint_as_active_refcount_;
+ // A transient bubble hits this code path when it loses focus.
+ // Return false after Close() is called.
+ if (widget_closed_)
+ return false;
+
+ return native_widget_active_ || paint_as_active_refcount_ ||
+ (parent() && parent()->ShouldPaintAsActive());
+}
+
+void Widget::OnParentShouldPaintAsActiveChanged() {
+ DCHECK(parent());
+ // |native_widget_| has already been deleted and |this| is being deleted so
+ // that we don't have to handle the event and also it's unsafe to reference
+ // |native_widget_| in this case.
+ if (native_widget_destroyed_)
+ return;
+
+ // |native_widget_active| is being updated in
+ // OnNativeWidgetActivationChanged(). Notification will be handled there.
+ if (native_widget_active_ != native_widget_->IsActive())
+ return;
+
+ // this->ShouldPaintAsActive() changes iff the native widget is
+ // inactive and there's no lock on this widget.
+ if (!(native_widget_active_ || paint_as_active_refcount_))
+ paint_as_active_callbacks_.Notify();
}
void Widget::SetNativeTheme(ui::NativeTheme* native_theme) {
@@ -1136,7 +1244,7 @@ void Widget::SetNativeTheme(ui::NativeTheme* native_theme) {
native_theme_observation_.Reset();
if (native_theme)
native_theme_observation_.Observe(native_theme);
- PropagateNativeThemeChanged();
+ ThemeChanged();
}
int Widget::GetX() const {
@@ -1239,7 +1347,18 @@ bool Widget::OnNativeWidgetActivationChanged(bool active) {
observer.OnWidgetActivationChanged(this, active);
const bool was_paint_as_active = ShouldPaintAsActive();
+
+ // Widgets in a widget tree should share the same ShouldPaintAsActive().
+ // Lock the parent as paint-as-active when this widget becomes active.
+ if (!active && !paint_as_active_refcount_)
+ parent_paint_as_active_lock_.reset();
+ else if (parent())
+ parent_paint_as_active_lock_ = parent()->LockPaintAsActive();
+
native_widget_active_ = active;
+
+ // Notify controls (e.g. LabelButton) and children widgets about the
+ // paint-as-active change.
if (ShouldPaintAsActive() != was_paint_as_active)
paint_as_active_callbacks_.Notify();
@@ -1254,11 +1373,6 @@ void Widget::OnNativeBlur() {
WidgetFocusManager::GetInstance()->OnNativeFocusChanged(nullptr);
}
-void Widget::OnNativeWidgetVisibilityChanging(bool visible) {
- for (WidgetObserver& observer : observers_)
- observer.OnWidgetVisibilityChanging(this, visible);
-}
-
void Widget::OnNativeWidgetVisibilityChanged(bool visible) {
View* root = GetRootView();
if (root)
@@ -1297,6 +1411,9 @@ void Widget::OnNativeWidgetDestroyed() {
widget_delegate_->can_delete_this_ = true;
widget_delegate_->DeleteDelegate();
widget_delegate_ = nullptr;
+ // TODO(pbos): Replace this with native_widget_ = nullptr; and nullptr
+ // checking. This currently breaks on reentrant calls to CloseNow() that I'm
+ // too scared to fix right now.
native_widget_destroyed_ = true;
}
@@ -1626,16 +1743,12 @@ View* Widget::GetFocusTraversableParentView() {
void Widget::OnNativeThemeUpdated(ui::NativeTheme* observed_theme) {
TRACE_EVENT0("ui", "Widget::OnNativeThemeUpdated");
- PropagateNativeThemeChanged();
+ ThemeChanged();
}
////////////////////////////////////////////////////////////////////////////////
// Widget, protected:
-void Widget::PropagateNativeThemeChanged() {
- root_view_->PropagateThemeChanged();
-}
-
internal::RootView* Widget::CreateRootView() {
return new internal::RootView(this);
}
@@ -1647,7 +1760,7 @@ void Widget::DestroyRootView() {
// Remove all children before the unique_ptr reset so that
// GetWidget()->GetRootView() doesn't return nullptr while the views hierarchy
// is being torn down.
- root_view_->RemoveAllChildViews(true);
+ root_view_->RemoveAllChildViews();
root_view_.reset();
}
@@ -1779,6 +1892,10 @@ void Widget::UnlockPaintAsActive() {
const bool was_paint_as_active = ShouldPaintAsActive();
DCHECK_GT(paint_as_active_refcount_, 0U);
--paint_as_active_refcount_;
+
+ if (!paint_as_active_refcount_ && !native_widget_active_)
+ parent_paint_as_active_lock_.reset();
+
if (ShouldPaintAsActive() != was_paint_as_active)
paint_as_active_callbacks_.Notify();
}
diff --git a/chromium/ui/views/widget/widget.h b/chromium/ui/views/widget/widget.h
index ef3892d66fa..6ab943e4b73 100644
--- a/chromium/ui/views/widget/widget.h
+++ b/chromium/ui/views/widget/widget.h
@@ -10,6 +10,7 @@
#include <string>
#include <vector>
+#include "base/callback_list.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
@@ -686,7 +687,11 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
bool IsMinimized() const;
// Accessors for fullscreen state.
- void SetFullscreen(bool fullscreen);
+ // If `delay` is given, some underlying implementations will set their target
+ // fullscreen state and then post a delayed task to request the actual window
+ // transition, in order to handle some platform-specific quirks in specific
+ // fullscreen scenarios. See crbug.com/1210548 and crbug.com/1034783.
+ void SetFullscreen(bool fullscreen, base::TimeDelta delay = {});
bool IsFullscreen() const;
// macOS: Sets whether the window can share fullscreen windows' spaces.
@@ -970,18 +975,25 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
// returned lock can safely outlive the associated widget.
std::unique_ptr<PaintAsActiveLock> LockPaintAsActive();
+ // Undoes LockPaintAsActive(). Called by PaintAsActiveLock destructor.
+ void UnlockPaintAsActive();
+
+ // Returns true if the window should paint as active.
+ bool ShouldPaintAsActive() const;
+
+ // Called when the ShouldPaintAsActive() of parent changes.
+ void OnParentShouldPaintAsActiveChanged();
+
base::WeakPtr<Widget> GetWeakPtr();
// Overridden from NativeWidgetDelegate:
bool IsModal() const override;
bool IsDialogBox() const override;
bool CanActivate() const override;
- bool ShouldPaintAsActive() const override;
bool IsNativeWidgetInitialized() const override;
bool OnNativeWidgetActivationChanged(bool active) override;
void OnNativeFocus() override;
void OnNativeBlur() override;
- void OnNativeWidgetVisibilityChanging(bool visible) override;
void OnNativeWidgetVisibilityChanged(bool visible) override;
void OnNativeWidgetCreated() override;
void OnNativeWidgetDestroying() override;
@@ -1032,10 +1044,6 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
}
protected:
- // Call this to propagate native theme changes to the root view. Subclasses
- // may override this to customize how native theme updates are propagated.
- virtual void PropagateNativeThemeChanged();
-
// Creates the RootView to be used within this Widget. Subclasses may override
// to create custom RootViews that do specialized event processing.
// TODO(beng): Investigate whether or not this is needed.
@@ -1122,9 +1130,6 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
// layer.
const View::Views& GetViewsWithLayers();
- // Undoes LockPaintAsActive(). Called by PaintAsActiveLock destructor.
- void UnlockPaintAsActive();
-
// If a descendent of |root_view_| is focused, then clear the focus.
void ClearFocusFromWidget();
@@ -1137,8 +1142,6 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
base::ObserverList<WidgetRemovalsObserver>::Unchecked removals_observers_;
- PaintAsActiveCallbackList paint_as_active_callbacks_;
-
// Non-owned pointer to the Widget's delegate. If a NULL delegate is supplied
// to Init() a default WidgetDelegate is created.
WidgetDelegate* widget_delegate_ = nullptr;
@@ -1182,9 +1185,19 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
// Tracks whether the native widget is active.
bool native_widget_active_ = false;
- // Tracks locks on the paint-as-active behavior. See LockPaintAsActive().
+ // Count of paint-as-active locks on this widget. See LockPaintAsActive().
size_t paint_as_active_refcount_ = 0;
+ // Callbacks to notify when the ShouldPaintAsActive() changes.
+ PaintAsActiveCallbackList paint_as_active_callbacks_;
+
+ // Lock on the parent widget when this widget is active.
+ // When this widget is destroyed, the lock is automatically released.
+ std::unique_ptr<PaintAsActiveLock> parent_paint_as_active_lock_;
+
+ // Subscription to parent's ShouldPaintAsActive() change.
+ base::CallbackListSubscription parent_paint_as_active_subscription_;
+
// Set to true if the widget is in the process of closing.
bool widget_closed_ = false;
diff --git a/chromium/ui/views/widget/widget_delegate.cc b/chromium/ui/views/widget/widget_delegate.cc
index b4fa10a853f..a25d32d5cef 100644
--- a/chromium/ui/views/widget/widget_delegate.cc
+++ b/chromium/ui/views/widget/widget_delegate.cc
@@ -12,6 +12,7 @@
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/base/models/image_model.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/gfx/image/image_skia.h"
@@ -48,8 +49,7 @@ WidgetDelegate::Params::Params() = default;
WidgetDelegate::Params::~Params() = default;
WidgetDelegate::WidgetDelegate()
- : widget_initializing_callbacks_(std::make_unique<ClosureVector>()),
- widget_initialized_callbacks_(std::make_unique<ClosureVector>()),
+ : widget_initialized_callbacks_(std::make_unique<ClosureVector>()),
client_view_factory_(
base::BindOnce(&CreateDefaultClientView, base::Unretained(this))),
non_client_frame_view_factory_(
@@ -143,17 +143,17 @@ bool WidgetDelegate::ShouldShowCloseButton() const {
return params_.show_close_button;
}
-gfx::ImageSkia WidgetDelegate::GetWindowAppIcon() {
+ui::ImageModel WidgetDelegate::GetWindowAppIcon() {
// Prefer app icon if available.
if (!params_.app_icon.isNull())
- return params_.app_icon;
+ return ui::ImageModel::FromImageSkia(params_.app_icon);
// Fall back to the window icon.
return GetWindowIcon();
}
// Returns the icon to be displayed in the window.
-gfx::ImageSkia WidgetDelegate::GetWindowIcon() {
- return params_.icon;
+ui::ImageModel WidgetDelegate::GetWindowIcon() {
+ return ui::ImageModel::FromImageSkia(params_.icon);
}
bool WidgetDelegate::ShouldShowWindowIcon() const {
@@ -194,10 +194,6 @@ bool WidgetDelegate::GetSavedWindowPlacement(
void WidgetDelegate::WidgetInitializing(Widget* widget) {
widget_ = widget;
- for (auto&& callback : *widget_initializing_callbacks_)
- std::move(callback).Run();
- widget_initializing_callbacks_.reset();
- OnWidgetInitializing();
}
void WidgetDelegate::WidgetInitialized() {
@@ -401,12 +397,6 @@ void WidgetDelegate::SetHasWindowSizeControls(bool has_controls) {
SetCanResize(has_controls);
}
-void WidgetDelegate::RegisterWidgetInitializingCallback(
- base::OnceClosure callback) {
- DCHECK(widget_initializing_callbacks_);
- widget_initializing_callbacks_->emplace_back(std::move(callback));
-}
-
void WidgetDelegate::RegisterWidgetInitializedCallback(
base::OnceClosure callback) {
DCHECK(widget_initialized_callbacks_);
@@ -443,13 +433,11 @@ void WidgetDelegate::SetOverlayViewFactory(OverlayViewFactory factory) {
overlay_view_factory_ = std::move(factory);
}
-void WidgetDelegate::SetContentsViewImpl(View* contents) {
- // Note: DCHECKing the ownership of contents is done in the public setters,
- // which are inlined in the header.
+void WidgetDelegate::SetContentsViewImpl(std::unique_ptr<View> contents) {
+ DCHECK(!contents->owned_by_client());
DCHECK(!unowned_contents_view_);
- if (!contents->owned_by_client())
- owned_contents_view_ = base::WrapUnique(contents);
- unowned_contents_view_ = contents;
+ owned_contents_view_ = std::move(contents);
+ unowned_contents_view_ = owned_contents_view_.get();
}
////////////////////////////////////////////////////////////////////////////////
@@ -457,7 +445,6 @@ void WidgetDelegate::SetContentsViewImpl(View* contents) {
WidgetDelegateView::WidgetDelegateView() {
// A WidgetDelegate should be deleted on DeleteDelegate.
- set_owned_by_client();
SetOwnedByWidget(true);
}
diff --git a/chromium/ui/views/widget/widget_delegate.h b/chromium/ui/views/widget/widget_delegate.h
index a53c8102301..16245ed7e0b 100644
--- a/chromium/ui/views/widget/widget_delegate.h
+++ b/chromium/ui/views/widget/widget_delegate.h
@@ -7,6 +7,7 @@
#include <memory>
#include <string>
+#include <utility>
#include <vector>
#include "base/macros.h"
@@ -22,6 +23,10 @@ class ImageSkia;
class Rect;
} // namespace gfx
+namespace ui {
+class ImageModel;
+} // namespace ui
+
namespace views {
class BubbleDialogDelegate;
class ClientView;
@@ -138,10 +143,6 @@ class VIEWS_EXPORT WidgetDelegate {
// 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() {}
@@ -163,7 +164,7 @@ class VIEWS_EXPORT WidgetDelegate {
virtual DialogDelegate* AsDialogDelegate();
// Returns true if the window can be resized.
- virtual bool CanResize() const;
+ bool CanResize() const;
// Returns true if the window can be maximized.
virtual bool CanMaximize() const;
@@ -194,10 +195,10 @@ class VIEWS_EXPORT WidgetDelegate {
// 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();
+ virtual ui::ImageModel GetWindowAppIcon();
// Returns the icon to be displayed in the window.
- virtual gfx::ImageSkia GetWindowIcon();
+ virtual ui::ImageModel GetWindowIcon();
// Returns true if a window icon should be shown.
bool ShouldShowWindowIcon() const;
@@ -242,11 +243,15 @@ class VIEWS_EXPORT WidgetDelegate {
// 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 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.
+ //
+ // WARNING: Use SetOwnedByWidget(true) and use delete-delegate callbacks to do
+ // pre-destruction cleanup instead of using self-deleting callbacks. The
+ // latter may become a DCHECK in the future.
+ void DeleteDelegate();
// Called when the user begins/ends to change the bounds of the window.
virtual void OnWindowBeginUserBoundsChange() {}
@@ -348,24 +353,15 @@ class VIEWS_EXPORT WidgetDelegate {
template <typename T>
T* SetContentsView(std::unique_ptr<T> contents) {
- DCHECK(!contents->owned_by_client());
T* raw_contents = contents.get();
- SetContentsViewImpl(contents.release());
+ SetContentsViewImpl(std::move(contents));
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);
@@ -402,7 +398,7 @@ class VIEWS_EXPORT WidgetDelegate {
friend class Widget;
- void SetContentsViewImpl(View* contents);
+ void SetContentsViewImpl(std::unique_ptr<View> contents);
// The Widget that was initialized with this instance as its WidgetDelegate,
// if any.
@@ -423,10 +419,9 @@ class VIEWS_EXPORT WidgetDelegate {
// WidgetDelegate if the client has given ownership to the Widget.
bool* destructor_ran_ = nullptr;
- // The first two are stored as unique_ptrs to make it easier to check in the
+ // 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_initializing_callbacks_;
std::unique_ptr<ClosureVector> widget_initialized_callbacks_;
ClosureVector window_will_close_callbacks_;
ClosureVector window_closing_callbacks_;
diff --git a/chromium/ui/views/widget/widget_delegate_unittest.cc b/chromium/ui/views/widget/widget_delegate_unittest.cc
index 80209ee9d0a..3b9cc7b73e2 100644
--- a/chromium/ui/views/widget/widget_delegate_unittest.cc
+++ b/chromium/ui/views/widget/widget_delegate_unittest.cc
@@ -7,8 +7,10 @@
#include <utility>
#include "base/test/bind.h"
+#include "ui/base/models/image_model.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/image/image_unittest_util.h"
+#include "ui/views/image_model_utils.h"
#include "ui/views/test/views_test_base.h"
#include "ui/views/view.h"
#include "ui/views/view_tracker.h"
@@ -18,20 +20,6 @@ namespace {
using WidgetDelegateTest = views::ViewsTestBase;
-TEST_F(WidgetDelegateTest, ClientOwnedContentsViewOwnershipNotHeld) {
- std::unique_ptr<View> view = std::make_unique<View>();
- view->set_owned_by_client();
- ViewTracker tracker(view.get());
-
- auto delegate = std::make_unique<WidgetDelegate>();
- delegate->SetContentsView(view.get());
- delegate.reset();
-
- ASSERT_TRUE(tracker.view());
- view.reset();
- EXPECT_FALSE(tracker.view());
-}
-
TEST_F(WidgetDelegateTest, ContentsViewOwnershipHeld) {
std::unique_ptr<View> view = std::make_unique<View>();
ViewTracker tracker(view.get());
@@ -122,8 +110,10 @@ TEST_F(WidgetDelegateTest, AppIconCanDifferFromWindowIcon) {
delegate->SetIcon(window_icon);
gfx::ImageSkia app_icon = gfx::test::CreateImageSkia(48, 48);
delegate->SetAppIcon(app_icon);
- EXPECT_TRUE(delegate->GetWindowIcon().BackedBySameObjectAs(window_icon));
- EXPECT_TRUE(delegate->GetWindowAppIcon().BackedBySameObjectAs(app_icon));
+ EXPECT_TRUE(GetImageSkiaFromImageModel(delegate->GetWindowIcon(), nullptr)
+ .BackedBySameObjectAs(window_icon));
+ EXPECT_TRUE(GetImageSkiaFromImageModel(delegate->GetWindowAppIcon(), nullptr)
+ .BackedBySameObjectAs(app_icon));
}
TEST_F(WidgetDelegateTest, AppIconFallsBackToWindowIcon) {
@@ -132,7 +122,8 @@ TEST_F(WidgetDelegateTest, AppIconFallsBackToWindowIcon) {
gfx::ImageSkia window_icon = gfx::test::CreateImageSkia(16, 16);
delegate->SetIcon(window_icon);
// Don't set an independent app icon.
- EXPECT_TRUE(delegate->GetWindowAppIcon().BackedBySameObjectAs(window_icon));
+ EXPECT_TRUE(GetImageSkiaFromImageModel(delegate->GetWindowAppIcon(), nullptr)
+ .BackedBySameObjectAs(window_icon));
}
} // namespace
diff --git a/chromium/ui/views/widget/widget_hwnd_utils.cc b/chromium/ui/views/widget/widget_hwnd_utils.cc
index e07a1291859..c23259757d9 100644
--- a/chromium/ui/views/widget/widget_hwnd_utils.cc
+++ b/chromium/ui/views/widget/widget_hwnd_utils.cc
@@ -109,8 +109,7 @@ void CalculateWindowStylesFromInitParams(
break;
case Widget::InitParams::TYPE_MENU:
*style |= WS_POPUP;
- if (::features::IsFormControlsRefreshEnabled() &&
- params.remove_standard_frame) {
+ if (params.remove_standard_frame) {
// If the platform doesn't support drop shadow, decorate the Window
// with just a border.
if (ui::win::IsAeroGlassEnabled())
diff --git a/chromium/ui/views/widget/widget_interactive_uitest.cc b/chromium/ui/views/widget/widget_interactive_uitest.cc
index c9480f71a98..7c91221838f 100644
--- a/chromium/ui/views/widget/widget_interactive_uitest.cc
+++ b/chromium/ui/views/widget/widget_interactive_uitest.cc
@@ -533,7 +533,13 @@ TEST_F(WidgetTestInteractive, ViewFocusOnWidgetActivationChanges) {
}
// Test z-order of child widgets relative to their parent.
-TEST_F(WidgetTestInteractive, ChildStackedRelativeToParent) {
+// TODO(crbug.com/1227009): Disabled on Mac due to flake
+#if defined(OS_MAC)
+#define MAYBE_ChildStackedRelativeToParent DISABLED_ChildStackedRelativeToParent
+#else
+#define MAYBE_ChildStackedRelativeToParent ChildStackedRelativeToParent
+#endif
+TEST_F(WidgetTestInteractive, MAYBE_ChildStackedRelativeToParent) {
WidgetAutoclosePtr parent(CreateTopLevelPlatformWidget());
Widget* child = CreateChildPlatformWidget(parent->GetNativeView());
@@ -1040,6 +1046,19 @@ TEST_F(WidgetTestInteractive, ShowAfterShowInactive) {
EXPECT_EQ(GetWidgetShowState(widget.get()), ui::SHOW_STATE_NORMAL);
}
+TEST_F(WidgetTestInteractive, WidgetShouldBeActiveWhenShow) {
+ // TODO(crbug/1217331): This test fails if put under NativeWidgetAuraTest.
+ WidgetAutoclosePtr anchor_widget(CreateTopLevelNativeWidget());
+
+ test::WidgetActivationWaiter waiter(anchor_widget.get(), true);
+ anchor_widget->Show();
+ waiter.Wait();
+ EXPECT_TRUE(anchor_widget->IsActive());
+#if !defined(OS_MAC)
+ EXPECT_TRUE(anchor_widget->GetNativeWindow()->HasFocus());
+#endif
+}
+
#if BUILDFLAG(ENABLE_DESKTOP_AURA) || defined(OS_MAC)
TEST_F(WidgetTestInteractive, InactiveWidgetDoesNotGrabActivation) {
WidgetAutoclosePtr widget(CreateTopLevelPlatformWidget());
diff --git a/chromium/ui/views/widget/widget_observer.h b/chromium/ui/views/widget/widget_observer.h
index 4050dd33db5..32a27d0e034 100644
--- a/chromium/ui/views/widget/widget_observer.h
+++ b/chromium/ui/views/widget/widget_observer.h
@@ -41,7 +41,6 @@ class VIEWS_EXPORT WidgetObserver : public base::CheckedObserver {
virtual void OnWidgetDragWillStart(Widget* widget) {}
virtual void OnWidgetDragComplete(Widget* widget) {}
- virtual void OnWidgetVisibilityChanging(Widget* widget, bool visible) {}
virtual void OnWidgetVisibilityChanged(Widget* widget, bool visible) {}
virtual void OnWidgetActivationChanged(Widget* widget, bool active) {}
diff --git a/chromium/ui/views/widget/widget_unittest.cc b/chromium/ui/views/widget/widget_unittest.cc
index 8b107c8a08d..32fffc05f1b 100644
--- a/chromium/ui/views/widget/widget_unittest.cc
+++ b/chromium/ui/views/widget/widget_unittest.cc
@@ -30,6 +30,7 @@
#include "ui/views/controls/textfield/textfield.h"
#include "ui/views/event_monitor.h"
#include "ui/views/layout/fill_layout.h"
+#include "ui/views/style/platform_style.h"
#include "ui/views/test/native_widget_factory.h"
#include "ui/views/test/test_views.h"
#include "ui/views/test/test_widget_observer.h"
@@ -69,6 +70,7 @@
#if defined(USE_OZONE)
#include "ui/base/ui_base_features.h"
#include "ui/ozone/public/ozone_platform.h"
+#include "ui/ozone/public/platform_gl_egl_utility.h"
#endif
namespace views {
@@ -753,6 +755,9 @@ TEST_F(WidgetOwnsNativeWidgetTest, WidgetDelegateView) {
using WidgetWithDestroyedNativeViewTest = ViewsTestBaseWithNativeWidgetType;
TEST_P(WidgetWithDestroyedNativeViewTest, Test) {
+ // TODO(pbos): Add a version of this that tests with params that use
+ // NATIVE_WIDGET_OWNS_WIDGET. A lot of these implementations look like they
+ // call `native_widget_->` which should be illegal after CloseNow().
std::unique_ptr<Widget> widget = CreateTestWidget();
widget->Show();
@@ -2099,6 +2104,90 @@ TEST_F(WidgetTest, LockPaintAsActive_BecomesActive) {
EXPECT_TRUE(widget->ShouldPaintAsActive());
}
+class PaintAsActiveCallbackCounter {
+ public:
+ explicit PaintAsActiveCallbackCounter(Widget* widget) {
+ // Subscribe to |widget|'s paint-as-active change.
+ paint_as_active_subscription_ =
+ widget->RegisterPaintAsActiveChangedCallback(base::BindRepeating(
+ &PaintAsActiveCallbackCounter::Call, base::Unretained(this)));
+ }
+ void Call() { count_++; }
+ int CallCount() { return count_; }
+
+ private:
+ int count_ = 0;
+ base::CallbackListSubscription paint_as_active_subscription_;
+};
+
+TEST_F(WidgetTest, LockParentPaintAsActive) {
+ if (!PlatformStyle::kInactiveWidgetControlsAppearDisabled)
+ return;
+
+ WidgetAutoclosePtr parent(CreateTopLevelPlatformWidget());
+ WidgetAutoclosePtr child(CreateChildPlatformWidget(parent->GetNativeView()));
+ WidgetAutoclosePtr grandchild(
+ CreateChildPlatformWidget(child->GetNativeView()));
+ WidgetAutoclosePtr other(CreateTopLevelPlatformWidget());
+ child->widget_delegate()->SetCanActivate(true);
+ grandchild->widget_delegate()->SetCanActivate(true);
+
+ PaintAsActiveCallbackCounter parent_control(parent.get());
+ PaintAsActiveCallbackCounter child_control(child.get());
+ PaintAsActiveCallbackCounter grandchild_control(grandchild.get());
+ PaintAsActiveCallbackCounter other_control(other.get());
+
+ parent->Show();
+ EXPECT_TRUE(parent->ShouldPaintAsActive());
+ EXPECT_TRUE(child->ShouldPaintAsActive());
+ EXPECT_TRUE(grandchild->ShouldPaintAsActive());
+ EXPECT_FALSE(other->ShouldPaintAsActive());
+ EXPECT_EQ(parent_control.CallCount(), 1);
+ EXPECT_EQ(child_control.CallCount(), 1);
+ EXPECT_EQ(grandchild_control.CallCount(), 1);
+ EXPECT_EQ(other_control.CallCount(), 0);
+
+ other->Show();
+ EXPECT_FALSE(parent->ShouldPaintAsActive());
+ EXPECT_FALSE(child->ShouldPaintAsActive());
+ EXPECT_FALSE(grandchild->ShouldPaintAsActive());
+ EXPECT_TRUE(other->ShouldPaintAsActive());
+ EXPECT_EQ(parent_control.CallCount(), 2);
+ EXPECT_EQ(child_control.CallCount(), 2);
+ EXPECT_EQ(grandchild_control.CallCount(), 2);
+ EXPECT_EQ(other_control.CallCount(), 1);
+
+ child->Show();
+ EXPECT_TRUE(parent->ShouldPaintAsActive());
+ EXPECT_TRUE(child->ShouldPaintAsActive());
+ EXPECT_TRUE(grandchild->ShouldPaintAsActive());
+ EXPECT_FALSE(other->ShouldPaintAsActive());
+ EXPECT_EQ(parent_control.CallCount(), 3);
+ EXPECT_EQ(child_control.CallCount(), 3);
+ EXPECT_EQ(grandchild_control.CallCount(), 3);
+ EXPECT_EQ(other_control.CallCount(), 2);
+
+ other->Show();
+ EXPECT_FALSE(parent->ShouldPaintAsActive());
+ EXPECT_FALSE(child->ShouldPaintAsActive());
+ EXPECT_FALSE(grandchild->ShouldPaintAsActive());
+ EXPECT_TRUE(other->ShouldPaintAsActive());
+ EXPECT_EQ(parent_control.CallCount(), 4);
+ EXPECT_EQ(child_control.CallCount(), 4);
+ EXPECT_EQ(grandchild_control.CallCount(), 4);
+ EXPECT_EQ(other_control.CallCount(), 3);
+
+ grandchild->Show();
+ EXPECT_TRUE(parent->ShouldPaintAsActive());
+ EXPECT_TRUE(child->ShouldPaintAsActive());
+ EXPECT_TRUE(grandchild->ShouldPaintAsActive());
+ EXPECT_FALSE(other->ShouldPaintAsActive());
+ EXPECT_EQ(parent_control.CallCount(), 5);
+ EXPECT_EQ(child_control.CallCount(), 5);
+ EXPECT_EQ(grandchild_control.CallCount(), 5);
+ EXPECT_EQ(other_control.CallCount(), 4);
+}
+
// Widget used to destroy itself when OnNativeWidgetDestroyed is called.
class TestNativeWidgetDestroyedWidget : public Widget {
public:
@@ -4049,9 +4138,9 @@ namespace {
bool CanHaveCompositingManager() {
#if defined(USE_OZONE)
if (features::IsUsingOzonePlatform()) {
- const auto* const egl_utility =
+ auto* const egl_utility =
ui::OzonePlatform::GetInstance()->GetPlatformGLEGLUtility();
- return egl_utility != nullptr;
+ return (egl_utility != nullptr) && egl_utility->HasVisualManager();
}
#endif
#if defined(USE_X11)
diff --git a/chromium/ui/views/widget/window_reorderer.cc b/chromium/ui/views/widget/window_reorderer.cc
index 0992ed1828c..cb5b0ac2393 100644
--- a/chromium/ui/views/widget/window_reorderer.cc
+++ b/chromium/ui/views/widget/window_reorderer.cc
@@ -56,7 +56,7 @@ void GetOrderOfViewsWithLayers(
order->push_back(view);
}
- for (views::View* child : view->children())
+ for (views::View* child : view->GetChildrenInZOrder())
GetOrderOfViewsWithLayers(child, parent_layer, hosts, order);
}