| // Copyright 2014 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "ui/views/test/widget_test.h" |
| |
| #include <Cocoa/Cocoa.h> |
| |
| #import "base/apple/scoped_objc_class_swizzler.h" |
| #import "components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h" |
| #import "ui/base/test/windowed_nsnotification_observer.h" |
| #include "ui/gfx/native_ui_types.h" |
| #include "ui/views/cocoa/native_widget_mac_ns_window_host.h" |
| #include "ui/views/widget/native_widget_mac.h" |
| #include "ui/views/widget/root_view.h" |
| |
| namespace views::test { |
| |
| namespace { |
| |
| // The NSWindow last activated by SimulateNativeActivate(). It will have a |
| // simulated deactivate on a subsequent call. |
| NSWindow* g_simulated_active_window_ = nil; |
| |
| } // namespace |
| |
| // static |
| void WidgetTest::SimulateNativeActivate(Widget* widget) { |
| NSNotificationCenter* center = NSNotificationCenter.defaultCenter; |
| if (g_simulated_active_window_) { |
| [center postNotificationName:NSWindowDidResignKeyNotification |
| object:g_simulated_active_window_]; |
| } |
| |
| g_simulated_active_window_ = widget->GetNativeWindow().GetNativeNSWindow(); |
| DCHECK(g_simulated_active_window_); |
| |
| // For now, don't simulate main status or windows that can't activate. |
| DCHECK(g_simulated_active_window_.canBecomeKeyWindow); |
| [center postNotificationName:NSWindowDidBecomeKeyNotification |
| object:g_simulated_active_window_]; |
| } |
| |
| // static |
| bool WidgetTest::IsNativeWindowVisible(gfx::NativeWindow window) { |
| return window.GetNativeNSWindow().visible; |
| } |
| |
| // static |
| bool WidgetTest::IsWindowStackedAbove(Widget* above, Widget* below) { |
| // Since 10.13, a trip to the runloop has been necessary to ensure [NSApp |
| // orderedWindows] has been updated. |
| base::RunLoop().RunUntilIdle(); |
| |
| EXPECT_TRUE(above->IsVisible()); |
| EXPECT_TRUE(below->IsVisible()); |
| |
| // -[NSApplication orderedWindows] are ordered front-to-back. |
| NSWindow* first = above->GetNativeWindow().GetNativeNSWindow(); |
| NSWindow* second = below->GetNativeWindow().GetNativeNSWindow(); |
| |
| for (NSWindow* window in NSApp.orderedWindows) { |
| if (window == second) { |
| return !first; |
| } |
| |
| if (window == first) { |
| first = nil; |
| } |
| } |
| return false; |
| } |
| |
| gfx::Size WidgetTest::GetNativeWidgetMinimumContentSize(Widget* widget) { |
| return gfx::Size( |
| widget->GetNativeWindow().GetNativeNSWindow().contentMinSize); |
| } |
| |
| // static |
| ui::EventSink* WidgetTest::GetEventSink(Widget* widget) { |
| return static_cast<internal::RootView*>(widget->GetRootView()); |
| } |
| |
| // static |
| ui::ImeKeyEventDispatcher* WidgetTest::GetImeKeyEventDispatcherForWidget( |
| Widget* widget) { |
| return NativeWidgetMacNSWindowHost::GetFromNativeWindow( |
| widget->GetNativeWindow()) |
| ->native_widget_mac(); |
| } |
| |
| // static |
| bool WidgetTest::IsNativeWindowTransparent(gfx::NativeWindow window) { |
| return !window.GetNativeNSWindow().opaque; |
| } |
| |
| // static |
| bool WidgetTest::WidgetHasInProcessShadow(Widget* widget) { |
| return false; |
| } |
| |
| // static |
| Widget::Widgets WidgetTest::GetAllWidgets() { |
| Widget::Widgets all_widgets; |
| for (NSWindow* window : [NSApp windows]) { |
| if (Widget* widget = |
| Widget::GetWidgetForNativeWindow(gfx::NativeWindow(window))) { |
| all_widgets.insert(widget); |
| } |
| } |
| return all_widgets; |
| } |
| |
| // static |
| void WidgetTest::WaitForSystemAppActivation() { |
| // This seems to be only necessary on 10.15+ but it's obscure why. Shortly |
| // after launching an app, the system sends ApplicationDidFinishLaunching |
| // (which is normal), which causes AppKit on 10.15 to try to find a window to |
| // activate. If it finds one it will makeKeyAndOrderFront: it, which breaks |
| // tests that are deliberately creating inactive windows. |
| WindowedNSNotificationObserver* observer = |
| [[WindowedNSNotificationObserver alloc] |
| initForNotification:NSApplicationDidFinishLaunchingNotification |
| object:NSApp]; |
| [observer wait]; |
| } |
| |
| } // namespace views::test |