1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <stddef.h>
6 
7 #include <memory>
8 #include <utility>
9 
10 #include "base/bind.h"
11 #include "base/callback.h"
12 #include "base/command_line.h"
13 #include "base/location.h"
14 #include "base/macros.h"
15 #include "base/run_loop.h"
16 #include "base/single_thread_task_runner.h"
17 #include "base/strings/stringprintf.h"
18 #include "base/strings/utf_string_conversions.h"
19 #include "base/threading/thread_task_runner_handle.h"
20 #include "base/timer/timer.h"
21 #include "base/win/windows_version.h"
22 #include "build/build_config.h"
23 #include "ui/base/ime/input_method.h"
24 #include "ui/base/ime/text_input_client.h"
25 #include "ui/base/resource/resource_bundle.h"
26 #include "ui/base/test/ui_controls.h"
27 #include "ui/base/ui_base_features.h"
28 #include "ui/base/ui_base_switches.h"
29 #include "ui/events/event_processor.h"
30 #include "ui/events/event_utils.h"
31 #include "ui/events/test/event_generator.h"
32 #include "ui/gfx/native_widget_types.h"
33 #include "ui/views/bubble/bubble_dialog_delegate_view.h"
34 #include "ui/views/controls/textfield/textfield.h"
35 #include "ui/views/controls/textfield/textfield_test_api.h"
36 #include "ui/views/focus/focus_manager.h"
37 #include "ui/views/test/focus_manager_test.h"
38 #include "ui/views/test/native_widget_factory.h"
39 #include "ui/views/test/widget_test.h"
40 #include "ui/views/touchui/touch_selection_controller_impl.h"
41 #include "ui/views/widget/root_view.h"
42 #include "ui/views/widget/widget.h"
43 #include "ui/views/widget/widget_utils.h"
44 #include "ui/views/window/dialog_delegate.h"
45 #include "ui/wm/public/activation_client.h"
46 
47 #if defined(OS_WIN)
48 #include "ui/aura/window.h"
49 #include "ui/aura/window_tree_host.h"
50 #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
51 #include "ui/views/win/hwnd_util.h"
52 #endif
53 
54 namespace views {
55 namespace test {
56 
57 namespace {
58 
59 // A View that closes the Widget and exits the current message-loop when it
60 // receives a mouse-release event.
61 class ExitLoopOnRelease : public View {
62  public:
ExitLoopOnRelease(base::OnceClosure quit_closure)63   explicit ExitLoopOnRelease(base::OnceClosure quit_closure)
64       : quit_closure_(std::move(quit_closure)) {
65     DCHECK(quit_closure_);
66   }
67 
68   ~ExitLoopOnRelease() override = default;
69 
70  private:
71   // View:
OnMouseReleased(const ui::MouseEvent & event)72   void OnMouseReleased(const ui::MouseEvent& event) override {
73     GetWidget()->Close();
74     std::move(quit_closure_).Run();
75   }
76 
77   base::OnceClosure quit_closure_;
78 
79   DISALLOW_COPY_AND_ASSIGN(ExitLoopOnRelease);
80 };
81 
82 // A view that does a capture on ui::ET_GESTURE_TAP_DOWN events.
83 class GestureCaptureView : public View {
84  public:
85   GestureCaptureView() = default;
86   ~GestureCaptureView() override = default;
87 
88  private:
89   // View:
OnGestureEvent(ui::GestureEvent * event)90   void OnGestureEvent(ui::GestureEvent* event) override {
91     if (event->type() == ui::ET_GESTURE_TAP_DOWN) {
92       GetWidget()->SetCapture(this);
93       event->StopPropagation();
94     }
95   }
96 
97   DISALLOW_COPY_AND_ASSIGN(GestureCaptureView);
98 };
99 
100 // A view that always processes all mouse events.
101 class MouseView : public View {
102  public:
103   MouseView() = default;
104   ~MouseView() override = default;
105 
OnMousePressed(const ui::MouseEvent & event)106   bool OnMousePressed(const ui::MouseEvent& event) override {
107     pressed_++;
108     return true;
109   }
110 
OnMouseEntered(const ui::MouseEvent & event)111   void OnMouseEntered(const ui::MouseEvent& event) override { entered_++; }
112 
OnMouseExited(const ui::MouseEvent & event)113   void OnMouseExited(const ui::MouseEvent& event) override { exited_++; }
114 
115   // Return the number of OnMouseEntered calls and reset the counter.
EnteredCalls()116   int EnteredCalls() {
117     int i = entered_;
118     entered_ = 0;
119     return i;
120   }
121 
122   // Return the number of OnMouseExited calls and reset the counter.
ExitedCalls()123   int ExitedCalls() {
124     int i = exited_;
125     exited_ = 0;
126     return i;
127   }
128 
pressed() const129   int pressed() const { return pressed_; }
130 
131  private:
132   int entered_ = 0;
133   int exited_ = 0;
134 
135   int pressed_ = 0;
136 
137   DISALLOW_COPY_AND_ASSIGN(MouseView);
138 };
139 
140 // A View that shows a different widget, sets capture on that widget, and
141 // initiates a nested message-loop when it receives a mouse-press event.
142 class NestedLoopCaptureView : public View {
143  public:
NestedLoopCaptureView(Widget * widget)144   explicit NestedLoopCaptureView(Widget* widget)
145       : run_loop_(base::RunLoop::Type::kNestableTasksAllowed),
146         widget_(widget) {}
147   ~NestedLoopCaptureView() override = default;
148 
GetQuitClosure()149   base::OnceClosure GetQuitClosure() { return run_loop_.QuitClosure(); }
150 
151  private:
152   // View:
OnMousePressed(const ui::MouseEvent & event)153   bool OnMousePressed(const ui::MouseEvent& event) override {
154     // Start a nested loop.
155     widget_->Show();
156     widget_->SetCapture(widget_->GetContentsView());
157     EXPECT_TRUE(widget_->HasCapture());
158 
159     run_loop_.Run();
160     return true;
161   }
162 
163   base::RunLoop run_loop_;
164 
165   Widget* widget_;
166 
167   DISALLOW_COPY_AND_ASSIGN(NestedLoopCaptureView);
168 };
169 
GetWidgetShowState(const Widget * widget)170 ui::WindowShowState GetWidgetShowState(const Widget* widget) {
171   // Use IsMaximized/IsMinimized/IsFullScreen instead of GetWindowPlacement
172   // because the former is implemented on all platforms but the latter is not.
173   if (widget->IsFullscreen())
174     return ui::SHOW_STATE_FULLSCREEN;
175   if (widget->IsMaximized())
176     return ui::SHOW_STATE_MAXIMIZED;
177   if (widget->IsMinimized())
178     return ui::SHOW_STATE_MINIMIZED;
179   return widget->IsActive() ? ui::SHOW_STATE_NORMAL : ui::SHOW_STATE_INACTIVE;
180 }
181 
182 // Give the OS an opportunity to process messages for an activation change, when
183 // there is actually no change expected (e.g. ShowInactive()).
RunPendingMessagesForActiveStatusChange()184 void RunPendingMessagesForActiveStatusChange() {
185 #if defined(OS_APPLE)
186   // On Mac, a single spin is *usually* enough. It isn't when a widget is shown
187   // and made active in two steps, so tests should follow up with a ShowSync()
188   // or ActivateSync to ensure a consistent state.
189   base::RunLoop().RunUntilIdle();
190 #endif
191   // TODO(tapted): Check for desktop aura widgets.
192 }
193 
194 // Activate a widget, and wait for it to become active. On non-desktop Aura
195 // this is just an activation. For other widgets, it means activating and then
196 // spinning the run loop until the OS has activated the window.
ActivateSync(Widget * widget)197 void ActivateSync(Widget* widget) {
198   views::test::WidgetActivationWaiter waiter(widget, true);
199   widget->Activate();
200   waiter.Wait();
201 }
202 
203 // Like for ActivateSync(), wait for a widget to become active, but Show() the
204 // widget rather than calling Activate().
ShowSync(Widget * widget)205 void ShowSync(Widget* widget) {
206   views::test::WidgetActivationWaiter waiter(widget, true);
207   widget->Show();
208   waiter.Wait();
209 }
210 
DeactivateSync(Widget * widget)211 void DeactivateSync(Widget* widget) {
212 #if defined(OS_APPLE)
213   // Deactivation of a window isn't a concept on Mac: If an application is
214   // active and it has any activatable windows, then one of them is always
215   // active. But we can simulate deactivation (e.g. as if another application
216   // became active) by temporarily making |widget| non-activatable, then
217   // activating (and closing) a temporary widget.
218   widget->widget_delegate()->SetCanActivate(false);
219   Widget* stealer = new Widget;
220   stealer->Init(Widget::InitParams(Widget::InitParams::TYPE_WINDOW));
221   ShowSync(stealer);
222   stealer->CloseNow();
223   widget->widget_delegate()->SetCanActivate(true);
224 #else
225   views::test::WidgetActivationWaiter waiter(widget, false);
226   widget->Deactivate();
227   waiter.Wait();
228 #endif
229 }
230 
231 #if defined(OS_WIN)
ActivatePlatformWindow(Widget * widget)232 void ActivatePlatformWindow(Widget* widget) {
233   ::SetActiveWindow(
234       widget->GetNativeWindow()->GetHost()->GetAcceleratedWidget());
235 }
236 #endif
237 
238 // Calls ShowInactive() on a Widget, and spins a run loop. The goal is to give
239 // the OS a chance to activate a widget. However, for this case, the test
240 // doesn't expect that to happen, so there is nothing to wait for.
ShowInactiveSync(Widget * widget)241 void ShowInactiveSync(Widget* widget) {
242   widget->ShowInactive();
243   RunPendingMessagesForActiveStatusChange();
244 }
245 
246 // Wait until |callback| returns |expected_value|, but no longer than 1 second.
247 class PropertyWaiter {
248  public:
PropertyWaiter(base::RepeatingCallback<bool (void)> callback,bool expected_value)249   PropertyWaiter(base::RepeatingCallback<bool(void)> callback,
250                  bool expected_value)
251       : callback_(std::move(callback)), expected_value_(expected_value) {}
252 
Wait()253   bool Wait() {
254     if (callback_.Run() == expected_value_) {
255       success_ = true;
256       return success_;
257     }
258     start_time_ = base::TimeTicks::Now();
259     timer_.Start(FROM_HERE, base::TimeDelta(), this, &PropertyWaiter::Check);
260     run_loop_.Run();
261     return success_;
262   }
263 
264  private:
Check()265   void Check() {
266     DCHECK(!success_);
267     success_ = callback_.Run() == expected_value_;
268     if (success_ || base::TimeTicks::Now() - start_time_ > kTimeout) {
269       timer_.Stop();
270       run_loop_.Quit();
271     }
272   }
273 
274   const base::TimeDelta kTimeout = base::TimeDelta::FromSeconds(1);
275   base::RepeatingCallback<bool(void)> callback_;
276   const bool expected_value_;
277   bool success_ = false;
278   base::TimeTicks start_time_;
279   base::RunLoop run_loop_;
280   base::RepeatingTimer timer_;
281 };
282 
283 }  // namespace
284 
285 class WidgetTestInteractive : public WidgetTest {
286  public:
287   WidgetTestInteractive() = default;
288   ~WidgetTestInteractive() override = default;
289 
SetUp()290   void SetUp() override {
291     SetUpForInteractiveTests();
292     WidgetTest::SetUp();
293   }
294 };
295 
296 #if defined(OS_WIN)
297 // Tests whether activation and focus change works correctly in Windows.
298 // We test the following:-
299 // 1. If the active aura window is correctly set when a top level widget is
300 //    created.
301 // 2. If the active aura window in widget 1 created above, is set to NULL when
302 //    another top level widget is created and focused.
303 // 3. On focusing the native platform window for widget 1, the active aura
304 //    window for widget 1 should be set and that for widget 2 should reset.
305 // TODO(ananta): Discuss with erg on how to write this test for linux x11 aura.
TEST_F(DesktopWidgetTestInteractive,DesktopNativeWidgetAuraActivationAndFocusTest)306 TEST_F(DesktopWidgetTestInteractive,
307        DesktopNativeWidgetAuraActivationAndFocusTest) {
308   // Create widget 1 and expect the active window to be its window.
309   View* focusable_view1 = new View;
310   focusable_view1->SetFocusBehavior(View::FocusBehavior::ALWAYS);
311   WidgetAutoclosePtr widget1(CreateTopLevelNativeWidget());
312   widget1->GetContentsView()->AddChildView(focusable_view1);
313   widget1->Show();
314   aura::Window* root_window1 = GetRootWindow(widget1.get());
315   focusable_view1->RequestFocus();
316 
317   EXPECT_TRUE(root_window1 != nullptr);
318   wm::ActivationClient* activation_client1 =
319       wm::GetActivationClient(root_window1);
320   EXPECT_TRUE(activation_client1 != nullptr);
321   EXPECT_EQ(activation_client1->GetActiveWindow(), widget1->GetNativeView());
322 
323   // Create widget 2 and expect the active window to be its window.
324   View* focusable_view2 = new View;
325   WidgetAutoclosePtr widget2(CreateTopLevelNativeWidget());
326   widget1->GetContentsView()->AddChildView(focusable_view2);
327   widget2->Show();
328   aura::Window* root_window2 = GetRootWindow(widget2.get());
329   focusable_view2->RequestFocus();
330   ActivatePlatformWindow(widget2.get());
331 
332   wm::ActivationClient* activation_client2 =
333       wm::GetActivationClient(root_window2);
334   EXPECT_TRUE(activation_client2 != nullptr);
335   EXPECT_EQ(activation_client2->GetActiveWindow(), widget2->GetNativeView());
336   EXPECT_EQ(activation_client1->GetActiveWindow(),
337             reinterpret_cast<aura::Window*>(NULL));
338 
339   // Now set focus back to widget 1 and expect the active window to be its
340   // window.
341   focusable_view1->RequestFocus();
342   ActivatePlatformWindow(widget1.get());
343   EXPECT_EQ(activation_client2->GetActiveWindow(),
344             reinterpret_cast<aura::Window*>(NULL));
345   EXPECT_EQ(activation_client1->GetActiveWindow(), widget1->GetNativeView());
346 }
347 
348 // Verifies bubbles result in a focus lost when shown.
TEST_F(DesktopWidgetTestInteractive,FocusChangesOnBubble)349 TEST_F(DesktopWidgetTestInteractive, FocusChangesOnBubble) {
350   WidgetAutoclosePtr widget(CreateTopLevelNativeWidget());
351   View* focusable_view =
352       widget->GetContentsView()->AddChildView(std::make_unique<View>());
353   focusable_view->SetFocusBehavior(View::FocusBehavior::ALWAYS);
354   widget->Show();
355   focusable_view->RequestFocus();
356   EXPECT_TRUE(focusable_view->HasFocus());
357 
358   // Show a bubble.
359   auto owned_bubble_delegate_view =
360       std::make_unique<views::BubbleDialogDelegateView>(focusable_view,
361                                                         BubbleBorder::NONE);
362   owned_bubble_delegate_view->SetFocusBehavior(View::FocusBehavior::ALWAYS);
363   BubbleDialogDelegateView* bubble_delegate_view =
364       owned_bubble_delegate_view.get();
365   BubbleDialogDelegateView::CreateBubble(std::move(owned_bubble_delegate_view))
366       ->Show();
367   bubble_delegate_view->RequestFocus();
368 
369   // |focusable_view| should no longer have focus.
370   EXPECT_FALSE(focusable_view->HasFocus());
371   EXPECT_TRUE(bubble_delegate_view->HasFocus());
372 
373   bubble_delegate_view->GetWidget()->CloseNow();
374 
375   // Closing the bubble should result in focus going back to the contents view.
376   EXPECT_TRUE(focusable_view->HasFocus());
377 }
378 
379 class TouchEventHandler : public ui::EventHandler {
380  public:
TouchEventHandler(Widget * widget)381   explicit TouchEventHandler(Widget* widget) : widget_(widget) {
382     widget_->GetNativeWindow()->GetHost()->window()->AddPreTargetHandler(this);
383   }
384 
~TouchEventHandler()385   ~TouchEventHandler() override {
386     widget_->GetNativeWindow()->GetHost()->window()->RemovePreTargetHandler(
387         this);
388   }
389 
WaitForEvents()390   void WaitForEvents() {
391     base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);
392     quit_closure_ = run_loop.QuitClosure();
393     run_loop.Run();
394   }
395 
AsyncActivateMouse(HWND hwnd,UINT msg,ULONG_PTR data,LRESULT result)396   static void __stdcall AsyncActivateMouse(HWND hwnd,
397                                            UINT msg,
398                                            ULONG_PTR data,
399                                            LRESULT result) {
400     EXPECT_EQ(MA_NOACTIVATE, result);
401     std::move(reinterpret_cast<TouchEventHandler*>(data)->quit_closure_).Run();
402   }
403 
ActivateViaMouse()404   void ActivateViaMouse() {
405     SendMessageCallback(
406         widget_->GetNativeWindow()->GetHost()->GetAcceleratedWidget(),
407         WM_MOUSEACTIVATE, 0, 0, AsyncActivateMouse,
408         reinterpret_cast<ULONG_PTR>(this));
409   }
410 
411  private:
412   // ui::EventHandler:
OnTouchEvent(ui::TouchEvent * event)413   void OnTouchEvent(ui::TouchEvent* event) override {
414     if (event->type() == ui::ET_TOUCH_PRESSED)
415       ActivateViaMouse();
416   }
417 
418   Widget* widget_;
419   base::OnceClosure quit_closure_;
420   DISALLOW_COPY_AND_ASSIGN(TouchEventHandler);
421 };
422 
423 // TODO(dtapuska): Disabled due to it being flaky crbug.com/817531
TEST_F(DesktopWidgetTestInteractive,DISABLED_TouchNoActivateWindow)424 TEST_F(DesktopWidgetTestInteractive, DISABLED_TouchNoActivateWindow) {
425   // ui_controls::SendTouchEvents which uses InjectTouchInput API only works
426   // on Windows 8 and up.
427   if (base::win::GetVersion() <= base::win::Version::WIN7)
428     return;
429 
430   View* focusable_view = new View;
431   focusable_view->SetFocusBehavior(View::FocusBehavior::ALWAYS);
432   WidgetAutoclosePtr widget(CreateTopLevelNativeWidget());
433   widget->GetContentsView()->AddChildView(focusable_view);
434   widget->Show();
435 
436   {
437     TouchEventHandler touch_event_handler(widget.get());
438     ASSERT_TRUE(ui_controls::SendTouchEvents(ui_controls::PRESS, 1, 100, 100));
439     touch_event_handler.WaitForEvents();
440   }
441 }
442 
443 #endif  // defined(OS_WIN)
444 
445 // Tests mouse move outside of the window into the "resize controller" and back
446 // will still generate an OnMouseEntered and OnMouseExited event..
TEST_F(WidgetTestInteractive,CheckResizeControllerEvents)447 TEST_F(WidgetTestInteractive, CheckResizeControllerEvents) {
448   WidgetAutoclosePtr toplevel(CreateTopLevelFramelessPlatformWidget());
449 
450   toplevel->SetBounds(gfx::Rect(0, 0, 100, 100));
451 
452   MouseView* view = new MouseView();
453   view->SetBounds(90, 90, 10, 10);
454   // |view| needs to be a particular size. Reset the LayoutManager so that
455   // it doesn't get resized.
456   toplevel->GetRootView()->SetLayoutManager(nullptr);
457   toplevel->GetRootView()->AddChildView(view);
458 
459   toplevel->Show();
460   RunPendingMessages();
461 
462   // Move to an outside position.
463   gfx::Point p1(200, 200);
464   ui::MouseEvent moved_out(ui::ET_MOUSE_MOVED, p1, p1, ui::EventTimeForNow(),
465                            ui::EF_NONE, ui::EF_NONE);
466   toplevel->OnMouseEvent(&moved_out);
467   EXPECT_EQ(0, view->EnteredCalls());
468   EXPECT_EQ(0, view->ExitedCalls());
469 
470   // Move onto the active view.
471   gfx::Point p2(95, 95);
472   ui::MouseEvent moved_over(ui::ET_MOUSE_MOVED, p2, p2, ui::EventTimeForNow(),
473                             ui::EF_NONE, ui::EF_NONE);
474   toplevel->OnMouseEvent(&moved_over);
475   EXPECT_EQ(1, view->EnteredCalls());
476   EXPECT_EQ(0, view->ExitedCalls());
477 
478   // Move onto the outer resizing border.
479   gfx::Point p3(102, 95);
480   ui::MouseEvent moved_resizer(ui::ET_MOUSE_MOVED, p3, p3,
481                                ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE);
482   toplevel->OnMouseEvent(&moved_resizer);
483   EXPECT_EQ(0, view->EnteredCalls());
484   EXPECT_EQ(1, view->ExitedCalls());
485 
486   // Move onto the view again.
487   toplevel->OnMouseEvent(&moved_over);
488   EXPECT_EQ(1, view->EnteredCalls());
489   EXPECT_EQ(0, view->ExitedCalls());
490 }
491 
492 // Test view focus restoration when a widget is deactivated and re-activated.
TEST_F(WidgetTestInteractive,ViewFocusOnWidgetActivationChanges)493 TEST_F(WidgetTestInteractive, ViewFocusOnWidgetActivationChanges) {
494   WidgetAutoclosePtr widget1(CreateTopLevelPlatformWidget());
495   View* view1 = new View;
496   view1->SetFocusBehavior(View::FocusBehavior::ALWAYS);
497   widget1->GetContentsView()->AddChildView(view1);
498 
499   WidgetAutoclosePtr widget2(CreateTopLevelPlatformWidget());
500   View* view2a = new View;
501   View* view2b = new View;
502   view2a->SetFocusBehavior(View::FocusBehavior::ALWAYS);
503   view2b->SetFocusBehavior(View::FocusBehavior::ALWAYS);
504   widget2->GetContentsView()->AddChildView(view2a);
505   widget2->GetContentsView()->AddChildView(view2b);
506 
507   ShowSync(widget1.get());
508   EXPECT_TRUE(widget1->IsActive());
509   view1->RequestFocus();
510   EXPECT_EQ(view1, widget1->GetFocusManager()->GetFocusedView());
511 
512   ShowSync(widget2.get());
513   EXPECT_TRUE(widget2->IsActive());
514   EXPECT_FALSE(widget1->IsActive());
515   EXPECT_EQ(nullptr, widget1->GetFocusManager()->GetFocusedView());
516   view2a->RequestFocus();
517   EXPECT_EQ(view2a, widget2->GetFocusManager()->GetFocusedView());
518   view2b->RequestFocus();
519   EXPECT_EQ(view2b, widget2->GetFocusManager()->GetFocusedView());
520 
521   ActivateSync(widget1.get());
522   EXPECT_TRUE(widget1->IsActive());
523   EXPECT_EQ(view1, widget1->GetFocusManager()->GetFocusedView());
524   EXPECT_FALSE(widget2->IsActive());
525   EXPECT_EQ(nullptr, widget2->GetFocusManager()->GetFocusedView());
526 
527   ActivateSync(widget2.get());
528   EXPECT_TRUE(widget2->IsActive());
529   EXPECT_EQ(view2b, widget2->GetFocusManager()->GetFocusedView());
530   EXPECT_FALSE(widget1->IsActive());
531   EXPECT_EQ(nullptr, widget1->GetFocusManager()->GetFocusedView());
532 }
533 
534 // Test z-order of child widgets relative to their parent.
TEST_F(WidgetTestInteractive,ChildStackedRelativeToParent)535 TEST_F(WidgetTestInteractive, ChildStackedRelativeToParent) {
536   WidgetAutoclosePtr parent(CreateTopLevelPlatformWidget());
537   Widget* child = CreateChildPlatformWidget(parent->GetNativeView());
538 
539   parent->SetBounds(gfx::Rect(160, 100, 320, 200));
540   child->SetBounds(gfx::Rect(50, 50, 30, 20));
541 
542   // Child shown first. Initially not visible, but on top of parent when shown.
543   // Use ShowInactive whenever showing the child, otherwise the usual activation
544   // logic will just put it on top anyway. Here, we want to ensure it is on top
545   // of its parent regardless.
546   child->ShowInactive();
547   EXPECT_FALSE(child->IsVisible());
548 
549   ShowSync(parent.get());
550   EXPECT_TRUE(child->IsVisible());
551   EXPECT_TRUE(IsWindowStackedAbove(child, parent.get()));
552   EXPECT_FALSE(IsWindowStackedAbove(parent.get(), child));  // Sanity check.
553 
554   WidgetAutoclosePtr popover(CreateTopLevelPlatformWidget());
555   popover->SetBounds(gfx::Rect(150, 90, 340, 240));
556   ShowSync(popover.get());
557 
558   // NOTE: for aura-mus-client stacking of top-levels is not maintained in the
559   // client, so z-order of top-levels can't be determined.
560   EXPECT_TRUE(IsWindowStackedAbove(popover.get(), child));
561   EXPECT_TRUE(IsWindowStackedAbove(child, parent.get()));
562 
563   // Showing the parent again should raise it and its child above the popover.
564   ShowSync(parent.get());
565   EXPECT_TRUE(IsWindowStackedAbove(child, parent.get()));
566   EXPECT_TRUE(IsWindowStackedAbove(parent.get(), popover.get()));
567 
568   // Test grandchildren.
569   Widget* grandchild = CreateChildPlatformWidget(child->GetNativeView());
570   grandchild->SetBounds(gfx::Rect(5, 5, 15, 10));
571   grandchild->ShowInactive();
572   EXPECT_TRUE(IsWindowStackedAbove(grandchild, child));
573   EXPECT_TRUE(IsWindowStackedAbove(child, parent.get()));
574   EXPECT_TRUE(IsWindowStackedAbove(parent.get(), popover.get()));
575 
576   ShowSync(popover.get());
577   EXPECT_TRUE(IsWindowStackedAbove(popover.get(), grandchild));
578   EXPECT_TRUE(IsWindowStackedAbove(grandchild, child));
579 
580   ShowSync(parent.get());
581   EXPECT_TRUE(IsWindowStackedAbove(grandchild, child));
582   EXPECT_TRUE(IsWindowStackedAbove(child, popover.get()));
583 
584   // Test hiding and reshowing.
585   parent->Hide();
586   EXPECT_FALSE(grandchild->IsVisible());
587   ShowSync(parent.get());
588 
589   EXPECT_TRUE(IsWindowStackedAbove(grandchild, child));
590   EXPECT_TRUE(IsWindowStackedAbove(child, parent.get()));
591   EXPECT_TRUE(IsWindowStackedAbove(parent.get(), popover.get()));
592 
593   grandchild->Hide();
594   EXPECT_FALSE(grandchild->IsVisible());
595   grandchild->ShowInactive();
596 
597   EXPECT_TRUE(IsWindowStackedAbove(grandchild, child));
598   EXPECT_TRUE(IsWindowStackedAbove(child, parent.get()));
599   EXPECT_TRUE(IsWindowStackedAbove(parent.get(), popover.get()));
600 }
601 
602 #if defined(OS_WIN)
603 
604 // Test view focus retention when a widget's HWND is disabled and re-enabled.
TEST_F(WidgetTestInteractive,ViewFocusOnHWNDEnabledChanges)605 TEST_F(WidgetTestInteractive, ViewFocusOnHWNDEnabledChanges) {
606   WidgetAutoclosePtr widget(CreateTopLevelFramelessPlatformWidget());
607   widget->SetContentsView(std::make_unique<View>());
608   for (size_t i = 0; i < 2; ++i) {
609     auto child = std::make_unique<View>();
610     child->SetFocusBehavior(View::FocusBehavior::ALWAYS);
611     widget->GetContentsView()->AddChildView(std::move(child));
612   }
613 
614   widget->Show();
615   widget->GetNativeWindow()->GetHost()->Show();
616   const HWND hwnd = HWNDForWidget(widget.get());
617   EXPECT_TRUE(::IsWindow(hwnd));
618   EXPECT_TRUE(::IsWindowEnabled(hwnd));
619   EXPECT_EQ(hwnd, ::GetActiveWindow());
620 
621   for (View* view : widget->GetContentsView()->children()) {
622     SCOPED_TRACE(base::StringPrintf(
623         "Child view %d", widget->GetContentsView()->GetIndexOf(view)));
624 
625     view->RequestFocus();
626     EXPECT_EQ(view, widget->GetFocusManager()->GetFocusedView());
627     EXPECT_FALSE(::EnableWindow(hwnd, FALSE));
628     EXPECT_FALSE(::IsWindowEnabled(hwnd));
629 
630     // Oddly, disabling the HWND leaves it active with the focus unchanged.
631     EXPECT_EQ(hwnd, ::GetActiveWindow());
632     EXPECT_TRUE(widget->IsActive());
633     EXPECT_EQ(view, widget->GetFocusManager()->GetFocusedView());
634 
635     EXPECT_TRUE(::EnableWindow(hwnd, TRUE));
636     EXPECT_TRUE(::IsWindowEnabled(hwnd));
637     EXPECT_EQ(hwnd, ::GetActiveWindow());
638     EXPECT_TRUE(widget->IsActive());
639     EXPECT_EQ(view, widget->GetFocusManager()->GetFocusedView());
640   }
641 }
642 
643 // This class subclasses the Widget class to listen for activation change
644 // notifications and provides accessors to return information as to whether
645 // the widget is active. We need this to ensure that users of the widget
646 // class activate the widget only when the underlying window becomes really
647 // active. Previously we would activate the widget in the WM_NCACTIVATE
648 // message which is incorrect because APIs like FlashWindowEx flash the
649 // window caption by sending fake WM_NCACTIVATE messages.
650 class WidgetActivationTest : public Widget {
651  public:
652   WidgetActivationTest() = default;
653 
654   ~WidgetActivationTest() override = default;
655 
OnNativeWidgetActivationChanged(bool active)656   bool OnNativeWidgetActivationChanged(bool active) override {
657     active_ = active;
658     return true;
659   }
660 
active() const661   bool active() const { return active_; }
662 
663  private:
664   bool active_ = false;
665 
666   DISALLOW_COPY_AND_ASSIGN(WidgetActivationTest);
667 };
668 
669 // Tests whether the widget only becomes active when the underlying window
670 // is really active.
TEST_F(WidgetTestInteractive,WidgetNotActivatedOnFakeActivationMessages)671 TEST_F(WidgetTestInteractive, WidgetNotActivatedOnFakeActivationMessages) {
672   WidgetActivationTest widget1;
673   Widget::InitParams init_params =
674       CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
675   init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
676   init_params.native_widget = new DesktopNativeWidgetAura(&widget1);
677   init_params.bounds = gfx::Rect(0, 0, 200, 200);
678   widget1.Init(std::move(init_params));
679   widget1.Show();
680   EXPECT_EQ(true, widget1.active());
681 
682   WidgetActivationTest widget2;
683   init_params.native_widget = new DesktopNativeWidgetAura(&widget2);
684   widget2.Init(std::move(init_params));
685   widget2.Show();
686   EXPECT_EQ(true, widget2.active());
687   EXPECT_EQ(false, widget1.active());
688 
689   HWND win32_native_window1 = HWNDForWidget(&widget1);
690   EXPECT_TRUE(::IsWindow(win32_native_window1));
691 
692   ::SendMessage(win32_native_window1, WM_NCACTIVATE, 1, 0);
693   EXPECT_EQ(false, widget1.active());
694   EXPECT_EQ(true, widget2.active());
695 
696   ::SetActiveWindow(win32_native_window1);
697   EXPECT_EQ(true, widget1.active());
698   EXPECT_EQ(false, widget2.active());
699 }
700 
701 // On Windows if we create a fullscreen window on a thread, then it affects the
702 // way other windows on the thread interact with the taskbar. To workaround
703 // this we reduce the bounds of a fullscreen window by 1px when it loses
704 // activation. This test verifies the same.
TEST_F(WidgetTestInteractive,FullscreenBoundsReducedOnActivationLoss)705 TEST_F(WidgetTestInteractive, FullscreenBoundsReducedOnActivationLoss) {
706   Widget widget1;
707   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
708   params.native_widget = new DesktopNativeWidgetAura(&widget1);
709   params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
710   widget1.Init(std::move(params));
711   widget1.SetBounds(gfx::Rect(0, 0, 200, 200));
712   widget1.Show();
713 
714   widget1.Activate();
715   RunPendingMessages();
716   EXPECT_EQ(::GetActiveWindow(),
717             widget1.GetNativeWindow()->GetHost()->GetAcceleratedWidget());
718 
719   widget1.SetFullscreen(true);
720   EXPECT_TRUE(widget1.IsFullscreen());
721   // Ensure that the StopIgnoringPosChanges task in HWNDMessageHandler runs.
722   // This task is queued when a widget becomes fullscreen.
723   RunPendingMessages();
724   EXPECT_EQ(::GetActiveWindow(),
725             widget1.GetNativeWindow()->GetHost()->GetAcceleratedWidget());
726   gfx::Rect fullscreen_bounds = widget1.GetWindowBoundsInScreen();
727 
728   Widget widget2;
729   params.native_widget = new DesktopNativeWidgetAura(&widget2);
730   params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
731   widget2.Init(std::move(params));
732   widget2.SetBounds(gfx::Rect(0, 0, 200, 200));
733   widget2.Show();
734 
735   widget2.Activate();
736   RunPendingMessages();
737   EXPECT_EQ(::GetActiveWindow(),
738             widget2.GetNativeWindow()->GetHost()->GetAcceleratedWidget());
739 
740   gfx::Rect fullscreen_bounds_after_activation_loss =
741       widget1.GetWindowBoundsInScreen();
742 
743   // After deactivation loss the bounds of the fullscreen widget should be
744   // reduced by 1px.
745   EXPECT_EQ(fullscreen_bounds.height() -
746                 fullscreen_bounds_after_activation_loss.height(),
747             1);
748 
749   widget1.Activate();
750   RunPendingMessages();
751   EXPECT_EQ(::GetActiveWindow(),
752             widget1.GetNativeWindow()->GetHost()->GetAcceleratedWidget());
753 
754   gfx::Rect fullscreen_bounds_after_activate =
755       widget1.GetWindowBoundsInScreen();
756 
757   // After activation the bounds of the fullscreen widget should be restored.
758   EXPECT_EQ(fullscreen_bounds, fullscreen_bounds_after_activate);
759 
760   widget1.CloseNow();
761   widget2.CloseNow();
762 }
763 
764 // Ensure the window rect and client rects are correct with a window that was
765 // maximized.
TEST_F(WidgetTestInteractive,FullscreenMaximizedWindowBounds)766 TEST_F(WidgetTestInteractive, FullscreenMaximizedWindowBounds) {
767   Widget widget;
768   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
769   params.native_widget = new DesktopNativeWidgetAura(&widget);
770   params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
771   widget.set_frame_type(Widget::FrameType::kForceCustom);
772   widget.Init(std::move(params));
773   widget.SetBounds(gfx::Rect(0, 0, 200, 200));
774   widget.Show();
775 
776   widget.Maximize();
777   EXPECT_TRUE(widget.IsMaximized());
778 
779   widget.SetFullscreen(true);
780   EXPECT_TRUE(widget.IsFullscreen());
781   EXPECT_FALSE(widget.IsMaximized());
782   // Ensure that the StopIgnoringPosChanges task in HWNDMessageHandler runs.
783   // This task is queued when a widget becomes fullscreen.
784   RunPendingMessages();
785 
786   aura::WindowTreeHost* host = widget.GetNativeWindow()->GetHost();
787   HWND hwnd = host->GetAcceleratedWidget();
788 
789   HMONITOR monitor = ::MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
790   ASSERT_TRUE(!!monitor);
791   MONITORINFO monitor_info;
792   monitor_info.cbSize = sizeof(monitor_info);
793   ASSERT_TRUE(::GetMonitorInfo(monitor, &monitor_info));
794 
795   gfx::Rect monitor_bounds(monitor_info.rcMonitor);
796   gfx::Rect window_bounds = widget.GetWindowBoundsInScreen();
797   gfx::Rect client_area_bounds = host->GetBoundsInPixels();
798 
799   EXPECT_EQ(window_bounds, monitor_bounds);
800   EXPECT_EQ(monitor_bounds, client_area_bounds);
801 
802   // Setting not fullscreen should return it to maximized.
803   widget.SetFullscreen(false);
804   EXPECT_FALSE(widget.IsFullscreen());
805   EXPECT_TRUE(widget.IsMaximized());
806 
807   client_area_bounds = host->GetBoundsInPixels();
808   EXPECT_TRUE(monitor_bounds.Contains(client_area_bounds));
809   EXPECT_NE(monitor_bounds, client_area_bounds);
810 
811   widget.CloseNow();
812 }
813 #endif  // defined(OS_WIN)
814 
815 #if BUILDFLAG(ENABLE_DESKTOP_AURA) || defined(OS_APPLE)
816 // Tests whether the focused window is set correctly when a modal window is
817 // created and destroyed. When it is destroyed it should focus the owner window.
TEST_F(DesktopWidgetTestInteractive,WindowModalWindowDestroyedActivationTest)818 TEST_F(DesktopWidgetTestInteractive, WindowModalWindowDestroyedActivationTest) {
819   TestWidgetFocusChangeListener focus_listener;
820   WidgetFocusManager::GetInstance()->AddFocusChangeListener(&focus_listener);
821   const std::vector<gfx::NativeView>& focus_changes =
822       focus_listener.focus_changes();
823 
824   // Create a top level widget.
825   Widget top_level_widget;
826   Widget::InitParams init_params =
827       CreateParams(Widget::InitParams::TYPE_WINDOW);
828   init_params.show_state = ui::SHOW_STATE_NORMAL;
829   gfx::Rect initial_bounds(0, 0, 500, 500);
830   init_params.bounds = initial_bounds;
831   init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
832   top_level_widget.Init(std::move(init_params));
833   ShowSync(&top_level_widget);
834 
835   gfx::NativeView top_level_native_view = top_level_widget.GetNativeView();
836   ASSERT_FALSE(focus_listener.focus_changes().empty());
837   EXPECT_EQ(1u, focus_changes.size());
838   EXPECT_EQ(top_level_native_view, focus_changes[0]);
839 
840   // Create a modal dialog.
841   auto dialog_delegate = std::make_unique<DialogDelegateView>();
842   dialog_delegate->SetModalType(ui::MODAL_TYPE_WINDOW);
843 
844   Widget* modal_dialog_widget = views::DialogDelegate::CreateDialogWidget(
845       dialog_delegate.release(), nullptr, top_level_widget.GetNativeView());
846   modal_dialog_widget->SetBounds(gfx::Rect(100, 100, 200, 200));
847 
848   // Note the dialog widget doesn't need a ShowSync. Since it is modal, it gains
849   // active status synchronously, even on Mac.
850   modal_dialog_widget->Show();
851 
852   gfx::NativeView modal_native_view = modal_dialog_widget->GetNativeView();
853   ASSERT_EQ(3u, focus_changes.size());
854   EXPECT_EQ(gfx::kNullNativeView, focus_changes[1]);
855   EXPECT_EQ(modal_native_view, focus_changes[2]);
856 
857 #if defined(OS_APPLE)
858   // Window modal dialogs on Mac are "sheets", which animate to close before
859   // activating their parent widget.
860   views::test::WidgetActivationWaiter waiter(&top_level_widget, true);
861   modal_dialog_widget->Close();
862   waiter.Wait();
863 #else
864   modal_dialog_widget->CloseNow();
865 #endif
866 
867   ASSERT_EQ(5u, focus_changes.size());
868   EXPECT_EQ(gfx::kNullNativeView, focus_changes[3]);
869   EXPECT_EQ(top_level_native_view, focus_changes[4]);
870 
871   top_level_widget.CloseNow();
872   WidgetFocusManager::GetInstance()->RemoveFocusChangeListener(&focus_listener);
873 }
874 #endif
875 
TEST_F(DesktopWidgetTestInteractive,CanActivateFlagIsHonored)876 TEST_F(DesktopWidgetTestInteractive, CanActivateFlagIsHonored) {
877   Widget widget;
878   Widget::InitParams init_params =
879       CreateParams(Widget::InitParams::TYPE_WINDOW);
880   init_params.bounds = gfx::Rect(0, 0, 200, 200);
881   init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
882   init_params.activatable = Widget::InitParams::ACTIVATABLE_NO;
883   widget.Init(std::move(init_params));
884 
885   widget.Show();
886   EXPECT_FALSE(widget.IsActive());
887 }
888 
889 #if defined(USE_AURA)
890 
891 #if defined(OS_CHROMEOS)
892 // TODO(crbug.com/916272): investigate fixing and enabling on Chrome OS.
893 #define MAYBE_TouchSelectionQuickMenuIsNotActivated \
894   DISABLED_TouchSelectionQuickMenuIsNotActivated
895 #else
896 #define MAYBE_TouchSelectionQuickMenuIsNotActivated \
897   TouchSelectionQuickMenuIsNotActivated
898 #endif
899 
900 // Test that touch selection quick menu is not activated when opened.
TEST_F(DesktopWidgetTestInteractive,MAYBE_TouchSelectionQuickMenuIsNotActivated)901 TEST_F(DesktopWidgetTestInteractive,
902        MAYBE_TouchSelectionQuickMenuIsNotActivated) {
903   WidgetAutoclosePtr widget(CreateTopLevelNativeWidget());
904   widget->SetBounds(gfx::Rect(0, 0, 200, 200));
905 
906   Textfield* textfield = new Textfield;
907   textfield->SetBounds(0, 0, 200, 20);
908   textfield->SetText(base::ASCIIToUTF16("some text"));
909   widget->GetRootView()->AddChildView(textfield);
910 
911   widget->Show();
912   textfield->RequestFocus();
913   textfield->SelectAll(true);
914   TextfieldTestApi textfield_test_api(textfield);
915 
916   RunPendingMessages();
917 
918   ui::test::EventGenerator generator(GetRootWindow(widget.get()));
919   generator.GestureTapAt(textfield->GetBoundsInScreen().origin() +
920                          gfx::Vector2d(10, 10));
921   static_cast<TouchSelectionControllerImpl*>(
922       textfield_test_api.touch_selection_controller())
923       ->ShowQuickMenuImmediatelyForTesting();
924 
925   EXPECT_TRUE(textfield->HasFocus());
926   EXPECT_TRUE(widget->IsActive());
927   EXPECT_TRUE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning());
928 }
929 #endif  // defined(USE_AURA)
930 
931 #if defined(OS_WIN)
TEST_F(DesktopWidgetTestInteractive,DisableViewDoesNotActivateWidget)932 TEST_F(DesktopWidgetTestInteractive, DisableViewDoesNotActivateWidget) {
933 #else
934 TEST_F(WidgetTestInteractive, DisableViewDoesNotActivateWidget) {
935 #endif  // !defined(OS_WIN)
936 
937   // Create first widget and view, activate the widget, and focus the view.
938   Widget widget1;
939   Widget::InitParams params1 = CreateParams(Widget::InitParams::TYPE_POPUP);
940   params1.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
941   params1.activatable = Widget::InitParams::ACTIVATABLE_YES;
942   widget1.Init(std::move(params1));
943 
944   View* view1 = new View();
945   view1->SetFocusBehavior(View::FocusBehavior::ALWAYS);
946   widget1.GetRootView()->AddChildView(view1);
947 
948   widget1.Show();
949   ActivateSync(&widget1);
950 
951   FocusManager* focus_manager1 = widget1.GetFocusManager();
952   ASSERT_TRUE(focus_manager1);
953   focus_manager1->SetFocusedView(view1);
954   EXPECT_EQ(view1, focus_manager1->GetFocusedView());
955 
956   // Create second widget and view, activate the widget, and focus the view.
957   Widget widget2;
958   Widget::InitParams params2 = CreateParams(Widget::InitParams::TYPE_POPUP);
959   params2.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
960   params2.activatable = Widget::InitParams::ACTIVATABLE_YES;
961   widget2.Init(std::move(params2));
962 
963   View* view2 = new View();
964   view2->SetFocusBehavior(View::FocusBehavior::ALWAYS);
965   widget2.GetRootView()->AddChildView(view2);
966 
967   widget2.Show();
968   ActivateSync(&widget2);
969   EXPECT_TRUE(widget2.IsActive());
970   EXPECT_FALSE(widget1.IsActive());
971 
972   FocusManager* focus_manager2 = widget2.GetFocusManager();
973   ASSERT_TRUE(focus_manager2);
974   focus_manager2->SetFocusedView(view2);
975   EXPECT_EQ(view2, focus_manager2->GetFocusedView());
976 
977   // Disable the first view and make sure it loses focus, but its widget is not
978   // activated.
979   view1->SetEnabled(false);
980   EXPECT_NE(view1, focus_manager1->GetFocusedView());
981   EXPECT_FALSE(widget1.IsActive());
982   EXPECT_TRUE(widget2.IsActive());
983 }  // namespace test
984 
985 TEST_F(WidgetTestInteractive, ShowCreatesActiveWindow) {
986   WidgetAutoclosePtr widget(CreateTopLevelPlatformWidget());
987 
988   ShowSync(widget.get());
989   EXPECT_EQ(GetWidgetShowState(widget.get()), ui::SHOW_STATE_NORMAL);
990 }
991 
992 TEST_F(WidgetTestInteractive, ShowInactive) {
993   WidgetTest::WaitForSystemAppActivation();
994   WidgetAutoclosePtr widget(CreateTopLevelPlatformWidget());
995 
996   ShowInactiveSync(widget.get());
997   EXPECT_EQ(GetWidgetShowState(widget.get()), ui::SHOW_STATE_INACTIVE);
998 }
999 
1000 TEST_F(WidgetTestInteractive, InactiveBeforeShow) {
1001   WidgetAutoclosePtr widget(CreateTopLevelPlatformWidget());
1002 
1003   EXPECT_FALSE(widget->IsActive());
1004   EXPECT_FALSE(widget->IsVisible());
1005 
1006   ShowSync(widget.get());
1007 
1008   EXPECT_TRUE(widget->IsActive());
1009   EXPECT_TRUE(widget->IsVisible());
1010 }
1011 
1012 TEST_F(WidgetTestInteractive, ShowInactiveAfterShow) {
1013   // Create 2 widgets to ensure window layering does not change.
1014   WidgetAutoclosePtr widget(CreateTopLevelPlatformWidget());
1015   WidgetAutoclosePtr widget2(CreateTopLevelPlatformWidget());
1016 
1017   ShowSync(widget2.get());
1018   EXPECT_FALSE(widget->IsActive());
1019   EXPECT_TRUE(widget2->IsVisible());
1020   EXPECT_TRUE(widget2->IsActive());
1021 
1022   ShowSync(widget.get());
1023   EXPECT_TRUE(widget->IsActive());
1024   EXPECT_FALSE(widget2->IsActive());
1025 
1026   ShowInactiveSync(widget.get());
1027   EXPECT_TRUE(widget->IsActive());
1028   EXPECT_FALSE(widget2->IsActive());
1029   EXPECT_EQ(GetWidgetShowState(widget.get()), ui::SHOW_STATE_NORMAL);
1030 }
1031 
1032 TEST_F(WidgetTestInteractive, ShowAfterShowInactive) {
1033   WidgetAutoclosePtr widget(CreateTopLevelPlatformWidget());
1034   widget->SetBounds(gfx::Rect(100, 100, 100, 100));
1035 
1036   ShowInactiveSync(widget.get());
1037   ShowSync(widget.get());
1038   EXPECT_EQ(GetWidgetShowState(widget.get()), ui::SHOW_STATE_NORMAL);
1039 }
1040 
1041 #if BUILDFLAG(ENABLE_DESKTOP_AURA) || defined(OS_APPLE)
1042 TEST_F(WidgetTestInteractive, InactiveWidgetDoesNotGrabActivation) {
1043   WidgetAutoclosePtr widget(CreateTopLevelPlatformWidget());
1044   ShowSync(widget.get());
1045   EXPECT_EQ(GetWidgetShowState(widget.get()), ui::SHOW_STATE_NORMAL);
1046 
1047   WidgetAutoclosePtr widget2(new Widget());
1048   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
1049   params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
1050   widget2->Init(std::move(params));
1051   widget2->Show();
1052   RunPendingMessagesForActiveStatusChange();
1053 
1054   EXPECT_EQ(GetWidgetShowState(widget2.get()), ui::SHOW_STATE_INACTIVE);
1055   EXPECT_EQ(GetWidgetShowState(widget.get()), ui::SHOW_STATE_NORMAL);
1056 }
1057 #endif  // BUILDFLAG(ENABLE_DESKTOP_AURA) || defined(OS_APPLE)
1058 
1059 // ExitFullscreenRestoreState doesn't use DesktopAura widgets. On Mac, there are
1060 // currently only Desktop widgets and fullscreen changes have to coordinate with
1061 // the OS. See BridgedNativeWidgetUITest for native Mac fullscreen tests.
1062 // Maximize on mac is also (intentionally) a no-op.
1063 #if defined(OS_APPLE)
1064 #define MAYBE_ExitFullscreenRestoreState DISABLED_ExitFullscreenRestoreState
1065 #else
1066 #define MAYBE_ExitFullscreenRestoreState ExitFullscreenRestoreState
1067 #endif
1068 
1069 // Test that window state is not changed after getting out of full screen.
1070 TEST_F(WidgetTestInteractive, MAYBE_ExitFullscreenRestoreState) {
1071   WidgetAutoclosePtr toplevel(CreateTopLevelPlatformWidget());
1072 
1073   toplevel->Show();
1074   RunPendingMessages();
1075 
1076   // This should be a normal state window.
1077   EXPECT_EQ(ui::SHOW_STATE_NORMAL, GetWidgetShowState(toplevel.get()));
1078 
1079   toplevel->SetFullscreen(true);
1080   EXPECT_EQ(ui::SHOW_STATE_FULLSCREEN, GetWidgetShowState(toplevel.get()));
1081   toplevel->SetFullscreen(false);
1082   EXPECT_NE(ui::SHOW_STATE_FULLSCREEN, GetWidgetShowState(toplevel.get()));
1083 
1084   // And it should still be in normal state after getting out of full screen.
1085   EXPECT_EQ(ui::SHOW_STATE_NORMAL, GetWidgetShowState(toplevel.get()));
1086 
1087   // Now, make it maximized.
1088   toplevel->Maximize();
1089   EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED, GetWidgetShowState(toplevel.get()));
1090 
1091   toplevel->SetFullscreen(true);
1092   EXPECT_EQ(ui::SHOW_STATE_FULLSCREEN, GetWidgetShowState(toplevel.get()));
1093   toplevel->SetFullscreen(false);
1094   EXPECT_NE(ui::SHOW_STATE_FULLSCREEN, GetWidgetShowState(toplevel.get()));
1095 
1096   // And it stays maximized after getting out of full screen.
1097   EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED, GetWidgetShowState(toplevel.get()));
1098 }
1099 
1100 // Testing initial focus is assigned properly for normal top-level widgets,
1101 // and subclasses that specify a initially focused child view.
1102 TEST_F(WidgetTestInteractive, InitialFocus) {
1103   // By default, there is no initially focused view (even if there is a
1104   // focusable subview).
1105   Widget* toplevel(CreateTopLevelPlatformWidget());
1106   View* view = new View;
1107   view->SetFocusBehavior(View::FocusBehavior::ALWAYS);
1108   toplevel->GetContentsView()->AddChildView(view);
1109 
1110   ShowSync(toplevel);
1111   toplevel->Show();
1112   EXPECT_FALSE(view->HasFocus());
1113   EXPECT_FALSE(toplevel->GetFocusManager()->GetStoredFocusView());
1114   toplevel->CloseNow();
1115 
1116   // Testing a widget which specifies a initially focused view.
1117   TestInitialFocusWidgetDelegate delegate(GetContext());
1118 
1119   Widget* widget = delegate.GetWidget();
1120   ShowSync(widget);
1121   widget->Show();
1122   EXPECT_TRUE(delegate.view()->HasFocus());
1123   EXPECT_EQ(delegate.view(), widget->GetFocusManager()->GetStoredFocusView());
1124 }
1125 
1126 TEST_F(DesktopWidgetTestInteractive, RestoreAfterMinimize) {
1127   WidgetAutoclosePtr widget(CreateTopLevelNativeWidget());
1128   ShowSync(widget.get());
1129   ASSERT_FALSE(widget->IsMinimized());
1130 
1131   PropertyWaiter minimize_waiter(
1132       base::BindRepeating(&Widget::IsMinimized, base::Unretained(widget.get())),
1133       true);
1134   widget->Minimize();
1135   EXPECT_TRUE(minimize_waiter.Wait());
1136 
1137   PropertyWaiter restore_waiter(
1138       base::BindRepeating(&Widget::IsMinimized, base::Unretained(widget.get())),
1139       false);
1140   widget->Restore();
1141   EXPECT_TRUE(restore_waiter.Wait());
1142 }
1143 
1144 #if defined(OS_WIN)
1145 // TODO(davidbienvenu): Get this test to pass on Linux and ChromeOS by hiding
1146 // the root window when desktop widget is minimized.
1147 // Tests that root window visibility toggles correctly when the desktop widget
1148 // is minimized and maximized on Windows, and the Widget remains visible.
1149 TEST_F(DesktopWidgetTestInteractive, RestoreAndMinimizeVisibility) {
1150   WidgetAutoclosePtr widget(CreateTopLevelNativeWidget());
1151   aura::Window* root_window = GetRootWindow(widget.get());
1152   ShowSync(widget.get());
1153   ASSERT_FALSE(widget->IsMinimized());
1154   EXPECT_TRUE(root_window->IsVisible());
1155 
1156   PropertyWaiter minimize_widget_waiter(
1157       base::BindRepeating(&Widget::IsMinimized, base::Unretained(widget.get())),
1158       true);
1159   widget->Minimize();
1160   EXPECT_TRUE(minimize_widget_waiter.Wait());
1161   EXPECT_TRUE(widget->IsVisible());
1162   EXPECT_FALSE(root_window->IsVisible());
1163 
1164   PropertyWaiter restore_widget_waiter(
1165       base::BindRepeating(&Widget::IsMinimized, base::Unretained(widget.get())),
1166       false);
1167   widget->Restore();
1168   EXPECT_TRUE(restore_widget_waiter.Wait());
1169   EXPECT_TRUE(widget->IsVisible());
1170   EXPECT_TRUE(root_window->IsVisible());
1171 }
1172 
1173 // Test that focus is restored to the widget after a minimized window
1174 // is activated.
1175 TEST_F(DesktopWidgetTestInteractive, MinimizeAndActivateFocus) {
1176   WidgetAutoclosePtr widget(CreateTopLevelNativeWidget());
1177   aura::Window* root_window = GetRootWindow(widget.get());
1178   auto* widget_window = widget->GetNativeWindow();
1179   ShowSync(widget.get());
1180   ASSERT_FALSE(widget->IsMinimized());
1181   EXPECT_TRUE(root_window->IsVisible());
1182   widget_window->Focus();
1183   EXPECT_TRUE(widget_window->HasFocus());
1184   widget->GetContentsView()->SetFocusBehavior(View::FocusBehavior::ALWAYS);
1185   widget->GetContentsView()->RequestFocus();
1186   EXPECT_TRUE(widget->GetContentsView()->HasFocus());
1187 
1188   PropertyWaiter minimize_widget_waiter(
1189       base::BindRepeating(&Widget::IsMinimized, base::Unretained(widget.get())),
1190       true);
1191   widget->Minimize();
1192   EXPECT_TRUE(minimize_widget_waiter.Wait());
1193   EXPECT_TRUE(widget->IsVisible());
1194   EXPECT_FALSE(root_window->IsVisible());
1195 
1196   PropertyWaiter restore_widget_waiter(
1197       base::BindRepeating(&Widget::IsMinimized, base::Unretained(widget.get())),
1198       false);
1199   widget->Activate();
1200   EXPECT_TRUE(widget->GetContentsView()->HasFocus());
1201   EXPECT_TRUE(restore_widget_waiter.Wait());
1202   EXPECT_TRUE(widget->IsVisible());
1203   EXPECT_TRUE(root_window->IsVisible());
1204   EXPECT_TRUE(widget_window->CanFocus());
1205 }
1206 
1207 #endif  // defined(OS_WIN)
1208 
1209 #if BUILDFLAG(ENABLE_DESKTOP_AURA) || defined(OS_APPLE)
1210 // Tests that minimizing a widget causes the gesture_handler
1211 // to be cleared when the widget is minimized.
1212 TEST_F(DesktopWidgetTestInteractive, EventHandlersClearedOnWidgetMinimize) {
1213   WidgetAutoclosePtr widget(CreateTopLevelNativeWidget());
1214   ShowSync(widget.get());
1215   ASSERT_FALSE(widget->IsMinimized());
1216   View mouse_handler_view;
1217   internal::RootView* root_view =
1218       static_cast<internal::RootView*>(widget->GetRootView());
1219   // This also sets the gesture_handler, and we'll verify that it
1220   // gets cleared when the widget is minimized.
1221   root_view->SetMouseHandler(&mouse_handler_view);
1222   EXPECT_TRUE(GetGestureHandler(root_view));
1223 
1224   widget->Minimize();
1225   EXPECT_FALSE(GetGestureHandler(root_view));
1226 }
1227 #endif
1228 
1229 #if (defined(OS_LINUX) || defined(OS_CHROMEOS)) && \
1230     BUILDFLAG(ENABLE_DESKTOP_AURA)
1231 // Tests that when a desktop native widget has modal transient child, it should
1232 // avoid restore focused view itself as the modal transient child window will do
1233 // that, thus avoids having multiple focused view visually (crbug.com/727641).
1234 TEST_F(DesktopWidgetTestInteractive,
1235        DesktopNativeWidgetWithModalTransientChild) {
1236   // Create a desktop native Widget for Widget::Deactivate().
1237   WidgetAutoclosePtr deactivate_widget(CreateTopLevelNativeWidget());
1238   ShowSync(deactivate_widget.get());
1239 
1240   // Create a top level desktop native widget.
1241   WidgetAutoclosePtr top_level(CreateTopLevelNativeWidget());
1242 
1243   Textfield* textfield = new Textfield;
1244   textfield->SetBounds(0, 0, 200, 20);
1245   top_level->GetRootView()->AddChildView(textfield);
1246   ShowSync(top_level.get());
1247   textfield->RequestFocus();
1248   EXPECT_TRUE(textfield->HasFocus());
1249 
1250   // Create a modal dialog.
1251   // This instance will be destroyed when the dialog is destroyed.
1252   auto dialog_delegate = std::make_unique<DialogDelegateView>();
1253   dialog_delegate->SetModalType(ui::MODAL_TYPE_WINDOW);
1254   Widget* modal_dialog_widget = DialogDelegate::CreateDialogWidget(
1255       dialog_delegate.release(), nullptr, top_level->GetNativeView());
1256   modal_dialog_widget->SetBounds(gfx::Rect(0, 0, 100, 10));
1257   Textfield* dialog_textfield = new Textfield;
1258   dialog_textfield->SetBounds(0, 0, 50, 5);
1259   modal_dialog_widget->GetRootView()->AddChildView(dialog_textfield);
1260   // Dialog widget doesn't need a ShowSync as it gains active status
1261   // synchronously.
1262   modal_dialog_widget->Show();
1263   dialog_textfield->RequestFocus();
1264   EXPECT_TRUE(dialog_textfield->HasFocus());
1265   EXPECT_FALSE(textfield->HasFocus());
1266 
1267   DeactivateSync(top_level.get());
1268   EXPECT_FALSE(dialog_textfield->HasFocus());
1269   EXPECT_FALSE(textfield->HasFocus());
1270 
1271   // After deactivation and activation of top level widget, only modal dialog
1272   // should restore focused view.
1273   ActivateSync(top_level.get());
1274   EXPECT_TRUE(dialog_textfield->HasFocus());
1275   EXPECT_FALSE(textfield->HasFocus());
1276 }
1277 #endif  // (defined(OS_LINUX) || defined(OS_CHROMEOS)) &&
1278         // BUILDFLAG(ENABLE_DESKTOP_AURA)
1279 
1280 namespace {
1281 
1282 // Helper class for CaptureLostTrackingWidget to store whether
1283 // OnMouseCaptureLost has been invoked for a widget.
1284 class CaptureLostState {
1285  public:
1286   CaptureLostState() = default;
1287 
1288   bool GetAndClearGotCaptureLost() {
1289     bool value = got_capture_lost_;
1290     got_capture_lost_ = false;
1291     return value;
1292   }
1293 
1294   void OnMouseCaptureLost() { got_capture_lost_ = true; }
1295 
1296  private:
1297   bool got_capture_lost_ = false;
1298 
1299   DISALLOW_COPY_AND_ASSIGN(CaptureLostState);
1300 };
1301 
1302 // Used to verify OnMouseCaptureLost() has been invoked.
1303 class CaptureLostTrackingWidget : public Widget {
1304  public:
1305   explicit CaptureLostTrackingWidget(CaptureLostState* capture_lost_state)
1306       : capture_lost_state_(capture_lost_state) {}
1307 
1308   // Widget:
1309   void OnMouseCaptureLost() override {
1310     capture_lost_state_->OnMouseCaptureLost();
1311     Widget::OnMouseCaptureLost();
1312   }
1313 
1314  private:
1315   // Weak. Stores whether OnMouseCaptureLost has been invoked for this widget.
1316   CaptureLostState* capture_lost_state_;
1317 
1318   DISALLOW_COPY_AND_ASSIGN(CaptureLostTrackingWidget);
1319 };
1320 
1321 }  // namespace
1322 
1323 class WidgetCaptureTest : public DesktopWidgetTestInteractive {
1324  public:
1325   WidgetCaptureTest() = default;
1326   ~WidgetCaptureTest() override = default;
1327 
1328   // Verifies Widget::SetCapture() results in updating native capture along with
1329   // invoking the right Widget function.
1330   void TestCapture(bool use_desktop_native_widget) {
1331     CaptureLostState capture_state1;
1332     CaptureLostTrackingWidget widget1(&capture_state1);
1333     InitPlatformWidget(&widget1, use_desktop_native_widget);
1334     widget1.Show();
1335 
1336     CaptureLostState capture_state2;
1337     CaptureLostTrackingWidget widget2(&capture_state2);
1338     InitPlatformWidget(&widget2, use_desktop_native_widget);
1339     widget2.Show();
1340 
1341     // Set capture to widget2 and verity it gets it.
1342     widget2.SetCapture(widget2.GetRootView());
1343     EXPECT_FALSE(widget1.HasCapture());
1344     EXPECT_TRUE(widget2.HasCapture());
1345     EXPECT_FALSE(capture_state1.GetAndClearGotCaptureLost());
1346     EXPECT_FALSE(capture_state2.GetAndClearGotCaptureLost());
1347 
1348     // Set capture to widget1 and verify it gets it.
1349     widget1.SetCapture(widget1.GetRootView());
1350     EXPECT_TRUE(widget1.HasCapture());
1351     EXPECT_FALSE(widget2.HasCapture());
1352     EXPECT_FALSE(capture_state1.GetAndClearGotCaptureLost());
1353     EXPECT_TRUE(capture_state2.GetAndClearGotCaptureLost());
1354 
1355     // Release and verify no one has it.
1356     widget1.ReleaseCapture();
1357     EXPECT_FALSE(widget1.HasCapture());
1358     EXPECT_FALSE(widget2.HasCapture());
1359     EXPECT_TRUE(capture_state1.GetAndClearGotCaptureLost());
1360     EXPECT_FALSE(capture_state2.GetAndClearGotCaptureLost());
1361   }
1362 
1363   void InitPlatformWidget(Widget* widget, bool use_desktop_native_widget) {
1364     Widget::InitParams params =
1365         CreateParams(views::Widget::InitParams::TYPE_WINDOW);
1366     // The test class by default returns DesktopNativeWidgetAura.
1367     params.native_widget =
1368         use_desktop_native_widget
1369             ? nullptr
1370             : CreatePlatformNativeWidgetImpl(widget, kDefault, nullptr);
1371     params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
1372     widget->Init(std::move(params));
1373   }
1374 
1375  private:
1376   DISALLOW_COPY_AND_ASSIGN(WidgetCaptureTest);
1377 };
1378 
1379 // See description in TestCapture().
1380 TEST_F(WidgetCaptureTest, Capture) {
1381   TestCapture(false);
1382 }
1383 
1384 #if BUILDFLAG(ENABLE_DESKTOP_AURA) || defined(OS_APPLE)
1385 // See description in TestCapture(). Creates DesktopNativeWidget.
1386 TEST_F(WidgetCaptureTest, CaptureDesktopNativeWidget) {
1387   TestCapture(true);
1388 }
1389 #endif
1390 
1391 // Tests to ensure capture is correctly released from a Widget with capture when
1392 // it is destroyed. Test for crbug.com/622201.
1393 TEST_F(WidgetCaptureTest, DestroyWithCapture_CloseNow) {
1394   CaptureLostState capture_state;
1395   CaptureLostTrackingWidget* widget =
1396       new CaptureLostTrackingWidget(&capture_state);
1397   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
1398   widget->Init(std::move(params));
1399   widget->Show();
1400 
1401   widget->SetCapture(widget->GetRootView());
1402   EXPECT_TRUE(widget->HasCapture());
1403   EXPECT_FALSE(capture_state.GetAndClearGotCaptureLost());
1404   widget->CloseNow();
1405 
1406   EXPECT_TRUE(capture_state.GetAndClearGotCaptureLost());
1407 }
1408 
1409 TEST_F(WidgetCaptureTest, DestroyWithCapture_Close) {
1410   CaptureLostState capture_state;
1411   CaptureLostTrackingWidget* widget =
1412       new CaptureLostTrackingWidget(&capture_state);
1413   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
1414   widget->Init(std::move(params));
1415   widget->Show();
1416 
1417   widget->SetCapture(widget->GetRootView());
1418   EXPECT_TRUE(widget->HasCapture());
1419   EXPECT_FALSE(capture_state.GetAndClearGotCaptureLost());
1420   widget->Close();
1421   EXPECT_TRUE(capture_state.GetAndClearGotCaptureLost());
1422 }
1423 
1424 TEST_F(WidgetCaptureTest, DestroyWithCapture_WidgetOwnsNativeWidget) {
1425   Widget widget;
1426   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
1427   params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
1428   widget.Init(std::move(params));
1429   widget.Show();
1430 
1431   widget.SetCapture(widget.GetRootView());
1432   EXPECT_TRUE(widget.HasCapture());
1433 }
1434 
1435 // Test that no state is set if capture fails.
1436 TEST_F(WidgetCaptureTest, FailedCaptureRequestIsNoop) {
1437   Widget widget;
1438   Widget::InitParams params =
1439       CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
1440   params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
1441   params.bounds = gfx::Rect(400, 400);
1442   widget.Init(std::move(params));
1443 
1444   MouseView* mouse_view1 = new MouseView;
1445   MouseView* mouse_view2 = new MouseView;
1446   auto contents_view = std::make_unique<View>();
1447   contents_view->AddChildView(mouse_view1);
1448   contents_view->AddChildView(mouse_view2);
1449   widget.SetContentsView(std::move(contents_view));
1450 
1451   mouse_view1->SetBounds(0, 0, 200, 400);
1452   mouse_view2->SetBounds(200, 0, 200, 400);
1453 
1454   // Setting capture should fail because |widget| is not visible.
1455   widget.SetCapture(mouse_view1);
1456   EXPECT_FALSE(widget.HasCapture());
1457 
1458   widget.Show();
1459   ui::test::EventGenerator generator(GetRootWindow(&widget),
1460                                      widget.GetNativeWindow());
1461   generator.set_current_screen_location(gfx::Point(300, 10));
1462   generator.PressLeftButton();
1463 
1464   EXPECT_FALSE(mouse_view1->pressed());
1465   EXPECT_TRUE(mouse_view2->pressed());
1466 }
1467 
1468 TEST_F(WidgetCaptureTest, CaptureAutoReset) {
1469   WidgetAutoclosePtr toplevel(CreateTopLevelFramelessPlatformWidget());
1470   toplevel->SetContentsView(std::make_unique<View>());
1471 
1472   EXPECT_FALSE(toplevel->HasCapture());
1473   toplevel->SetCapture(nullptr);
1474   EXPECT_TRUE(toplevel->HasCapture());
1475 
1476   // By default, mouse release removes capture.
1477   gfx::Point click_location(45, 15);
1478   ui::MouseEvent release(ui::ET_MOUSE_RELEASED, click_location, click_location,
1479                          ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
1480                          ui::EF_LEFT_MOUSE_BUTTON);
1481   toplevel->OnMouseEvent(&release);
1482   EXPECT_FALSE(toplevel->HasCapture());
1483 
1484   // Now a mouse release shouldn't remove capture.
1485   toplevel->set_auto_release_capture(false);
1486   toplevel->SetCapture(nullptr);
1487   EXPECT_TRUE(toplevel->HasCapture());
1488   toplevel->OnMouseEvent(&release);
1489   EXPECT_TRUE(toplevel->HasCapture());
1490   toplevel->ReleaseCapture();
1491   EXPECT_FALSE(toplevel->HasCapture());
1492 }
1493 
1494 TEST_F(WidgetCaptureTest, ResetCaptureOnGestureEnd) {
1495   WidgetAutoclosePtr toplevel(CreateTopLevelFramelessPlatformWidget());
1496   View* container = toplevel->SetContentsView(std::make_unique<View>());
1497 
1498   View* gesture = new GestureCaptureView;
1499   gesture->SetBounds(0, 0, 30, 30);
1500   container->AddChildView(gesture);
1501 
1502   MouseView* mouse = new MouseView;
1503   mouse->SetBounds(30, 0, 30, 30);
1504   container->AddChildView(mouse);
1505 
1506   toplevel->SetSize(gfx::Size(100, 100));
1507   toplevel->Show();
1508 
1509   // Start a gesture on |gesture|.
1510   ui::GestureEvent tap_down(15, 15, 0, base::TimeTicks(),
1511                             ui::GestureEventDetails(ui::ET_GESTURE_TAP_DOWN));
1512   ui::GestureEvent end(15, 15, 0, base::TimeTicks(),
1513                        ui::GestureEventDetails(ui::ET_GESTURE_END));
1514   toplevel->OnGestureEvent(&tap_down);
1515 
1516   // Now try to click on |mouse|. Since |gesture| will have capture, |mouse|
1517   // will not receive the event.
1518   gfx::Point click_location(45, 15);
1519 
1520   ui::MouseEvent press(ui::ET_MOUSE_PRESSED, click_location, click_location,
1521                        ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
1522                        ui::EF_LEFT_MOUSE_BUTTON);
1523   ui::MouseEvent release(ui::ET_MOUSE_RELEASED, click_location, click_location,
1524                          ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
1525                          ui::EF_LEFT_MOUSE_BUTTON);
1526 
1527   EXPECT_TRUE(toplevel->HasCapture());
1528 
1529   toplevel->OnMouseEvent(&press);
1530   toplevel->OnMouseEvent(&release);
1531   EXPECT_EQ(0, mouse->pressed());
1532 
1533   EXPECT_FALSE(toplevel->HasCapture());
1534 
1535   // The end of the gesture should release the capture, and pressing on |mouse|
1536   // should now reach |mouse|.
1537   toplevel->OnGestureEvent(&end);
1538   toplevel->OnMouseEvent(&press);
1539   toplevel->OnMouseEvent(&release);
1540   EXPECT_EQ(1, mouse->pressed());
1541 }
1542 
1543 // Checks that if a mouse-press triggers a capture on a different widget (which
1544 // consumes the mouse-release event), then the target of the press does not have
1545 // capture.
1546 TEST_F(WidgetCaptureTest, DisableCaptureWidgetFromMousePress) {
1547   // The test creates two widgets: |first| and |second|.
1548   // The View in |first| makes |second| visible, sets capture on it, and starts
1549   // a nested loop (like a menu does). The View in |second| terminates the
1550   // nested loop and closes the widget.
1551   // The test sends a mouse-press event to |first|, and posts a task to send a
1552   // release event to |second|, to make sure that the release event is
1553   // dispatched after the nested loop starts.
1554 
1555   WidgetAutoclosePtr first(CreateTopLevelFramelessPlatformWidget());
1556   Widget* second = CreateTopLevelFramelessPlatformWidget();
1557 
1558   NestedLoopCaptureView* container =
1559       first->SetContentsView(std::make_unique<NestedLoopCaptureView>(second));
1560 
1561   second->SetContentsView(
1562       std::make_unique<ExitLoopOnRelease>(container->GetQuitClosure()));
1563 
1564   first->SetSize(gfx::Size(100, 100));
1565   first->Show();
1566 
1567   gfx::Point location(20, 20);
1568   base::ThreadTaskRunnerHandle::Get()->PostTask(
1569       FROM_HERE,
1570       base::BindOnce(
1571           &Widget::OnMouseEvent, base::Unretained(second),
1572           base::Owned(new ui::MouseEvent(
1573               ui::ET_MOUSE_RELEASED, location, location, ui::EventTimeForNow(),
1574               ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON))));
1575   ui::MouseEvent press(ui::ET_MOUSE_PRESSED, location, location,
1576                        ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
1577                        ui::EF_LEFT_MOUSE_BUTTON);
1578   first->OnMouseEvent(&press);
1579   EXPECT_FALSE(first->HasCapture());
1580 }
1581 
1582 // Tests some grab/ungrab events. Only one Widget can have capture at any given
1583 // time.
1584 TEST_F(WidgetCaptureTest, GrabUngrab) {
1585   auto top_level = CreateTestWidget();
1586   top_level->SetContentsView(std::make_unique<MouseView>());
1587 
1588   Widget* child1 = new Widget;
1589   Widget::InitParams params1 = CreateParams(Widget::InitParams::TYPE_CONTROL);
1590   params1.parent = top_level->GetNativeView();
1591   params1.bounds = gfx::Rect(10, 10, 100, 100);
1592   child1->Init(std::move(params1));
1593   child1->SetContentsView(std::make_unique<MouseView>());
1594 
1595   Widget* child2 = new Widget;
1596   Widget::InitParams params2 = CreateParams(Widget::InitParams::TYPE_CONTROL);
1597   params2.parent = top_level->GetNativeView();
1598   params2.bounds = gfx::Rect(110, 10, 100, 100);
1599   child2->Init(std::move(params2));
1600   child2->SetContentsView(std::make_unique<MouseView>());
1601 
1602   top_level->Show();
1603   RunPendingMessages();
1604 
1605   // Click on child1.
1606   ui::test::EventGenerator generator(GetRootWindow(top_level.get()),
1607                                      child1->GetNativeWindow());
1608   generator.PressLeftButton();
1609 
1610   EXPECT_FALSE(top_level->HasCapture());
1611   EXPECT_TRUE(child1->HasCapture());
1612   EXPECT_FALSE(child2->HasCapture());
1613 
1614   generator.ReleaseLeftButton();
1615   EXPECT_FALSE(top_level->HasCapture());
1616   EXPECT_FALSE(child1->HasCapture());
1617   EXPECT_FALSE(child2->HasCapture());
1618 
1619   // Click on child2.
1620   generator.SetTargetWindow(child2->GetNativeWindow());
1621   generator.set_current_screen_location(
1622       generator.delegate()->CenterOfWindow(child2->GetNativeWindow()));
1623   generator.PressLeftButton();
1624 
1625   EXPECT_FALSE(top_level->HasCapture());
1626   EXPECT_FALSE(child1->HasCapture());
1627   EXPECT_TRUE(child2->HasCapture());
1628 
1629   generator.ReleaseLeftButton();
1630   EXPECT_FALSE(top_level->HasCapture());
1631   EXPECT_FALSE(child1->HasCapture());
1632   EXPECT_FALSE(child2->HasCapture());
1633 
1634   // Click on top_level.
1635   generator.SetTargetWindow(top_level->GetNativeWindow());
1636   generator.set_current_screen_location(gfx::Point());
1637   generator.PressLeftButton();
1638 
1639   EXPECT_TRUE(top_level->HasCapture());
1640   EXPECT_FALSE(child1->HasCapture());
1641   EXPECT_FALSE(child2->HasCapture());
1642 
1643   generator.ReleaseLeftButton();
1644   EXPECT_FALSE(top_level->HasCapture());
1645   EXPECT_FALSE(child1->HasCapture());
1646   EXPECT_FALSE(child2->HasCapture());
1647 }
1648 
1649 // Disabled on Mac. Desktop Mac doesn't have system modal windows since Carbon
1650 // was deprecated. It does have application modal windows, but only Ash requests
1651 // those.
1652 #if defined(OS_APPLE)
1653 #define MAYBE_SystemModalWindowReleasesCapture \
1654   DISABLED_SystemModalWindowReleasesCapture
1655 #elif defined(OS_CHROMEOS)
1656 // Investigate enabling for Chrome OS. It probably requires help from the window
1657 // service.
1658 #define MAYBE_SystemModalWindowReleasesCapture \
1659   DISABLED_SystemModalWindowReleasesCapture
1660 #else
1661 #define MAYBE_SystemModalWindowReleasesCapture SystemModalWindowReleasesCapture
1662 #endif
1663 
1664 // Test that when opening a system-modal window, capture is released.
1665 TEST_F(WidgetCaptureTest, MAYBE_SystemModalWindowReleasesCapture) {
1666   TestWidgetFocusChangeListener focus_listener;
1667   WidgetFocusManager::GetInstance()->AddFocusChangeListener(&focus_listener);
1668 
1669   // Create a top level widget.
1670   Widget top_level_widget;
1671   Widget::InitParams init_params =
1672       CreateParams(Widget::InitParams::TYPE_WINDOW);
1673   init_params.show_state = ui::SHOW_STATE_NORMAL;
1674   gfx::Rect initial_bounds(0, 0, 500, 500);
1675   init_params.bounds = initial_bounds;
1676   init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
1677   top_level_widget.Init(std::move(init_params));
1678   ShowSync(&top_level_widget);
1679 
1680   ASSERT_FALSE(focus_listener.focus_changes().empty());
1681   EXPECT_EQ(top_level_widget.GetNativeView(),
1682             focus_listener.focus_changes().back());
1683 
1684   EXPECT_FALSE(top_level_widget.HasCapture());
1685   top_level_widget.SetCapture(nullptr);
1686   EXPECT_TRUE(top_level_widget.HasCapture());
1687 
1688   // Create a modal dialog.
1689   auto dialog_delegate = std::make_unique<DialogDelegateView>();
1690   dialog_delegate->SetModalType(ui::MODAL_TYPE_SYSTEM);
1691 
1692   Widget* modal_dialog_widget = views::DialogDelegate::CreateDialogWidget(
1693       dialog_delegate.release(), nullptr, top_level_widget.GetNativeView());
1694   modal_dialog_widget->SetBounds(gfx::Rect(100, 100, 200, 200));
1695   ShowSync(modal_dialog_widget);
1696 
1697   EXPECT_FALSE(top_level_widget.HasCapture());
1698 
1699   modal_dialog_widget->CloseNow();
1700   top_level_widget.CloseNow();
1701   WidgetFocusManager::GetInstance()->RemoveFocusChangeListener(&focus_listener);
1702 }
1703 
1704 // Regression test for http://crbug.com/382421 (Linux-Aura issue).
1705 // TODO(pkotwicz): Make test pass on CrOS and Windows.
1706 // TODO(tapted): Investigate for toolkit-views on Mac http;//crbug.com/441064.
1707 #if defined(OS_CHROMEOS) || defined(OS_APPLE)
1708 #define MAYBE_MouseExitOnCaptureGrab DISABLED_MouseExitOnCaptureGrab
1709 #else
1710 #define MAYBE_MouseExitOnCaptureGrab MouseExitOnCaptureGrab
1711 #endif
1712 
1713 // Test that a synthetic mouse exit is sent to the widget which was handling
1714 // mouse events when a different widget grabs capture. Except for Windows,
1715 // which does not send a synthetic mouse exit.
1716 TEST_F(WidgetCaptureTest, MAYBE_MouseExitOnCaptureGrab) {
1717   Widget widget1;
1718   Widget::InitParams params1 =
1719       CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
1720   params1.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
1721   widget1.Init(std::move(params1));
1722   MouseView* mouse_view1 =
1723       widget1.SetContentsView(std::make_unique<MouseView>());
1724   widget1.Show();
1725   widget1.SetBounds(gfx::Rect(300, 300));
1726 
1727   Widget widget2;
1728   Widget::InitParams params2 =
1729       CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
1730   params2.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
1731   widget2.Init(std::move(params2));
1732   widget2.Show();
1733   widget2.SetBounds(gfx::Rect(400, 0, 300, 300));
1734 
1735   ui::test::EventGenerator generator(GetRootWindow(&widget1));
1736   generator.set_current_screen_location(gfx::Point(100, 100));
1737   generator.MoveMouseBy(0, 0);
1738 
1739   EXPECT_EQ(1, mouse_view1->EnteredCalls());
1740   EXPECT_EQ(0, mouse_view1->ExitedCalls());
1741 
1742   widget2.SetCapture(nullptr);
1743   EXPECT_EQ(0, mouse_view1->EnteredCalls());
1744   // On Windows, Chrome doesn't synthesize a separate mouse exited event.
1745   // Instead, it uses ::TrackMouseEvent to get notified of the mouse leaving.
1746   // Calling SetCapture does not cause Windows to generate a WM_MOUSELEAVE
1747   // event. See WindowEventDispatcher::OnOtherRootGotCapture() for more info.
1748 #if defined(OS_WIN)
1749   EXPECT_EQ(0, mouse_view1->ExitedCalls());
1750 #else
1751   EXPECT_EQ(1, mouse_view1->ExitedCalls());
1752 #endif  // OS_WIN
1753 }
1754 
1755 namespace {
1756 
1757 // Widget observer which grabs capture when the widget is activated.
1758 class CaptureOnActivationObserver : public WidgetObserver {
1759  public:
1760   CaptureOnActivationObserver() = default;
1761   ~CaptureOnActivationObserver() override = default;
1762 
1763   // WidgetObserver:
1764   void OnWidgetActivationChanged(Widget* widget, bool active) override {
1765     if (active) {
1766       widget->SetCapture(nullptr);
1767       activation_observed_ = true;
1768     }
1769   }
1770 
1771   bool activation_observed() const { return activation_observed_; }
1772 
1773  private:
1774   bool activation_observed_ = false;
1775 
1776   DISALLOW_COPY_AND_ASSIGN(CaptureOnActivationObserver);
1777 };
1778 
1779 }  // namespace
1780 
1781 // Test that setting capture on widget activation of a non-toplevel widget
1782 // (e.g. a bubble on Linux) succeeds.
1783 TEST_F(WidgetCaptureTest, SetCaptureToNonToplevel) {
1784   Widget toplevel;
1785   Widget::InitParams toplevel_params =
1786       CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
1787   toplevel_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
1788   toplevel.Init(std::move(toplevel_params));
1789   toplevel.Show();
1790 
1791   Widget* child = new Widget;
1792   Widget::InitParams child_params =
1793       CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
1794   child_params.parent = toplevel.GetNativeView();
1795   child_params.context = toplevel.GetNativeWindow();
1796   child->Init(std::move(child_params));
1797 
1798   CaptureOnActivationObserver observer;
1799   child->AddObserver(&observer);
1800   child->Show();
1801 
1802 #if defined(OS_APPLE)
1803   // On Mac, activation is asynchronous. A single trip to the runloop should be
1804   // sufficient. On Aura platforms, note that since the child widget isn't top-
1805   // level, the aura window manager gets asked whether the widget is active, not
1806   // the OS.
1807   base::RunLoop().RunUntilIdle();
1808 #endif
1809 
1810   EXPECT_TRUE(observer.activation_observed());
1811   EXPECT_TRUE(child->HasCapture());
1812 
1813   child->RemoveObserver(&observer);
1814 }
1815 
1816 #if defined(OS_WIN)
1817 namespace {
1818 
1819 // Used to verify OnMouseEvent() has been invoked.
1820 class MouseEventTrackingWidget : public Widget {
1821  public:
1822   MouseEventTrackingWidget() = default;
1823   ~MouseEventTrackingWidget() override = default;
1824 
1825   bool GetAndClearGotMouseEvent() {
1826     bool value = got_mouse_event_;
1827     got_mouse_event_ = false;
1828     return value;
1829   }
1830 
1831   // Widget:
1832   void OnMouseEvent(ui::MouseEvent* event) override {
1833     got_mouse_event_ = true;
1834     Widget::OnMouseEvent(event);
1835   }
1836 
1837  private:
1838   bool got_mouse_event_ = false;
1839 
1840   DISALLOW_COPY_AND_ASSIGN(MouseEventTrackingWidget);
1841 };
1842 
1843 }  // namespace
1844 
1845 // Verifies if a mouse event is received on a widget that doesn't have capture
1846 // on Windows that it is correctly processed by the widget that doesn't have
1847 // capture. This behavior is not desired on OSes other than Windows.
1848 TEST_F(WidgetCaptureTest, MouseEventDispatchedToRightWindow) {
1849   MouseEventTrackingWidget widget1;
1850   Widget::InitParams params1 =
1851       CreateParams(views::Widget::InitParams::TYPE_WINDOW);
1852   params1.native_widget = new DesktopNativeWidgetAura(&widget1);
1853   params1.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
1854   widget1.Init(std::move(params1));
1855   widget1.Show();
1856 
1857   MouseEventTrackingWidget widget2;
1858   Widget::InitParams params2 =
1859       CreateParams(views::Widget::InitParams::TYPE_WINDOW);
1860   params2.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
1861   params2.native_widget = new DesktopNativeWidgetAura(&widget2);
1862   widget2.Init(std::move(params2));
1863   widget2.Show();
1864 
1865   // Set capture to widget2 and verity it gets it.
1866   widget2.SetCapture(widget2.GetRootView());
1867   EXPECT_FALSE(widget1.HasCapture());
1868   EXPECT_TRUE(widget2.HasCapture());
1869 
1870   widget1.GetAndClearGotMouseEvent();
1871   widget2.GetAndClearGotMouseEvent();
1872   // Send a mouse event to the RootWindow associated with |widget1|. Even though
1873   // |widget2| has capture, |widget1| should still get the event.
1874   ui::MouseEvent mouse_event(ui::ET_MOUSE_EXITED, gfx::Point(), gfx::Point(),
1875                              ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE);
1876   ui::EventDispatchDetails details =
1877       widget1.GetNativeWindow()->GetHost()->event_sink()->OnEventFromSource(
1878           &mouse_event);
1879   ASSERT_FALSE(details.dispatcher_destroyed);
1880   EXPECT_TRUE(widget1.GetAndClearGotMouseEvent());
1881   EXPECT_FALSE(widget2.GetAndClearGotMouseEvent());
1882 }
1883 #endif  // defined(OS_WIN)
1884 
1885 class WidgetInputMethodInteractiveTest : public DesktopWidgetTestInteractive {
1886  public:
1887   WidgetInputMethodInteractiveTest() = default;
1888 
1889   // testing::Test:
1890   void SetUp() override {
1891     DesktopWidgetTestInteractive::SetUp();
1892 #if defined(OS_WIN)
1893     // On Windows, Widget::Deactivate() works by activating the next topmost
1894     // window on the z-order stack. This only works if there is at least one
1895     // other window, so make sure that is the case.
1896     deactivate_widget_ = CreateTopLevelNativeWidget();
1897     deactivate_widget_->Show();
1898 #endif
1899   }
1900 
1901   void TearDown() override {
1902     if (deactivate_widget_)
1903       deactivate_widget_->CloseNow();
1904     DesktopWidgetTestInteractive::TearDown();
1905   }
1906 
1907  private:
1908   Widget* deactivate_widget_ = nullptr;
1909 
1910   DISALLOW_COPY_AND_ASSIGN(WidgetInputMethodInteractiveTest);
1911 };
1912 
1913 #if defined(OS_APPLE)
1914 #define MAYBE_Activation DISABLED_Activation
1915 #else
1916 #define MAYBE_Activation Activation
1917 #endif
1918 // Test input method focus changes affected by top window activaction.
1919 TEST_F(WidgetInputMethodInteractiveTest, MAYBE_Activation) {
1920   WidgetAutoclosePtr widget(CreateTopLevelNativeWidget());
1921   Textfield* textfield = new Textfield;
1922   widget->GetRootView()->AddChildView(textfield);
1923   textfield->RequestFocus();
1924 
1925   ShowSync(widget.get());
1926 
1927   EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT,
1928             widget->GetInputMethod()->GetTextInputType());
1929 
1930   DeactivateSync(widget.get());
1931 
1932   EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE,
1933             widget->GetInputMethod()->GetTextInputType());
1934 }
1935 
1936 // Test input method focus changes affected by focus changes within 1 window.
1937 TEST_F(WidgetInputMethodInteractiveTest, OneWindow) {
1938   WidgetAutoclosePtr widget(CreateTopLevelNativeWidget());
1939   Textfield* textfield1 = new Textfield;
1940   Textfield* textfield2 = new Textfield;
1941   textfield2->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
1942   widget->GetRootView()->AddChildView(textfield1);
1943   widget->GetRootView()->AddChildView(textfield2);
1944 
1945   ShowSync(widget.get());
1946 
1947   textfield1->RequestFocus();
1948   EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT,
1949             widget->GetInputMethod()->GetTextInputType());
1950 
1951   textfield2->RequestFocus();
1952   EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD,
1953             widget->GetInputMethod()->GetTextInputType());
1954 
1955 // Widget::Deactivate() doesn't work for CrOS, because it uses NWA instead of
1956 // DNWA (which just activates the last active window) and involves the
1957 // AuraTestHelper which sets the input method as DummyInputMethod.
1958 #if BUILDFLAG(ENABLE_DESKTOP_AURA) || defined(OS_APPLE)
1959   DeactivateSync(widget.get());
1960   EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE,
1961             widget->GetInputMethod()->GetTextInputType());
1962 
1963   ActivateSync(widget.get());
1964   EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD,
1965             widget->GetInputMethod()->GetTextInputType());
1966 
1967   DeactivateSync(widget.get());
1968   textfield1->RequestFocus();
1969   ActivateSync(widget.get());
1970   EXPECT_TRUE(widget->IsActive());
1971   EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT,
1972             widget->GetInputMethod()->GetTextInputType());
1973 #endif
1974 }
1975 
1976 // Test input method focus changes affected by focus changes cross 2 windows
1977 // which shares the same top window.
1978 TEST_F(WidgetInputMethodInteractiveTest, TwoWindows) {
1979   WidgetAutoclosePtr parent(CreateTopLevelNativeWidget());
1980   parent->SetBounds(gfx::Rect(100, 100, 100, 100));
1981 
1982   Widget* child = CreateChildNativeWidgetWithParent(parent.get());
1983   child->SetBounds(gfx::Rect(0, 0, 50, 50));
1984   child->Show();
1985 
1986   Textfield* textfield_parent = new Textfield;
1987   Textfield* textfield_child = new Textfield;
1988   textfield_parent->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
1989   parent->GetRootView()->AddChildView(textfield_parent);
1990   child->GetRootView()->AddChildView(textfield_child);
1991   ShowSync(parent.get());
1992 
1993   EXPECT_EQ(parent->GetInputMethod(), child->GetInputMethod());
1994 
1995   textfield_parent->RequestFocus();
1996   EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD,
1997             parent->GetInputMethod()->GetTextInputType());
1998 
1999   textfield_child->RequestFocus();
2000   EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT,
2001             parent->GetInputMethod()->GetTextInputType());
2002 
2003 // Widget::Deactivate() doesn't work for CrOS, because it uses NWA instead of
2004 // DNWA (which just activates the last active window) and involves the
2005 // AuraTestHelper which sets the input method as DummyInputMethod.
2006 #if BUILDFLAG(ENABLE_DESKTOP_AURA) || defined(OS_APPLE)
2007   DeactivateSync(parent.get());
2008   EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE,
2009             parent->GetInputMethod()->GetTextInputType());
2010 
2011   ActivateSync(parent.get());
2012   EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT,
2013             parent->GetInputMethod()->GetTextInputType());
2014 
2015   textfield_parent->RequestFocus();
2016   DeactivateSync(parent.get());
2017   EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE,
2018             parent->GetInputMethod()->GetTextInputType());
2019 
2020   ActivateSync(parent.get());
2021   EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD,
2022             parent->GetInputMethod()->GetTextInputType());
2023 #endif
2024 }
2025 
2026 // Test input method focus changes affected by textfield's state changes.
2027 TEST_F(WidgetInputMethodInteractiveTest, TextField) {
2028   WidgetAutoclosePtr widget(CreateTopLevelNativeWidget());
2029   Textfield* textfield = new Textfield;
2030   widget->GetRootView()->AddChildView(textfield);
2031   ShowSync(widget.get());
2032   EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE,
2033             widget->GetInputMethod()->GetTextInputType());
2034 
2035   textfield->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
2036   EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE,
2037             widget->GetInputMethod()->GetTextInputType());
2038 
2039   textfield->RequestFocus();
2040   EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD,
2041             widget->GetInputMethod()->GetTextInputType());
2042 
2043   textfield->SetTextInputType(ui::TEXT_INPUT_TYPE_TEXT);
2044   EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT,
2045             widget->GetInputMethod()->GetTextInputType());
2046 
2047   textfield->SetReadOnly(true);
2048   EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE,
2049             widget->GetInputMethod()->GetTextInputType());
2050 }
2051 
2052 // Test input method should not work for accelerator.
2053 TEST_F(WidgetInputMethodInteractiveTest, AcceleratorInTextfield) {
2054   WidgetAutoclosePtr widget(CreateTopLevelNativeWidget());
2055   Textfield* textfield = new Textfield;
2056   widget->GetRootView()->AddChildView(textfield);
2057   ShowSync(widget.get());
2058   textfield->SetTextInputType(ui::TEXT_INPUT_TYPE_TEXT);
2059   textfield->RequestFocus();
2060 
2061   ui::KeyEvent key_event(ui::ET_KEY_PRESSED, ui::VKEY_F, ui::EF_ALT_DOWN);
2062   ui::Accelerator accelerator(key_event);
2063   widget->GetFocusManager()->RegisterAccelerator(
2064       accelerator, ui::AcceleratorManager::kNormalPriority, textfield);
2065 
2066   widget->OnKeyEvent(&key_event);
2067   EXPECT_TRUE(key_event.stopped_propagation());
2068 
2069   widget->GetFocusManager()->UnregisterAccelerators(textfield);
2070 
2071   ui::KeyEvent key_event2(key_event);
2072   widget->OnKeyEvent(&key_event2);
2073   EXPECT_FALSE(key_event2.stopped_propagation());
2074 }
2075 
2076 }  // namespace test
2077 }  // namespace views
2078