window_cycle_controller_unittest.cc 149 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446
  1. // Copyright 2014 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. #include "ash/wm/window_cycle/window_cycle_controller.h"
  5. #include <algorithm>
  6. #include <memory>
  7. #include "ash/accelerators/accelerator_controller_impl.h"
  8. #include "ash/accessibility/accessibility_controller_impl.h"
  9. #include "ash/accessibility/test_accessibility_controller_client.h"
  10. #include "ash/app_list/app_list_controller_impl.h"
  11. #include "ash/app_list/test/app_list_test_helper.h"
  12. #include "ash/constants/ash_features.h"
  13. #include "ash/constants/ash_pref_names.h"
  14. #include "ash/focus_cycler.h"
  15. #include "ash/frame_throttler/frame_throttling_controller.h"
  16. #include "ash/frame_throttler/mock_frame_throttling_observer.h"
  17. #include "ash/multi_user/multi_user_window_manager_impl.h"
  18. #include "ash/public/cpp/ash_prefs.h"
  19. #include "ash/public/cpp/multi_user_window_manager.h"
  20. #include "ash/public/cpp/multi_user_window_manager_delegate.h"
  21. #include "ash/public/cpp/shell_window_ids.h"
  22. #include "ash/public/cpp/window_properties.h"
  23. #include "ash/session/session_controller_impl.h"
  24. #include "ash/session/test_session_controller_client.h"
  25. #include "ash/shelf/shelf.h"
  26. #include "ash/shelf/shelf_view_test_api.h"
  27. #include "ash/shelf/shelf_widget.h"
  28. #include "ash/shell.h"
  29. #include "ash/strings/grit/ash_strings.h"
  30. #include "ash/system/unified/unified_system_tray.h"
  31. #include "ash/test/ash_test_base.h"
  32. #include "ash/test_shell_delegate.h"
  33. #include "ash/wm/desks/desk.h"
  34. #include "ash/wm/desks/desks_controller.h"
  35. #include "ash/wm/desks/desks_test_util.h"
  36. #include "ash/wm/gestures/wm_gesture_handler.h"
  37. #include "ash/wm/overview/overview_controller.h"
  38. #include "ash/wm/overview/overview_highlight_controller.h"
  39. #include "ash/wm/overview/overview_session.h"
  40. #include "ash/wm/overview/overview_test_util.h"
  41. #include "ash/wm/tablet_mode/tablet_mode_controller_test_api.h"
  42. #include "ash/wm/window_cycle/window_cycle_event_filter.h"
  43. #include "ash/wm/window_cycle/window_cycle_item_view.h"
  44. #include "ash/wm/window_cycle/window_cycle_list.h"
  45. #include "ash/wm/window_cycle/window_cycle_view.h"
  46. #include "ash/wm/window_state.h"
  47. #include "ash/wm/window_util.h"
  48. #include "ash/wm/wm_event.h"
  49. #include "base/containers/contains.h"
  50. #include "base/numerics/ranges.h"
  51. #include "base/run_loop.h"
  52. #include "base/test/metrics/histogram_tester.h"
  53. #include "base/test/scoped_feature_list.h"
  54. #include "components/prefs/pref_service.h"
  55. #include "ui/aura/client/aura_constants.h"
  56. #include "ui/aura/client/screen_position_client.h"
  57. #include "ui/aura/env.h"
  58. #include "ui/aura/test/test_windows.h"
  59. #include "ui/aura/window.h"
  60. #include "ui/aura/window_event_dispatcher.h"
  61. #include "ui/base/l10n/l10n_util.h"
  62. #include "ui/compositor/layer.h"
  63. #include "ui/compositor/layer_animator.h"
  64. #include "ui/compositor/scoped_animation_duration_scale_mode.h"
  65. #include "ui/display/display_layout_builder.h"
  66. #include "ui/display/manager/display_layout_store.h"
  67. #include "ui/display/manager/display_manager.h"
  68. #include "ui/display/scoped_display_for_new_windows.h"
  69. #include "ui/display/test/display_manager_test_api.h"
  70. #include "ui/events/event_handler.h"
  71. #include "ui/events/test/event_generator.h"
  72. #include "ui/gfx/geometry/rect.h"
  73. namespace ash {
  74. namespace {
  75. constexpr int kNumFingersForMouseWheel = 2;
  76. constexpr int kNumFingersForTrackpad = 3;
  77. class EventCounter : public ui::EventHandler {
  78. public:
  79. EventCounter() : key_events_(0), mouse_events_(0) {}
  80. EventCounter(const EventCounter&) = delete;
  81. EventCounter& operator=(const EventCounter&) = delete;
  82. ~EventCounter() override = default;
  83. int GetKeyEventCountAndReset() {
  84. int count = key_events_;
  85. key_events_ = 0;
  86. return count;
  87. }
  88. int GetMouseEventCountAndReset() {
  89. int count = mouse_events_;
  90. mouse_events_ = 0;
  91. return count;
  92. }
  93. // ui::EventHandler:
  94. void OnKeyEvent(ui::KeyEvent* event) override { key_events_++; }
  95. void OnMouseEvent(ui::MouseEvent* event) override { mouse_events_++; }
  96. private:
  97. int key_events_;
  98. int mouse_events_;
  99. };
  100. bool IsWindowMinimized(aura::Window* window) {
  101. return WindowState::Get(window)->IsMinimized();
  102. }
  103. bool InOverviewSession() {
  104. return Shell::Get()->overview_controller()->InOverviewSession();
  105. }
  106. bool IsNaturalScrollOn() {
  107. PrefService* pref =
  108. Shell::Get()->session_controller()->GetActivePrefService();
  109. return pref->GetBoolean(prefs::kTouchpadEnabled) &&
  110. pref->GetBoolean(prefs::kNaturalScroll);
  111. }
  112. int GetOffsetX(int offset) {
  113. // The handler code uses the new directions which is the reverse of the old
  114. // handler code. Reverse the offset if the ReverseScrollGestures feature is
  115. // disabled so that the unit tests test the old behavior.
  116. return features::IsReverseScrollGesturesEnabled() ? offset : -offset;
  117. }
  118. int GetOffsetY(int offset) {
  119. // The handler code uses the new directions which is the reverse of the old
  120. // handler code. Reverse the offset if the ReverseScrollGestures feature is
  121. // disabled so that the unit tests test the old behavior.
  122. if (!features::IsReverseScrollGesturesEnabled() || IsNaturalScrollOn())
  123. return -offset;
  124. return offset;
  125. }
  126. const WindowCycleList* GetCycleList() {
  127. return Shell::Get()->window_cycle_controller()->window_cycle_list();
  128. }
  129. } // namespace
  130. // Wrapper for WindowCycleList that exposes internal state to test functions.
  131. class WindowCycleListTestApi {
  132. public:
  133. explicit WindowCycleListTestApi(const WindowCycleList* cycle_list)
  134. : cycle_list_(cycle_list) {}
  135. WindowCycleListTestApi(const WindowCycleListTestApi&) = delete;
  136. WindowCycleListTestApi& operator=(const WindowCycleListTestApi&) = delete;
  137. ~WindowCycleListTestApi() = default;
  138. const aura::Window::Windows& windows() const { return cycle_list_->windows_; }
  139. const views::Widget* widget() const { return cycle_list_->cycle_ui_widget_; }
  140. WindowCycleView* cycle_view() const { return cycle_list_->cycle_view_; }
  141. const views::Label* no_recent_items_label() const {
  142. return cycle_view()->no_recent_items_label_;
  143. }
  144. const aura::Window* target_window() const {
  145. return cycle_view()->target_window_;
  146. }
  147. int current_index() const { return cycle_list_->current_index_; }
  148. const views::View::Views& GetWindowCycleItemViews() const {
  149. return cycle_view()->mirror_container_->children();
  150. }
  151. const views::View::Views& GetTabSliderButtons() const {
  152. auto* tab_slider_container = cycle_view()->tab_slider_container_;
  153. if (!tab_slider_container) {
  154. static const views::View::Views empty;
  155. return empty;
  156. }
  157. return tab_slider_container->buttons_container_->children();
  158. }
  159. bool IsCycleViewAnimating() const {
  160. return cycle_view()->layer()->GetAnimator()->is_animating();
  161. }
  162. private:
  163. const WindowCycleList* const cycle_list_;
  164. };
  165. using aura::Window;
  166. using aura::test::CreateTestWindowWithId;
  167. using aura::test::TestWindowDelegate;
  168. class WindowCycleControllerTest : public AshTestBase {
  169. public:
  170. WindowCycleControllerTest() = default;
  171. WindowCycleControllerTest(const WindowCycleControllerTest&) = delete;
  172. WindowCycleControllerTest& operator=(const WindowCycleControllerTest&) =
  173. delete;
  174. ~WindowCycleControllerTest() override = default;
  175. void SetUp() override {
  176. AshTestBase::SetUp();
  177. WindowCycleList::SetDisableInitialDelayForTesting(true);
  178. shelf_view_test_ = std::make_unique<ShelfViewTestAPI>(
  179. GetPrimaryShelf()->GetShelfViewForTesting());
  180. shelf_view_test_->SetAnimationDuration(base::Milliseconds(1));
  181. }
  182. const aura::Window::Windows GetWindows(WindowCycleController* controller) {
  183. return WindowCycleListTestApi(controller->window_cycle_list()).windows();
  184. }
  185. const views::Widget* GetWindowCycleListWidget() const {
  186. return WindowCycleListTestApi(GetCycleList()).widget();
  187. }
  188. const views::View::Views& GetWindowCycleItemViews() const {
  189. return WindowCycleListTestApi(GetCycleList()).GetWindowCycleItemViews();
  190. }
  191. const views::View::Views& GetWindowCycleTabSliderButtons() const {
  192. return WindowCycleListTestApi(GetCycleList()).GetTabSliderButtons();
  193. }
  194. const views::Label* GetWindowCycleNoRecentItemsLabel() const {
  195. return WindowCycleListTestApi(GetCycleList()).no_recent_items_label();
  196. }
  197. const aura::Window* GetTargetWindow() const {
  198. return WindowCycleListTestApi(GetCycleList()).target_window();
  199. }
  200. bool CycleViewExists() const {
  201. return WindowCycleListTestApi(GetCycleList()).cycle_view();
  202. }
  203. int GetCurrentIndex() const {
  204. return WindowCycleListTestApi(GetCycleList()).current_index();
  205. }
  206. void CompleteCycling(WindowCycleController* controller) {
  207. controller->CompleteCycling();
  208. base::RunLoop().RunUntilIdle();
  209. }
  210. void CompleteCyclingAndDeskSwitching(WindowCycleController* controller) {
  211. DeskSwitchAnimationWaiter waiter;
  212. controller->CompleteCycling();
  213. base::RunLoop().RunUntilIdle();
  214. auto* desks_controller = Shell::Get()->desks_controller();
  215. if (desks_controller->AreDesksBeingModified())
  216. waiter.Wait();
  217. }
  218. void Scroll(float x_offset, float y_offset, int fingers) {
  219. GetEventGenerator()->ScrollSequence(
  220. gfx::Point(), base::Milliseconds(5), GetOffsetX(x_offset),
  221. GetOffsetY(y_offset), /*steps=*/100, fingers);
  222. }
  223. void MouseWheelScroll(int delta_x, int delta_y, int num_of_times) {
  224. auto* generator = GetEventGenerator();
  225. for (int i = 0; i < num_of_times; i++)
  226. generator->MoveMouseWheel(delta_x, delta_y);
  227. }
  228. private:
  229. std::unique_ptr<ShelfViewTestAPI> shelf_view_test_;
  230. };
  231. TEST_F(WindowCycleControllerTest, HandleCycleWindowBaseCases) {
  232. WindowCycleController* controller = Shell::Get()->window_cycle_controller();
  233. // Cycling doesn't crash if there are no windows.
  234. controller->HandleCycleWindow(
  235. WindowCycleController::WindowCyclingDirection::kForward);
  236. // Create a single test window.
  237. std::unique_ptr<Window> window0(CreateTestWindowInShellWithId(0));
  238. wm::ActivateWindow(window0.get());
  239. EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
  240. // Cycling works for a single window, even though nothing changes.
  241. controller->HandleCycleWindow(
  242. WindowCycleController::WindowCyclingDirection::kForward);
  243. EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
  244. }
  245. // Verifies if there is only one window and it isn't active that cycling
  246. // activates it.
  247. TEST_F(WindowCycleControllerTest, SingleWindowNotActive) {
  248. WindowCycleController* controller = Shell::Get()->window_cycle_controller();
  249. // Create a single test window.
  250. std::unique_ptr<Window> window0(CreateTestWindowInShellWithId(0));
  251. wm::ActivateWindow(window0.get());
  252. EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
  253. // Rotate focus, this should move focus to another window that isn't part of
  254. // the default container.
  255. Shell::Get()->focus_cycler()->RotateFocus(FocusCycler::FORWARD);
  256. EXPECT_FALSE(wm::IsActiveWindow(window0.get()));
  257. // Cycling should activate the window.
  258. controller->HandleCycleWindow(
  259. WindowCycleController::WindowCyclingDirection::kForward);
  260. EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
  261. }
  262. TEST_F(WindowCycleControllerTest, HandleCycleWindow) {
  263. WindowCycleController* controller = Shell::Get()->window_cycle_controller();
  264. // Set up several windows to use to test cycling. Create them in reverse
  265. // order so they are stacked 0 over 1 over 2.
  266. std::unique_ptr<Window> window2(CreateTestWindowInShellWithId(2));
  267. std::unique_ptr<Window> window1(CreateTestWindowInShellWithId(1));
  268. std::unique_ptr<Window> window0(CreateTestWindowInShellWithId(0));
  269. wm::ActivateWindow(window0.get());
  270. // Simulate pressing and releasing Alt-tab.
  271. EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
  272. controller->HandleCycleWindow(
  273. WindowCycleController::WindowCyclingDirection::kForward);
  274. // Window lists should return the topmost window in front.
  275. ASSERT_TRUE(controller->window_cycle_list());
  276. ASSERT_EQ(3u, GetWindows(controller).size());
  277. ASSERT_EQ(window0.get(), GetWindows(controller)[0]);
  278. ASSERT_EQ(window1.get(), GetWindows(controller)[1]);
  279. ASSERT_EQ(window2.get(), GetWindows(controller)[2]);
  280. CompleteCycling(controller);
  281. EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
  282. // Pressing and releasing Alt-tab again should cycle back to the most-
  283. // recently-used window in the current child order.
  284. controller->HandleCycleWindow(
  285. WindowCycleController::WindowCyclingDirection::kForward);
  286. CompleteCycling(controller);
  287. EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
  288. // Cancelled cycling shouldn't move the active window.
  289. controller->HandleCycleWindow(
  290. WindowCycleController::WindowCyclingDirection::kForward);
  291. controller->CancelCycling();
  292. EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
  293. // Pressing Alt-tab multiple times without releasing Alt should cycle through
  294. // all the windows and wrap around.
  295. controller->HandleCycleWindow(
  296. WindowCycleController::WindowCyclingDirection::kForward);
  297. EXPECT_TRUE(controller->IsCycling());
  298. controller->HandleCycleWindow(
  299. WindowCycleController::WindowCyclingDirection::kForward);
  300. EXPECT_TRUE(controller->IsCycling());
  301. controller->HandleCycleWindow(
  302. WindowCycleController::WindowCyclingDirection::kForward);
  303. EXPECT_TRUE(controller->IsCycling());
  304. CompleteCycling(controller);
  305. EXPECT_FALSE(controller->IsCycling());
  306. EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
  307. // Reset our stacking order.
  308. wm::ActivateWindow(window2.get());
  309. wm::ActivateWindow(window1.get());
  310. wm::ActivateWindow(window0.get());
  311. // Likewise we can cycle backwards through the windows.
  312. controller->HandleCycleWindow(
  313. WindowCycleController::WindowCyclingDirection::kBackward);
  314. controller->HandleCycleWindow(
  315. WindowCycleController::WindowCyclingDirection::kBackward);
  316. CompleteCycling(controller);
  317. EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
  318. // Reset our stacking order.
  319. wm::ActivateWindow(window2.get());
  320. wm::ActivateWindow(window1.get());
  321. wm::ActivateWindow(window0.get());
  322. // When the screen is locked, cycling window does not take effect.
  323. GetSessionControllerClient()->LockScreen();
  324. EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
  325. controller->HandleCycleWindow(
  326. WindowCycleController::WindowCyclingDirection::kForward);
  327. EXPECT_FALSE(controller->IsCycling());
  328. // Unlock, it works again.
  329. GetSessionControllerClient()->UnlockScreen();
  330. EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
  331. controller->HandleCycleWindow(
  332. WindowCycleController::WindowCyclingDirection::kForward);
  333. controller->HandleCycleWindow(
  334. WindowCycleController::WindowCyclingDirection::kForward);
  335. CompleteCycling(controller);
  336. EXPECT_TRUE(wm::IsActiveWindow(window2.get()));
  337. // When a modal window is active, cycling window does not take effect.
  338. aura::Window* modal_container = Shell::GetContainer(
  339. Shell::GetPrimaryRootWindow(), kShellWindowId_SystemModalContainer);
  340. std::unique_ptr<Window> modal_window(
  341. CreateTestWindowWithId(-2, modal_container));
  342. modal_window->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_SYSTEM);
  343. wm::ActivateWindow(modal_window.get());
  344. EXPECT_TRUE(wm::IsActiveWindow(modal_window.get()));
  345. controller->HandleCycleWindow(
  346. WindowCycleController::WindowCyclingDirection::kForward);
  347. EXPECT_TRUE(wm::IsActiveWindow(modal_window.get()));
  348. EXPECT_FALSE(controller->IsCycling());
  349. EXPECT_FALSE(wm::IsActiveWindow(window0.get()));
  350. EXPECT_FALSE(wm::IsActiveWindow(window1.get()));
  351. EXPECT_FALSE(wm::IsActiveWindow(window2.get()));
  352. controller->HandleCycleWindow(
  353. WindowCycleController::WindowCyclingDirection::kBackward);
  354. EXPECT_TRUE(wm::IsActiveWindow(modal_window.get()));
  355. EXPECT_FALSE(controller->IsCycling());
  356. EXPECT_FALSE(wm::IsActiveWindow(window0.get()));
  357. EXPECT_FALSE(wm::IsActiveWindow(window1.get()));
  358. EXPECT_FALSE(wm::IsActiveWindow(window2.get()));
  359. modal_window.reset();
  360. std::unique_ptr<Window> skip_overview_window(
  361. CreateTestWindowInShellWithId(-3));
  362. skip_overview_window->SetProperty(kHideInOverviewKey, true);
  363. wm::ActivateWindow(window0.get());
  364. wm::ActivateWindow(skip_overview_window.get());
  365. wm::ActivateWindow(window1.get());
  366. EXPECT_FALSE(wm::IsActiveWindow(window0.get()));
  367. controller->HandleCycleWindow(
  368. WindowCycleController::WindowCyclingDirection::kForward);
  369. CompleteCycling(controller);
  370. EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
  371. EXPECT_FALSE(wm::IsActiveWindow(skip_overview_window.get()));
  372. EXPECT_FALSE(wm::IsActiveWindow(window1.get()));
  373. }
  374. // Cycles between a maximized and normal window.
  375. TEST_F(WindowCycleControllerTest, MaximizedWindow) {
  376. // Create a couple of test windows.
  377. std::unique_ptr<Window> window0(CreateTestWindowInShellWithId(0));
  378. std::unique_ptr<Window> window1(CreateTestWindowInShellWithId(1));
  379. WindowState* window1_state = WindowState::Get(window1.get());
  380. window1_state->Maximize();
  381. window1_state->Activate();
  382. EXPECT_TRUE(window1_state->IsActive());
  383. // Rotate focus, this should move focus to window0.
  384. WindowCycleController* controller = Shell::Get()->window_cycle_controller();
  385. controller->HandleCycleWindow(
  386. WindowCycleController::WindowCyclingDirection::kForward);
  387. CompleteCycling(controller);
  388. EXPECT_TRUE(WindowState::Get(window0.get())->IsActive());
  389. EXPECT_FALSE(window1_state->IsActive());
  390. // One more time.
  391. controller->HandleCycleWindow(
  392. WindowCycleController::WindowCyclingDirection::kForward);
  393. CompleteCycling(controller);
  394. EXPECT_TRUE(window1_state->IsActive());
  395. }
  396. // Cycles to a minimized window.
  397. TEST_F(WindowCycleControllerTest, Minimized) {
  398. // Create a couple of test windows.
  399. std::unique_ptr<Window> window0(CreateTestWindowInShellWithId(0));
  400. std::unique_ptr<Window> window1(CreateTestWindowInShellWithId(1));
  401. WindowState* window0_state = WindowState::Get(window0.get());
  402. WindowState* window1_state = WindowState::Get(window1.get());
  403. window1_state->Minimize();
  404. window0_state->Activate();
  405. EXPECT_TRUE(window0_state->IsActive());
  406. // Rotate focus, this should move focus to window1 and unminimize it.
  407. WindowCycleController* controller = Shell::Get()->window_cycle_controller();
  408. controller->HandleCycleWindow(
  409. WindowCycleController::WindowCyclingDirection::kForward);
  410. CompleteCycling(controller);
  411. EXPECT_FALSE(window0_state->IsActive());
  412. EXPECT_FALSE(window1_state->IsMinimized());
  413. EXPECT_TRUE(window1_state->IsActive());
  414. // One more time back to w0.
  415. controller->HandleCycleWindow(
  416. WindowCycleController::WindowCyclingDirection::kForward);
  417. CompleteCycling(controller);
  418. EXPECT_TRUE(window0_state->IsActive());
  419. }
  420. // Tests that when all windows are minimized, cycling starts with the first one
  421. // rather than the second.
  422. TEST_F(WindowCycleControllerTest, AllAreMinimized) {
  423. // Create a couple of test windows.
  424. std::unique_ptr<Window> window0(CreateTestWindowInShellWithId(0));
  425. std::unique_ptr<Window> window1(CreateTestWindowInShellWithId(1));
  426. WindowState* window0_state = WindowState::Get(window0.get());
  427. WindowState* window1_state = WindowState::Get(window1.get());
  428. window0_state->Minimize();
  429. window1_state->Minimize();
  430. WindowCycleController* controller = Shell::Get()->window_cycle_controller();
  431. controller->HandleCycleWindow(
  432. WindowCycleController::WindowCyclingDirection::kForward);
  433. CompleteCycling(controller);
  434. EXPECT_TRUE(window1_state->IsActive());
  435. EXPECT_FALSE(window1_state->IsMinimized());
  436. EXPECT_TRUE(window0_state->IsMinimized());
  437. // But it's business as usual when cycling backwards.
  438. window0_state->Minimize();
  439. window1_state->Minimize();
  440. controller->HandleCycleWindow(
  441. WindowCycleController::WindowCyclingDirection::kBackward);
  442. CompleteCycling(controller);
  443. EXPECT_TRUE(window0_state->IsActive());
  444. EXPECT_FALSE(window0_state->IsMinimized());
  445. EXPECT_TRUE(window1_state->IsMinimized());
  446. }
  447. TEST_F(WindowCycleControllerTest, AlwaysOnTopWindow) {
  448. WindowCycleController* controller = Shell::Get()->window_cycle_controller();
  449. // Set up several windows to use to test cycling.
  450. std::unique_ptr<Window> window0(CreateTestWindowInShellWithId(0));
  451. std::unique_ptr<Window> window1(CreateTestWindowInShellWithId(1));
  452. Window* top_container = Shell::GetContainer(
  453. Shell::GetPrimaryRootWindow(), kShellWindowId_AlwaysOnTopContainer);
  454. std::unique_ptr<Window> window2(CreateTestWindowWithId(2, top_container));
  455. wm::ActivateWindow(window0.get());
  456. // Simulate pressing and releasing Alt-tab.
  457. EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
  458. controller->HandleCycleWindow(
  459. WindowCycleController::WindowCyclingDirection::kForward);
  460. // Window lists should return the topmost window in front.
  461. ASSERT_TRUE(controller->window_cycle_list());
  462. ASSERT_EQ(3u, GetWindows(controller).size());
  463. EXPECT_EQ(window0.get(), GetWindows(controller)[0]);
  464. EXPECT_EQ(window2.get(), GetWindows(controller)[1]);
  465. EXPECT_EQ(window1.get(), GetWindows(controller)[2]);
  466. CompleteCycling(controller);
  467. }
  468. TEST_F(WindowCycleControllerTest, AlwaysOnTopMultiWindow) {
  469. WindowCycleController* controller = Shell::Get()->window_cycle_controller();
  470. // Set up several windows to use to test cycling.
  471. std::unique_ptr<Window> window0(CreateTestWindowInShellWithId(0));
  472. std::unique_ptr<Window> window1(CreateTestWindowInShellWithId(1));
  473. Window* top_container = Shell::GetContainer(
  474. Shell::GetPrimaryRootWindow(), kShellWindowId_AlwaysOnTopContainer);
  475. std::unique_ptr<Window> window2(CreateTestWindowWithId(2, top_container));
  476. std::unique_ptr<Window> window3(CreateTestWindowWithId(3, top_container));
  477. wm::ActivateWindow(window0.get());
  478. // Simulate pressing and releasing Alt-tab.
  479. EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
  480. controller->HandleCycleWindow(
  481. WindowCycleController::WindowCyclingDirection::kForward);
  482. // Window lists should return the topmost window in front.
  483. ASSERT_TRUE(controller->window_cycle_list());
  484. ASSERT_EQ(4u, GetWindows(controller).size());
  485. EXPECT_EQ(window0.get(), GetWindows(controller)[0]);
  486. EXPECT_EQ(window3.get(), GetWindows(controller)[1]);
  487. EXPECT_EQ(window2.get(), GetWindows(controller)[2]);
  488. EXPECT_EQ(window1.get(), GetWindows(controller)[3]);
  489. CompleteCycling(controller);
  490. }
  491. TEST_F(WindowCycleControllerTest, AlwaysOnTopMultipleRootWindows) {
  492. // Set up a second root window
  493. UpdateDisplay("1000x600,600x400");
  494. aura::Window::Windows root_windows = Shell::GetAllRootWindows();
  495. ASSERT_EQ(2U, root_windows.size());
  496. WindowCycleController* controller = Shell::Get()->window_cycle_controller();
  497. // Create two windows in the primary root.
  498. std::unique_ptr<Window> window0(CreateTestWindowInShellWithId(0));
  499. EXPECT_EQ(root_windows[0], window0->GetRootWindow());
  500. Window* top_container0 =
  501. Shell::GetContainer(root_windows[0], kShellWindowId_AlwaysOnTopContainer);
  502. std::unique_ptr<Window> window1(CreateTestWindowWithId(1, top_container0));
  503. EXPECT_EQ(root_windows[0], window1->GetRootWindow());
  504. // Move the active root window to the secondary root and create two windows.
  505. display::ScopedDisplayForNewWindows display_for_new_windows(root_windows[1]);
  506. std::unique_ptr<Window> window2(CreateTestWindowInShellWithId(2));
  507. EXPECT_EQ(root_windows[1], window2->GetRootWindow());
  508. Window* top_container1 =
  509. Shell::GetContainer(root_windows[1], kShellWindowId_AlwaysOnTopContainer);
  510. std::unique_ptr<Window> window3(CreateTestWindowWithId(3, top_container1));
  511. EXPECT_EQ(root_windows[1], window3->GetRootWindow());
  512. wm::ActivateWindow(window2.get());
  513. EXPECT_EQ(root_windows[0], window0->GetRootWindow());
  514. EXPECT_EQ(root_windows[0], window1->GetRootWindow());
  515. EXPECT_EQ(root_windows[1], window2->GetRootWindow());
  516. EXPECT_EQ(root_windows[1], window3->GetRootWindow());
  517. // Simulate pressing and releasing Alt-tab.
  518. EXPECT_TRUE(wm::IsActiveWindow(window2.get()));
  519. controller->HandleCycleWindow(
  520. WindowCycleController::WindowCyclingDirection::kForward);
  521. // Window lists should return the topmost window in front.
  522. ASSERT_TRUE(controller->window_cycle_list());
  523. ASSERT_EQ(4u, GetWindows(controller).size());
  524. EXPECT_EQ(window2.get(), GetWindows(controller)[0]);
  525. EXPECT_EQ(window3.get(), GetWindows(controller)[1]);
  526. EXPECT_EQ(window1.get(), GetWindows(controller)[2]);
  527. EXPECT_EQ(window0.get(), GetWindows(controller)[3]);
  528. CompleteCycling(controller);
  529. }
  530. TEST_F(WindowCycleControllerTest, MostRecentlyUsed) {
  531. WindowCycleController* controller = Shell::Get()->window_cycle_controller();
  532. // Set up several windows to use to test cycling.
  533. std::unique_ptr<Window> window0(CreateTestWindowInShellWithId(0));
  534. std::unique_ptr<Window> window1(CreateTestWindowInShellWithId(1));
  535. std::unique_ptr<Window> window2(CreateTestWindowInShellWithId(2));
  536. wm::ActivateWindow(window0.get());
  537. // Simulate pressing and releasing Alt-tab.
  538. EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
  539. controller->HandleCycleWindow(
  540. WindowCycleController::WindowCyclingDirection::kForward);
  541. // Window lists should return the topmost window in front.
  542. ASSERT_TRUE(controller->window_cycle_list());
  543. ASSERT_EQ(3u, GetWindows(controller).size());
  544. EXPECT_EQ(window0.get(), GetWindows(controller)[0]);
  545. EXPECT_EQ(window2.get(), GetWindows(controller)[1]);
  546. EXPECT_EQ(window1.get(), GetWindows(controller)[2]);
  547. // Cycling through then stopping the cycling will activate a window.
  548. controller->HandleCycleWindow(
  549. WindowCycleController::WindowCyclingDirection::kForward);
  550. CompleteCycling(controller);
  551. EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
  552. // Cycling alone (without CompleteCycling()) doesn't activate.
  553. controller->HandleCycleWindow(
  554. WindowCycleController::WindowCyclingDirection::kForward);
  555. EXPECT_FALSE(wm::IsActiveWindow(window0.get()));
  556. CompleteCycling(controller);
  557. }
  558. // Tests that beginning window selection hides the app list.
  559. TEST_F(WindowCycleControllerTest, SelectingHidesAppList) {
  560. WindowCycleController* controller = Shell::Get()->window_cycle_controller();
  561. std::unique_ptr<aura::Window> window0(CreateTestWindowInShellWithId(0));
  562. std::unique_ptr<aura::Window> window1(CreateTestWindowInShellWithId(1));
  563. wm::ActivateWindow(window0.get());
  564. GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplay().id());
  565. GetAppListTestHelper()->CheckVisibility(true);
  566. controller->HandleCycleWindow(
  567. WindowCycleController::WindowCyclingDirection::kForward);
  568. GetAppListTestHelper()->WaitUntilIdle();
  569. GetAppListTestHelper()->CheckVisibility(false);
  570. // Make sure that dismissing the app list this way doesn't pass activation
  571. // to a different window.
  572. EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
  573. EXPECT_FALSE(wm::IsActiveWindow(window1.get()));
  574. CompleteCycling(controller);
  575. }
  576. // Tests that beginning window selection doesn't hide the app list in tablet
  577. // mode.
  578. TEST_F(WindowCycleControllerTest, SelectingDoesNotHideAppListInTabletMode) {
  579. TabletModeControllerTestApi().EnterTabletMode();
  580. EXPECT_TRUE(TabletModeControllerTestApi().IsTabletModeStarted());
  581. EXPECT_TRUE(Shell::Get()->app_list_controller()->IsHomeScreenVisible());
  582. std::unique_ptr<aura::Window> window0(CreateTestWindowInShellWithId(0));
  583. std::unique_ptr<aura::Window> window1(CreateTestWindowInShellWithId(1));
  584. wm::ActivateWindow(window0.get());
  585. WindowCycleController* controller = Shell::Get()->window_cycle_controller();
  586. controller->HandleCycleWindow(
  587. WindowCycleController::WindowCyclingDirection::kForward);
  588. window0->Hide();
  589. window1->Hide();
  590. EXPECT_TRUE(Shell::Get()->app_list_controller()->IsHomeScreenVisible());
  591. }
  592. // Tests that cycling through windows doesn't change their minimized state.
  593. TEST_F(WindowCycleControllerTest, CyclePreservesMinimization) {
  594. WindowCycleController* controller = Shell::Get()->window_cycle_controller();
  595. std::unique_ptr<aura::Window> window0(CreateTestWindowInShellWithId(0));
  596. std::unique_ptr<aura::Window> window1(CreateTestWindowInShellWithId(1));
  597. wm::ActivateWindow(window1.get());
  598. WindowState::Get(window1.get())->Minimize();
  599. wm::ActivateWindow(window0.get());
  600. EXPECT_TRUE(IsWindowMinimized(window1.get()));
  601. // On window 2.
  602. controller->HandleCycleWindow(
  603. WindowCycleController::WindowCyclingDirection::kForward);
  604. EXPECT_TRUE(IsWindowMinimized(window1.get()));
  605. // Back on window 1.
  606. controller->HandleCycleWindow(
  607. WindowCycleController::WindowCyclingDirection::kForward);
  608. EXPECT_TRUE(IsWindowMinimized(window1.get()));
  609. CompleteCycling(controller);
  610. EXPECT_TRUE(IsWindowMinimized(window1.get()));
  611. }
  612. // Tests that the tab key events are not sent to the window.
  613. TEST_F(WindowCycleControllerTest, TabKeyNotLeaked) {
  614. std::unique_ptr<Window> w0(CreateTestWindowInShellWithId(0));
  615. std::unique_ptr<Window> w1(CreateTestWindowInShellWithId(1));
  616. EventCounter event_count;
  617. w0->AddPreTargetHandler(&event_count);
  618. w1->AddPreTargetHandler(&event_count);
  619. ui::test::EventGenerator* generator = GetEventGenerator();
  620. WindowState::Get(w0.get())->Activate();
  621. generator->PressKey(ui::VKEY_MENU, ui::EF_NONE);
  622. EXPECT_EQ(1, event_count.GetKeyEventCountAndReset());
  623. generator->PressKey(ui::VKEY_TAB, ui::EF_ALT_DOWN);
  624. EXPECT_EQ(0, event_count.GetKeyEventCountAndReset());
  625. generator->ReleaseKey(ui::VKEY_TAB, ui::EF_ALT_DOWN);
  626. EXPECT_EQ(0, event_count.GetKeyEventCountAndReset());
  627. generator->ReleaseKey(ui::VKEY_MENU, ui::EF_NONE);
  628. EXPECT_TRUE(WindowState::Get(w1.get())->IsActive());
  629. EXPECT_EQ(0, event_count.GetKeyEventCountAndReset());
  630. }
  631. // Tests that we can cycle past fullscreen windows: https://crbug.com/622396.
  632. // Fullscreen windows are special in that they are allowed to handle alt+tab
  633. // keypresses, which means the window cycle event filter should not handle
  634. // the tab press else it prevents cycling past that window.
  635. TEST_F(WindowCycleControllerTest, TabPastFullscreenWindow) {
  636. std::unique_ptr<Window> w0(CreateTestWindowInShellWithId(0));
  637. std::unique_ptr<Window> w1(CreateTestWindowInShellWithId(1));
  638. WMEvent maximize_event(WM_EVENT_FULLSCREEN);
  639. // To make this test work with or without the new alt+tab selector we make
  640. // both the initial window and the second window fullscreen.
  641. WindowState::Get(w0.get())->OnWMEvent(&maximize_event);
  642. WindowState::Get(w1.get())->Activate();
  643. WindowState::Get(w1.get())->OnWMEvent(&maximize_event);
  644. EXPECT_TRUE(WindowState::Get(w0.get())->IsFullscreen());
  645. EXPECT_TRUE(WindowState::Get(w1.get())->IsFullscreen());
  646. WindowState::Get(w0.get())->Activate();
  647. EXPECT_TRUE(WindowState::Get(w0.get())->IsActive());
  648. ui::test::EventGenerator* generator = GetEventGenerator();
  649. generator->PressKey(ui::VKEY_MENU, ui::EF_NONE);
  650. generator->PressKey(ui::VKEY_TAB, ui::EF_ALT_DOWN);
  651. generator->ReleaseKey(ui::VKEY_TAB, ui::EF_ALT_DOWN);
  652. // Because w0 and w1 are full-screen, the event should be passed to the
  653. // browser window to handle it (which if the browser doesn't handle it will
  654. // pass on the alt+tab to continue cycling). To make this test work with or
  655. // without the new alt+tab selector we check for the event on either
  656. // fullscreen window.
  657. EventCounter event_count;
  658. w0->AddPreTargetHandler(&event_count);
  659. w1->AddPreTargetHandler(&event_count);
  660. generator->PressKey(ui::VKEY_TAB, ui::EF_ALT_DOWN);
  661. EXPECT_EQ(1, event_count.GetKeyEventCountAndReset());
  662. }
  663. // Tests that the Alt+Tab UI's position isn't affected by the origin of the
  664. // display it's on. See crbug.com/675718
  665. TEST_F(WindowCycleControllerTest, MultiDisplayPositioning) {
  666. int64_t primary_id = GetPrimaryDisplay().id();
  667. display::DisplayIdList list =
  668. display::test::CreateDisplayIdListN(primary_id, 2);
  669. auto placements = {
  670. display::DisplayPlacement::BOTTOM,
  671. display::DisplayPlacement::TOP,
  672. display::DisplayPlacement::LEFT,
  673. display::DisplayPlacement::RIGHT,
  674. };
  675. gfx::Rect expected_bounds;
  676. for (auto placement : placements) {
  677. SCOPED_TRACE(placement);
  678. display::DisplayLayoutBuilder builder(primary_id);
  679. builder.AddDisplayPlacement(list[1], primary_id, placement, 0);
  680. display_manager()->layout_store()->RegisterLayoutForDisplayIdList(
  681. list, builder.Build());
  682. // Use two displays.
  683. UpdateDisplay("500x400,600x500");
  684. gfx::Rect second_display_bounds =
  685. display_manager()->GetDisplayAt(1).bounds();
  686. std::unique_ptr<Window> window0(
  687. CreateTestWindowInShellWithBounds(second_display_bounds));
  688. // Activate this window so that the secondary display becomes the one where
  689. // the Alt+Tab UI is shown.
  690. wm::ActivateWindow(window0.get());
  691. std::unique_ptr<Window> window1(
  692. CreateTestWindowInShellWithBounds(second_display_bounds));
  693. WindowCycleController* controller = Shell::Get()->window_cycle_controller();
  694. controller->HandleCycleWindow(
  695. WindowCycleController::WindowCyclingDirection::kForward);
  696. const gfx::Rect bounds =
  697. GetWindowCycleListWidget()->GetWindowBoundsInScreen();
  698. EXPECT_TRUE(second_display_bounds.Contains(bounds));
  699. EXPECT_FALSE(
  700. display_manager()->GetDisplayAt(0).bounds().Intersects(bounds));
  701. const gfx::Rect display_relative_bounds =
  702. bounds - second_display_bounds.OffsetFromOrigin();
  703. // Base case sets the expectation for other cases.
  704. if (expected_bounds.IsEmpty())
  705. expected_bounds = display_relative_bounds;
  706. else
  707. EXPECT_EQ(expected_bounds, display_relative_bounds);
  708. CompleteCycling(controller);
  709. }
  710. }
  711. TEST_F(WindowCycleControllerTest, CycleShowsAllDesksWindows) {
  712. auto win0 = CreateAppWindow(gfx::Rect(0, 0, 250, 100));
  713. auto win1 = CreateAppWindow(gfx::Rect(50, 50, 200, 200));
  714. auto* desks_controller = DesksController::Get();
  715. desks_controller->NewDesk(DesksCreationRemovalSource::kButton);
  716. desks_controller->NewDesk(DesksCreationRemovalSource::kButton);
  717. ASSERT_EQ(3u, desks_controller->desks().size());
  718. const Desk* desk_2 = desks_controller->desks()[1].get();
  719. ActivateDesk(desk_2);
  720. EXPECT_EQ(desk_2, desks_controller->active_desk());
  721. auto win2 = CreateAppWindow(gfx::Rect(0, 0, 300, 200));
  722. const Desk* desk_3 = desks_controller->desks()[2].get();
  723. ActivateDesk(desk_3);
  724. EXPECT_EQ(desk_3, desks_controller->active_desk());
  725. auto win3 = CreateAppWindow(gfx::Rect(10, 30, 400, 200));
  726. WindowCycleController* cycle_controller =
  727. Shell::Get()->window_cycle_controller();
  728. cycle_controller->HandleCycleWindow(
  729. WindowCycleController::WindowCyclingDirection::kForward);
  730. // All desks' windows are included in the cycle list.
  731. auto cycle_windows = GetWindows(cycle_controller);
  732. EXPECT_EQ(4u, cycle_windows.size());
  733. EXPECT_TRUE(base::Contains(cycle_windows, win0.get()));
  734. EXPECT_TRUE(base::Contains(cycle_windows, win1.get()));
  735. EXPECT_TRUE(base::Contains(cycle_windows, win2.get()));
  736. EXPECT_TRUE(base::Contains(cycle_windows, win3.get()));
  737. // The MRU order is {win3, win2, win1, win0}. We're now at win2. Cycling one
  738. // more time and completing the cycle, will activate win1 which exists on a
  739. // desk_1. This should activate desk_1.
  740. {
  741. base::HistogramTester histogram_tester;
  742. cycle_controller->HandleCycleWindow(
  743. WindowCycleController::WindowCyclingDirection::kForward);
  744. CompleteCyclingAndDeskSwitching(cycle_controller);
  745. Desk* desk_1 = desks_controller->desks()[0].get();
  746. EXPECT_EQ(desk_1, desks_controller->active_desk());
  747. EXPECT_EQ(win1.get(), window_util::GetActiveWindow());
  748. histogram_tester.ExpectUniqueSample(
  749. "Ash.WindowCycleController.DesksSwitchDistance",
  750. /*desk distance of 3 - 1 = */ 2, /*expected_count=*/1);
  751. }
  752. // Cycle again and activate win2, which exist on desk_2. Expect that desk to
  753. // be activated, and a histogram sample of distance of 1 is recorded.
  754. // MRU is {win1, win3, win2, win0}.
  755. {
  756. base::HistogramTester histogram_tester;
  757. cycle_controller->HandleCycleWindow(
  758. WindowCycleController::WindowCyclingDirection::kForward);
  759. cycle_controller->HandleCycleWindow(
  760. WindowCycleController::WindowCyclingDirection::kForward);
  761. CompleteCyclingAndDeskSwitching(cycle_controller);
  762. EXPECT_EQ(desk_2, desks_controller->active_desk());
  763. EXPECT_EQ(win2.get(), window_util::GetActiveWindow());
  764. histogram_tester.ExpectUniqueSample(
  765. "Ash.WindowCycleController.DesksSwitchDistance",
  766. /*desk distance of 2 - 1 = */ 1, /*expected_count=*/1);
  767. }
  768. }
  769. // Tests that frame throttling starts and ends accordingly when window cycling
  770. // starts and ends.
  771. TEST_F(WindowCycleControllerTest, FrameThrottling) {
  772. FrameThrottlingController* frame_throttling_controller =
  773. Shell::Get()->frame_throttling_controller();
  774. const int window_count = 5;
  775. std::vector<viz::FrameSinkId> ids{
  776. {1u, 1u}, {2u, 2u}, {3u, 3u}, {4u, 4u}, {5u, 5u}};
  777. std::unique_ptr<aura::Window> windows[window_count];
  778. for (int i = 0; i < window_count; ++i) {
  779. windows[i] = CreateAppWindow(gfx::Rect(), AppType::BROWSER);
  780. windows[i]->SetEmbedFrameSinkId(ids[i]);
  781. }
  782. WindowCycleController* controller = Shell::Get()->window_cycle_controller();
  783. controller->HandleCycleWindow(
  784. WindowCycleController::WindowCyclingDirection::kForward);
  785. EXPECT_THAT(frame_throttling_controller->GetFrameSinkIdsToThrottle(),
  786. testing::UnorderedElementsAreArray(ids));
  787. controller->HandleCycleWindow(
  788. WindowCycleController::WindowCyclingDirection::kForward);
  789. EXPECT_THAT(frame_throttling_controller->GetFrameSinkIdsToThrottle(),
  790. testing::UnorderedElementsAreArray(ids));
  791. CompleteCycling(controller);
  792. EXPECT_TRUE(frame_throttling_controller->GetFrameSinkIdsToThrottle().empty());
  793. controller->HandleCycleWindow(
  794. WindowCycleController::WindowCyclingDirection::kForward);
  795. EXPECT_THAT(frame_throttling_controller->GetFrameSinkIdsToThrottle(),
  796. testing::UnorderedElementsAreArray(ids));
  797. controller->CancelCycling();
  798. EXPECT_TRUE(frame_throttling_controller->GetFrameSinkIdsToThrottle().empty());
  799. }
  800. // Tests that pressing Alt+Tab while there is an on-going desk animation
  801. // prevents a new window cycle from starting.
  802. TEST_F(WindowCycleControllerTest, DoubleAltTabWithDeskSwitch) {
  803. WindowCycleController* cycle_controller =
  804. Shell::Get()->window_cycle_controller();
  805. auto win0 = CreateAppWindow(gfx::Rect(250, 100));
  806. auto* desks_controller = DesksController::Get();
  807. desks_controller->NewDesk(DesksCreationRemovalSource::kButton);
  808. ASSERT_EQ(2u, desks_controller->desks().size());
  809. const Desk* desk_0 = desks_controller->desks()[0].get();
  810. const Desk* desk_1 = desks_controller->desks()[1].get();
  811. ActivateDesk(desk_1);
  812. EXPECT_EQ(desk_1, desks_controller->active_desk());
  813. auto win1 = CreateAppWindow(gfx::Rect(300, 200));
  814. ASSERT_EQ(win1.get(), window_util::GetActiveWindow());
  815. auto desk_1_windows = desk_1->windows();
  816. EXPECT_EQ(1u, desk_1_windows.size());
  817. EXPECT_TRUE(base::Contains(desk_1_windows, win1.get()));
  818. DeskSwitchAnimationWaiter waiter;
  819. cycle_controller->HandleCycleWindow(
  820. WindowCycleController::WindowCyclingDirection::kForward);
  821. cycle_controller->CompleteCycling();
  822. EXPECT_FALSE(cycle_controller->CanCycle());
  823. cycle_controller->HandleCycleWindow(
  824. WindowCycleController::WindowCyclingDirection::kForward);
  825. EXPECT_FALSE(cycle_controller->IsCycling());
  826. waiter.Wait();
  827. EXPECT_EQ(desk_0, desks_controller->active_desk());
  828. EXPECT_EQ(win0.get(), window_util::GetActiveWindow());
  829. }
  830. // A regression test for crbug.com/1160676. Tests that the alt-key release
  831. // to quit alt-tab is acknowledged by the accelerator controller.
  832. TEST_F(WindowCycleControllerTest, AltKeyRelease) {
  833. std::unique_ptr<Window> window0(CreateTestWindowInShellWithId(0));
  834. std::unique_ptr<Window> window1(CreateTestWindowInShellWithId(1));
  835. wm::ActivateWindow(window1.get());
  836. // Press Alt and start cycling.
  837. auto* generator = GetEventGenerator();
  838. generator->PressKey(ui::VKEY_MENU, ui::EF_NONE);
  839. auto currently_pressed_keys = Shell::Get()
  840. ->accelerator_controller()
  841. ->GetAcceleratorHistory()
  842. ->currently_pressed_keys();
  843. // Expect exactly one key pressed, which is Alt.
  844. EXPECT_EQ(1u, currently_pressed_keys.size());
  845. EXPECT_TRUE(base::Contains(currently_pressed_keys, ui::VKEY_MENU));
  846. WindowCycleController* controller = Shell::Get()->window_cycle_controller();
  847. controller->HandleCycleWindow(
  848. WindowCycleController::WindowCyclingDirection::kForward);
  849. // Release Alt key to end alt-tab cycling and open up window0.
  850. generator->ReleaseKey(ui::VKEY_MENU, ui::EF_NONE);
  851. EXPECT_FALSE(controller->IsCycling());
  852. EXPECT_TRUE(WindowState::Get(window0.get())->IsActive());
  853. // Expect all keys pressed to be released.
  854. currently_pressed_keys = Shell::Get()
  855. ->accelerator_controller()
  856. ->GetAcceleratorHistory()
  857. ->currently_pressed_keys();
  858. EXPECT_EQ(0u, currently_pressed_keys.size());
  859. EXPECT_FALSE(base::Contains(currently_pressed_keys, ui::VKEY_MENU));
  860. }
  861. // Tests that system tray will be closed when alt-tab cycling starts. Also tests
  862. // releasing the alt key will end the alt-tab cycling successfully.
  863. TEST_F(WindowCycleControllerTest, AltKeyReleaseOnSystemTrayOpen) {
  864. std::unique_ptr<Window> window0(CreateTestWindowInShellWithId(0));
  865. std::unique_ptr<Window> window1(CreateTestWindowInShellWithId(1));
  866. WindowCycleController* controller = Shell::Get()->window_cycle_controller();
  867. ui::test::EventGenerator* event_generator = GetEventGenerator();
  868. // Open system tray.
  869. auto* system_tray = GetPrimaryUnifiedSystemTray();
  870. event_generator->MoveMouseTo(system_tray->GetBoundsInScreen().CenterPoint());
  871. event_generator->ClickLeftButton();
  872. EXPECT_TRUE(system_tray->IsBubbleShown());
  873. // Start window cycling by press Alt + Tab key.
  874. WindowState::Get(window0.get())->Activate();
  875. event_generator->PressKey(ui::VKEY_MENU, ui::EF_NONE);
  876. event_generator->PressKey(ui::VKEY_TAB, ui::EF_ALT_DOWN);
  877. EXPECT_TRUE(controller->IsCycling());
  878. // Verify the system tray is closed after the alt-tab cycling starts.
  879. EXPECT_FALSE(system_tray->IsBubbleShown());
  880. // Release Alt key, verify alt-tab cycling is ended.
  881. event_generator->ReleaseKey(ui::VKEY_MENU, ui::EF_NONE);
  882. EXPECT_FALSE(controller->IsCycling());
  883. }
  884. // Test alt-tab will be shown on the display where the cursor is located
  885. // when there are 2 displays,
  886. TEST_F(WindowCycleControllerTest, AltTabMultiDisplay) {
  887. // |features::kWindowsFollowCursor| enables alt-tab based on cursor position
  888. // when there's multiple displays.
  889. base::test::ScopedFeatureList scoped_feature_list;
  890. scoped_feature_list.InitWithFeatures({features::kWindowsFollowCursor}, {});
  891. UpdateDisplay("500x400,401+0-800x700");
  892. std::unique_ptr<Window> w0 = CreateTestWindow(gfx::Rect(200, 200));
  893. std::unique_ptr<Window> w1 = CreateTestWindow(gfx::Rect(420, 10, 200, 200));
  894. // |w0| needs to be activated to ensure it is the display for new windows.
  895. wm::ActivateWindow(w0.get());
  896. // TODO(crbug.com/990589): Unit tests should be able to simulate mouse input
  897. // without having to call |CursorManager::SetDisplay|.
  898. Shell::Get()->cursor_manager()->SetDisplay(
  899. display::Screen::GetScreen()->GetDisplayNearestWindow(w1.get()));
  900. // Test alt-tab activates on second display where the cursor point at, not
  901. // the display for new windows.
  902. WindowCycleController* cycle_controller =
  903. Shell::Get()->window_cycle_controller();
  904. cycle_controller->StartCycling();
  905. EXPECT_TRUE(cycle_controller->IsCycling());
  906. auto preview_items = GetWindowCycleItemViews();
  907. ASSERT_EQ(2u, preview_items.size());
  908. // Ensure preview is generated in secondary display where cursor is at.
  909. auto preview_display = display::Screen::GetScreen()->GetDisplayNearestWindow(
  910. GetWindowCycleListWidget()->GetNativeWindow());
  911. EXPECT_EQ(Shell::Get()->cursor_manager()->GetDisplay(), preview_display);
  912. CompleteCycling(cycle_controller);
  913. }
  914. // Test that alt-tab handles window destruction properly.
  915. TEST_F(WindowCycleControllerTest, WindowDestruction) {
  916. std::unique_ptr<Window> w0 = CreateTestWindow();
  917. std::unique_ptr<Window> w1 = CreateTestWindow();
  918. std::unique_ptr<Window> w2 = CreateTestWindow();
  919. // Start cycling and then destroy a window. We should still be cycling and
  920. // there should now only be two items.
  921. auto* controller = Shell::Get()->window_cycle_controller();
  922. controller->StartCycling();
  923. EXPECT_TRUE(controller->IsCycling());
  924. w1.reset();
  925. EXPECT_TRUE(controller->IsCycling());
  926. EXPECT_EQ(2u, GetWindows(controller).size());
  927. }
  928. // Tests that when the cycle view is not open, the event filter does not check
  929. // whether events occur within the cycle view.
  930. TEST_F(WindowCycleControllerTest, MouseEventWhenCycleViewDoesNotExist) {
  931. aura::test::TestWindowDelegate delegate;
  932. std::unique_ptr<Window> w0(CreateTestWindowInShellWithDelegate(
  933. &delegate, 0, gfx::Rect(0, 0, 100, 100)));
  934. EventCounter event_count;
  935. w0->AddPreTargetHandler(&event_count);
  936. ui::test::EventGenerator* generator = GetEventGenerator();
  937. WindowCycleController* controller = Shell::Get()->window_cycle_controller();
  938. // Mouse events get through if the cycle view is not open.
  939. // Cycling with one window open ensures the UI doesn't show but the event
  940. // filter is.
  941. controller->HandleCycleWindow(
  942. WindowCycleController::WindowCyclingDirection::kForward);
  943. generator->MoveMouseToCenterOf(w0.get());
  944. generator->ClickLeftButton();
  945. EXPECT_TRUE(controller->IsCycling());
  946. EXPECT_FALSE(CycleViewExists());
  947. EXPECT_LT(0, event_count.GetMouseEventCountAndReset());
  948. CompleteCycling(controller);
  949. }
  950. // When a user hovers their mouse over an item, it should cycle to it.
  951. // The items in the list should not move, only the focus ring.
  952. // If a user clicks on an item, it should complete cycling and activate
  953. // the hovered item.
  954. TEST_F(WindowCycleControllerTest, MouseHoverAndSelect) {
  955. std::unique_ptr<Window> w0 = CreateTestWindow();
  956. std::unique_ptr<Window> w1 = CreateTestWindow();
  957. std::unique_ptr<Window> w2 = CreateTestWindow();
  958. std::unique_ptr<Window> w3 = CreateTestWindow();
  959. std::unique_ptr<Window> w4 = CreateTestWindow();
  960. std::unique_ptr<Window> w5 = CreateTestWindow();
  961. std::unique_ptr<Window> w6 = CreateTestWindow();
  962. ui::test::EventGenerator* generator = GetEventGenerator();
  963. WindowCycleController* controller = Shell::Get()->window_cycle_controller();
  964. // Cycle to the third item, mouse over second item, and release alt-tab.
  965. // Starting order of windows in cycle list is [6,5,4,3,2,1,0].
  966. controller->HandleCycleWindow(
  967. WindowCycleController::WindowCyclingDirection::kForward);
  968. controller->HandleCycleWindow(
  969. WindowCycleController::WindowCyclingDirection::kForward);
  970. gfx::Point target_item_center =
  971. GetWindowCycleItemViews()[1]->GetBoundsInScreen().CenterPoint();
  972. generator->MoveMouseTo(target_item_center);
  973. EXPECT_EQ(target_item_center,
  974. GetWindowCycleItemViews()[1]->GetBoundsInScreen().CenterPoint());
  975. CompleteCycling(controller);
  976. EXPECT_TRUE(wm::IsActiveWindow(w5.get()));
  977. // Start cycle, mouse over third item, and release alt-tab.
  978. // Starting order of windows in cycle list is [5,6,4,3,2,1,0].
  979. controller->StartCycling();
  980. target_item_center =
  981. GetWindowCycleItemViews()[2]->GetBoundsInScreen().CenterPoint();
  982. generator->MoveMouseTo(target_item_center);
  983. EXPECT_EQ(target_item_center,
  984. GetWindowCycleItemViews()[2]->GetBoundsInScreen().CenterPoint());
  985. CompleteCycling(controller);
  986. EXPECT_TRUE(wm::IsActiveWindow(w4.get()));
  987. // Start cycle, cycle to the fifth item, mouse over seventh item, and click.
  988. // Starting order of windows in cycle list is [4,5,6,3,2,1,0].
  989. controller->StartCycling();
  990. for (int i = 0; i < 5; i++)
  991. controller->HandleCycleWindow(
  992. WindowCycleController::WindowCyclingDirection::kForward);
  993. target_item_center =
  994. GetWindowCycleItemViews()[6]->GetBoundsInScreen().CenterPoint();
  995. generator->MoveMouseTo(target_item_center);
  996. EXPECT_EQ(target_item_center,
  997. GetWindowCycleItemViews()[6]->GetBoundsInScreen().CenterPoint());
  998. generator->PressLeftButton();
  999. EXPECT_TRUE(wm::IsActiveWindow(w0.get()));
  1000. }
  1001. // Tests that the left and right keys cycle after the cycle list has been
  1002. // initialized.
  1003. TEST_F(WindowCycleControllerTest, LeftRightCycle) {
  1004. std::unique_ptr<Window> w0 = CreateTestWindow();
  1005. std::unique_ptr<Window> w1 = CreateTestWindow();
  1006. std::unique_ptr<Window> w2 = CreateTestWindow();
  1007. ui::test::EventGenerator* generator = GetEventGenerator();
  1008. WindowCycleController* controller = Shell::Get()->window_cycle_controller();
  1009. // Start cycle, simulating alt button being held down. Cycle right to the
  1010. // third item.
  1011. // Starting order of windows in cycle list is [2,1,0].
  1012. controller->StartCycling();
  1013. generator->PressKey(ui::VKEY_RIGHT, ui::EF_NONE);
  1014. generator->PressKey(ui::VKEY_RIGHT, ui::EF_NONE);
  1015. CompleteCycling(controller);
  1016. EXPECT_TRUE(wm::IsActiveWindow(w0.get()));
  1017. // Start cycle. Cycle right once, then left two times.
  1018. // Starting order of windows in cycle list is [0,2,1].
  1019. controller->StartCycling();
  1020. generator->PressKey(ui::VKEY_RIGHT, ui::EF_NONE);
  1021. generator->PressKey(ui::VKEY_LEFT, ui::EF_NONE);
  1022. generator->PressKey(ui::VKEY_LEFT, ui::EF_NONE);
  1023. CompleteCycling(controller);
  1024. EXPECT_TRUE(wm::IsActiveWindow(w1.get()));
  1025. // Start cycle. Cycle right once, then left once, then right once.
  1026. // Starting order of windows in cycle list is [0,2,1].
  1027. controller->StartCycling();
  1028. generator->PressKey(ui::VKEY_LEFT, ui::EF_ALT_DOWN);
  1029. generator->PressKey(ui::VKEY_RIGHT, ui::EF_ALT_DOWN);
  1030. generator->PressKey(ui::VKEY_LEFT, ui::EF_ALT_DOWN);
  1031. CompleteCycling(controller);
  1032. EXPECT_TRUE(wm::IsActiveWindow(w2.get()));
  1033. }
  1034. // Tests that pressing the space key, pressing the enter key, or releasing the
  1035. // alt key during window cycle confirms a selection.
  1036. TEST_F(WindowCycleControllerTest, KeysConfirmSelection) {
  1037. std::unique_ptr<Window> w0 = CreateTestWindow();
  1038. std::unique_ptr<Window> w1 = CreateTestWindow();
  1039. std::unique_ptr<Window> w2 = CreateTestWindow();
  1040. ui::test::EventGenerator* generator = GetEventGenerator();
  1041. WindowCycleController* controller = Shell::Get()->window_cycle_controller();
  1042. // Start cycle, simulating alt button being held down. Cycle right once and
  1043. // complete cycle using space.
  1044. // Starting order of windows in cycle list is [2,1,0].
  1045. controller->StartCycling();
  1046. controller->HandleCycleWindow(
  1047. WindowCycleController::WindowCyclingDirection::kForward);
  1048. generator->PressKey(ui::VKEY_SPACE, ui::EF_NONE);
  1049. EXPECT_TRUE(wm::IsActiveWindow(w1.get()));
  1050. // Start cycle, simulating alt button being held down. Cycle right once and
  1051. // complete cycle using enter.
  1052. // Starting order of windows in cycle list is [1,2,0].
  1053. controller->StartCycling();
  1054. controller->HandleCycleWindow(
  1055. WindowCycleController::WindowCyclingDirection::kForward);
  1056. generator->PressKey(ui::VKEY_RETURN, ui::EF_NONE);
  1057. EXPECT_TRUE(wm::IsActiveWindow(w2.get()));
  1058. // Start cycle, simulating alt button being held down. Cycle right once and
  1059. // complete cycle by releasing alt key (Views uses VKEY_MENU for both left and
  1060. // right alt keys).
  1061. // Starting order of windows in cycle list is [2,1,0].
  1062. controller->StartCycling();
  1063. controller->HandleCycleWindow(
  1064. WindowCycleController::WindowCyclingDirection::kForward);
  1065. generator->ReleaseKey(ui::VKEY_MENU, ui::EF_NONE);
  1066. EXPECT_TRUE(wm::IsActiveWindow(w1.get()));
  1067. }
  1068. // Tests that pressing the enter key or space key really quickly doesn't crash.
  1069. // See crbug.com/1187242.
  1070. TEST_F(WindowCycleControllerTest, RapidConfirmSelection) {
  1071. std::unique_ptr<Window> w0 = CreateTestWindow();
  1072. std::unique_ptr<Window> w1 = CreateTestWindow();
  1073. std::unique_ptr<Window> w2 = CreateTestWindow();
  1074. ui::test::EventGenerator* generator = GetEventGenerator();
  1075. WindowCycleController* controller = Shell::Get()->window_cycle_controller();
  1076. // Start cycling and press space twice. This should not crash.
  1077. controller->StartCycling();
  1078. controller->HandleCycleWindow(
  1079. WindowCycleController::WindowCyclingDirection::kForward);
  1080. generator->PressKey(ui::VKEY_SPACE, ui::EF_NONE);
  1081. generator->PressKey(ui::VKEY_SPACE, ui::EF_NONE);
  1082. EXPECT_TRUE(wm::IsActiveWindow(w1.get()));
  1083. // Start cycling and press enter twice. This should not crash.
  1084. controller->StartCycling();
  1085. controller->HandleCycleWindow(
  1086. WindowCycleController::WindowCyclingDirection::kForward);
  1087. generator->PressKey(ui::VKEY_RETURN, ui::EF_NONE);
  1088. generator->PressKey(ui::VKEY_RETURN, ui::EF_NONE);
  1089. EXPECT_TRUE(wm::IsActiveWindow(w2.get()));
  1090. // Press down alt and tab. Release alt key and press enter. This should not
  1091. // crash.
  1092. generator->PressKey(ui::VKEY_TAB, ui::EF_ALT_DOWN);
  1093. EXPECT_TRUE(controller->IsCycling());
  1094. generator->ReleaseKey(ui::VKEY_TAB, ui::EF_ALT_DOWN);
  1095. generator->PressKey(ui::VKEY_RETURN, ui::EF_NONE);
  1096. EXPECT_TRUE(wm::IsActiveWindow(w1.get()));
  1097. // Start cycling and press enter once and then right key. This should not
  1098. // crash and the right key should not affect the selection.
  1099. controller->StartCycling();
  1100. controller->HandleCycleWindow(
  1101. WindowCycleController::WindowCyclingDirection::kForward);
  1102. generator->PressKey(ui::VKEY_RETURN, ui::EF_NONE);
  1103. generator->PressKey(ui::VKEY_RIGHT, ui::EF_NONE);
  1104. EXPECT_TRUE(wm::IsActiveWindow(w2.get()));
  1105. }
  1106. // Tests that mouse events are filtered until the mouse is actually used,
  1107. // preventing the mouse from unexpectedly triggering events.
  1108. // See crbug.com/1143275.
  1109. TEST_F(WindowCycleControllerTest, FilterMouseEventsUntilUsed) {
  1110. std::unique_ptr<Window> w0 = CreateTestWindow();
  1111. std::unique_ptr<Window> w1 = CreateTestWindow();
  1112. std::unique_ptr<Window> w2 = CreateTestWindow();
  1113. EventCounter event_count;
  1114. ui::test::EventGenerator* generator = GetEventGenerator();
  1115. WindowCycleController* controller = Shell::Get()->window_cycle_controller();
  1116. // Start cycling.
  1117. // Current window order is [2,1,0].
  1118. controller->StartCycling();
  1119. auto item_views = GetWindowCycleItemViews();
  1120. item_views[2]->AddPreTargetHandler(&event_count);
  1121. // Move the mouse over to the third item and complete cycling. These mouse
  1122. // events shouldn't be filtered since the user has moved their mouse.
  1123. generator->MoveMouseTo(gfx::Point(0, 0));
  1124. const gfx::Point third_item_center =
  1125. GetWindowCycleItemViews()[2]->GetBoundsInScreen().CenterPoint();
  1126. generator->MoveMouseTo(third_item_center);
  1127. CompleteCycling(controller);
  1128. EXPECT_TRUE(wm::IsActiveWindow(w0.get()));
  1129. EXPECT_LT(0, event_count.GetMouseEventCountAndReset());
  1130. // Start cycling again while the mouse is over where the third item will be
  1131. // when cycling starts.
  1132. // Current window order is [0,2,1].
  1133. controller->StartCycling();
  1134. item_views = GetWindowCycleItemViews();
  1135. item_views[2]->AddPreTargetHandler(&event_count);
  1136. // Generate mouse events at the cursor's initial position. These mouse events
  1137. // should be filtered because the user hasn't moved their mouse yet.
  1138. generator->MoveMouseTo(third_item_center);
  1139. CompleteCycling(controller);
  1140. EXPECT_TRUE(wm::IsActiveWindow(w0.get()));
  1141. EXPECT_EQ(0, event_count.GetMouseEventCountAndReset());
  1142. // Start cycling again and click. This should not be filtered out.
  1143. // Current window order is [0,2,1].
  1144. controller->StartCycling();
  1145. generator->PressLeftButton();
  1146. EXPECT_FALSE(controller->IsCycling());
  1147. EXPECT_TRUE(wm::IsActiveWindow(w1.get()));
  1148. }
  1149. // When a user has the window cycle list open and clicks outside of it, it
  1150. // should cancel cycling.
  1151. TEST_F(WindowCycleControllerTest, MousePressOutsideOfListCancelsCycling) {
  1152. std::unique_ptr<Window> w0 = CreateTestWindow();
  1153. std::unique_ptr<Window> w1 = CreateTestWindow();
  1154. std::unique_ptr<Window> w2 = CreateTestWindow();
  1155. ui::test::EventGenerator* generator = GetEventGenerator();
  1156. WindowCycleController* controller = Shell::Get()->window_cycle_controller();
  1157. // Cycle to second item, move to above the window cycle list, and click.
  1158. controller->StartCycling();
  1159. controller->HandleCycleWindow(
  1160. WindowCycleController::WindowCyclingDirection::kForward);
  1161. gfx::Point above_window_cycle_list =
  1162. GetWindowCycleListWidget()->GetWindowBoundsInScreen().top_center();
  1163. above_window_cycle_list.Offset(0, 100);
  1164. generator->MoveMouseTo(above_window_cycle_list);
  1165. generator->ClickLeftButton();
  1166. EXPECT_FALSE(controller->IsCycling());
  1167. EXPECT_TRUE(wm::IsActiveWindow(w1.get()));
  1168. }
  1169. // When the user has one window open, the window cycle view isn't shown. In this
  1170. // case we should not eat mouse events.
  1171. TEST_F(WindowCycleControllerTest, MouseEventsNotEatenWhenCycleViewNotVisible) {
  1172. std::unique_ptr<Window> w0 = CreateTestWindow();
  1173. EventCounter event_count;
  1174. w0->AddPreTargetHandler(&event_count);
  1175. ui::test::EventGenerator* generator = GetEventGenerator();
  1176. // Start cycling. Since there's only one window the cycle view shouldn't be
  1177. // visible.
  1178. WindowCycleController* controller = Shell::Get()->window_cycle_controller();
  1179. controller->HandleCycleWindow(
  1180. WindowCycleController::WindowCyclingDirection::kForward);
  1181. ASSERT_TRUE(controller->IsCycling());
  1182. ASSERT_FALSE(controller->IsWindowListVisible());
  1183. generator->MoveMouseToCenterOf(w0.get());
  1184. generator->ClickLeftButton();
  1185. EXPECT_LT(0, event_count.GetMouseEventCountAndReset());
  1186. }
  1187. // Tests three finger horizontal scroll gesture to move selection left or right.
  1188. TEST_F(WindowCycleControllerTest,
  1189. ThreeFingerHorizontalScrollInWindowCycleList) {
  1190. const gfx::Rect bounds(0, 0, 400, 400);
  1191. std::unique_ptr<aura::Window> window1 = CreateTestWindow(bounds);
  1192. std::unique_ptr<aura::Window> window2 = CreateTestWindow(bounds);
  1193. std::unique_ptr<aura::Window> window3 = CreateTestWindow(bounds);
  1194. std::unique_ptr<aura::Window> window4 = CreateTestWindow(bounds);
  1195. std::unique_ptr<aura::Window> window5 = CreateTestWindow(bounds);
  1196. const float horizontal_scroll =
  1197. WindowCycleEventFilter::kHorizontalThresholdDp;
  1198. auto scroll_until_window_highlighted_and_confirm = [this](float x_offset,
  1199. float y_offset) {
  1200. WindowCycleController* controller = Shell::Get()->window_cycle_controller();
  1201. controller->StartCycling();
  1202. Scroll(GetOffsetX(x_offset), GetOffsetY(y_offset), kNumFingersForTrackpad);
  1203. CompleteCycling(controller);
  1204. };
  1205. // Start cycle, simulating alt key being held down. Scroll right to fourth
  1206. // item.
  1207. // Current order is [5,4,3,2,1].
  1208. scroll_until_window_highlighted_and_confirm(horizontal_scroll * 3, 0);
  1209. EXPECT_TRUE(wm::IsActiveWindow(window2.get()));
  1210. // Start cycle. Scroll left to third item.
  1211. // Current order is [2,5,4,3,1].
  1212. scroll_until_window_highlighted_and_confirm(-horizontal_scroll * 3, 0);
  1213. EXPECT_TRUE(wm::IsActiveWindow(window4.get()));
  1214. // Start cycle. Scroll right to second item.
  1215. // Current order is [4,2,5,3,1].
  1216. scroll_until_window_highlighted_and_confirm(horizontal_scroll, 0);
  1217. EXPECT_TRUE(wm::IsActiveWindow(window2.get()));
  1218. // Open an overview session.
  1219. EnterOverview();
  1220. EXPECT_TRUE(InOverviewSession());
  1221. // Open the window cycle list. Scroll right to second item. Overview mode
  1222. // should be dismissed at this point as they do the same thing by design.
  1223. // Current order is [2,4,5,3,1].
  1224. auto* cycle_controller = Shell::Get()->window_cycle_controller();
  1225. cycle_controller->StartCycling();
  1226. Scroll(GetOffsetX(horizontal_scroll), 0, kNumFingersForTrackpad);
  1227. EXPECT_FALSE(InOverviewSession());
  1228. CompleteCycling(cycle_controller);
  1229. EXPECT_FALSE(InOverviewSession());
  1230. EXPECT_TRUE(wm::IsActiveWindow(window4.get()));
  1231. }
  1232. // Tests two finger horizontal scroll gesture to move selection left or right.
  1233. TEST_F(WindowCycleControllerTest, TwoFingerHorizontalScrollInWindowCycleList) {
  1234. const gfx::Rect bounds(0, 0, 400, 400);
  1235. std::unique_ptr<aura::Window> window1 = CreateTestWindow(bounds);
  1236. std::unique_ptr<aura::Window> window2 = CreateTestWindow(bounds);
  1237. std::unique_ptr<aura::Window> window3 = CreateTestWindow(bounds);
  1238. std::unique_ptr<aura::Window> window4 = CreateTestWindow(bounds);
  1239. std::unique_ptr<aura::Window> window5 = CreateTestWindow(bounds);
  1240. const float horizontal_scroll =
  1241. WindowCycleEventFilter::kHorizontalThresholdDp;
  1242. auto scroll_until_window_highlighted_and_confirm = [this](float x_offset,
  1243. float y_offset) {
  1244. WindowCycleController* controller = Shell::Get()->window_cycle_controller();
  1245. controller->StartCycling();
  1246. // Since two finger swipes are negated, negate in tests to mimic how this
  1247. // actually behaves on devices.
  1248. Scroll(GetOffsetX(-x_offset), GetOffsetY(y_offset),
  1249. kNumFingersForMouseWheel);
  1250. CompleteCycling(controller);
  1251. };
  1252. // Start cycle, simulating alt key being held down. Scroll right to fourth
  1253. // item.
  1254. // Current order is [5,4,3,2,1].
  1255. scroll_until_window_highlighted_and_confirm(horizontal_scroll * 3, 0);
  1256. EXPECT_TRUE(wm::IsActiveWindow(window2.get()));
  1257. // Start cycle. Scroll left to third item.
  1258. // Current order is [2,5,4,3,1].
  1259. scroll_until_window_highlighted_and_confirm(-horizontal_scroll * 3, 0);
  1260. EXPECT_TRUE(wm::IsActiveWindow(window4.get()));
  1261. // Start cycle. Scroll right to second item.
  1262. // Current order is [4,2,5,3,1].
  1263. scroll_until_window_highlighted_and_confirm(horizontal_scroll, 0);
  1264. EXPECT_TRUE(wm::IsActiveWindow(window2.get()));
  1265. }
  1266. // Tests mouse wheel scroll gesture to move selection left or right.
  1267. TEST_F(WindowCycleControllerTest, MouseWheelScrollInWindowCycleList) {
  1268. const gfx::Rect bounds(0, 0, 400, 400);
  1269. std::unique_ptr<aura::Window> window1 = CreateTestWindow(bounds);
  1270. std::unique_ptr<aura::Window> window2 = CreateTestWindow(bounds);
  1271. std::unique_ptr<aura::Window> window3 = CreateTestWindow(bounds);
  1272. std::unique_ptr<aura::Window> window4 = CreateTestWindow(bounds);
  1273. std::unique_ptr<aura::Window> window5 = CreateTestWindow(bounds);
  1274. const float horizontal_scroll =
  1275. WindowCycleEventFilter::kHorizontalThresholdDp;
  1276. auto scroll_until_window_highlighted_and_confirm = [this](float x_offset,
  1277. float y_offset,
  1278. int num_of_times) {
  1279. WindowCycleController* controller = Shell::Get()->window_cycle_controller();
  1280. controller->StartCycling();
  1281. MouseWheelScroll(x_offset, y_offset, num_of_times);
  1282. CompleteCycling(controller);
  1283. };
  1284. // Start cycle, simulating alt key being held down. Scroll right to fourth
  1285. // item.
  1286. // Current order is [5,4,3,2,1].
  1287. scroll_until_window_highlighted_and_confirm(0, -horizontal_scroll, 3);
  1288. EXPECT_TRUE(wm::IsActiveWindow(window2.get()));
  1289. // Start cycle. Scroll left to third item.
  1290. // Current order is [2,5,4,3,1].
  1291. scroll_until_window_highlighted_and_confirm(0, horizontal_scroll, 3);
  1292. EXPECT_TRUE(wm::IsActiveWindow(window4.get()));
  1293. // Start cycle. Scroll right to second item.
  1294. // Current order is [4,2,5,3,1].
  1295. scroll_until_window_highlighted_and_confirm(0, -horizontal_scroll, 1);
  1296. EXPECT_TRUE(wm::IsActiveWindow(window2.get()));
  1297. }
  1298. // Tests that swiping up closes window cycle if it's open and starts overview
  1299. // mode.
  1300. TEST_F(WindowCycleControllerTest, VerticalScroll) {
  1301. std::unique_ptr<aura::Window> window1 = CreateTestWindow();
  1302. std::unique_ptr<aura::Window> window2 = CreateTestWindow();
  1303. const float vertical_scroll = 2 * WmGestureHandler::kVerticalThresholdDp;
  1304. const float horizontal_scroll =
  1305. WindowCycleEventFilter::kHorizontalThresholdDp;
  1306. auto* window_cycle_controller = Shell::Get()->window_cycle_controller();
  1307. // Start cycling and then swipe up to open up overview.
  1308. window_cycle_controller->HandleCycleWindow(
  1309. WindowCycleController::WindowCyclingDirection::kForward);
  1310. EXPECT_TRUE(window_cycle_controller->IsCycling());
  1311. Scroll(0, vertical_scroll, 3);
  1312. EXPECT_TRUE(InOverviewSession());
  1313. EXPECT_FALSE(window_cycle_controller->IsCycling());
  1314. // Start cycling and then swipe down.
  1315. window_cycle_controller->HandleCycleWindow(
  1316. WindowCycleController::WindowCyclingDirection::kForward);
  1317. EXPECT_TRUE(window_cycle_controller->IsCycling());
  1318. Scroll(0, -vertical_scroll, 3);
  1319. EXPECT_TRUE(window_cycle_controller->IsCycling());
  1320. // Swipe diagonally with horizontal bias.
  1321. Scroll(horizontal_scroll * 3, vertical_scroll, 3);
  1322. EXPECT_TRUE(window_cycle_controller->IsCycling());
  1323. EXPECT_FALSE(InOverviewSession());
  1324. // Swipe diagonally with vertical bias.
  1325. Scroll(horizontal_scroll, vertical_scroll, 3);
  1326. EXPECT_FALSE(window_cycle_controller->IsCycling());
  1327. EXPECT_TRUE(InOverviewSession());
  1328. }
  1329. // Tests that touch continuous scrolls for the window cycle list.
  1330. TEST_F(WindowCycleControllerTest, TouchScroll) {
  1331. const gfx::Rect bounds(0, 0, 200, 200);
  1332. std::unique_ptr<aura::Window> window5 = CreateTestWindow(bounds);
  1333. std::unique_ptr<aura::Window> window4 = CreateTestWindow(bounds);
  1334. std::unique_ptr<aura::Window> window3 = CreateTestWindow(bounds);
  1335. std::unique_ptr<aura::Window> window2 = CreateTestWindow(bounds);
  1336. std::unique_ptr<aura::Window> window1 = CreateTestWindow(bounds);
  1337. auto* cycle_controller = Shell::Get()->window_cycle_controller();
  1338. auto* event_generator = GetEventGenerator();
  1339. // Start cycling.
  1340. cycle_controller->StartCycling();
  1341. cycle_controller->HandleCycleWindow(
  1342. WindowCycleController::WindowCyclingDirection::kForward);
  1343. ASSERT_TRUE(cycle_controller->IsCycling());
  1344. ASSERT_EQ(window2.get(), GetTargetWindow());
  1345. // There should be five preview items and the first three should be contained
  1346. // by the screen. The fourth should be in the screen, but not contained. The
  1347. // last one should not be in the screen at all.
  1348. auto preview_items = GetWindowCycleItemViews();
  1349. ASSERT_EQ(5u, preview_items.size());
  1350. auto cycle_view_bounds =
  1351. GetWindowCycleListWidget()->GetWindowBoundsInScreen();
  1352. ASSERT_TRUE(cycle_view_bounds.x() <
  1353. preview_items[0]->GetBoundsInScreen().x());
  1354. ASSERT_TRUE(preview_items[2]->GetBoundsInScreen().x() <
  1355. cycle_view_bounds.right());
  1356. ASSERT_TRUE(cycle_view_bounds.right() <
  1357. preview_items[3]->GetBoundsInScreen().right());
  1358. ASSERT_TRUE(preview_items[3]->GetBoundsInScreen().x() <
  1359. cycle_view_bounds.right());
  1360. ASSERT_TRUE(cycle_view_bounds.right() <
  1361. preview_items[4]->GetBoundsInScreen().x());
  1362. // Drag from the middle of the first item to the right. The preview items
  1363. // should not move since we're at the beginning of the cycle list. Also the
  1364. // focus ring should not move.
  1365. auto drag_origin = preview_items[0]->GetBoundsInScreen().CenterPoint();
  1366. auto drag_dest = preview_items[1]->GetBoundsInScreen().CenterPoint();
  1367. event_generator->GestureScrollSequence(drag_origin, drag_dest,
  1368. base::Seconds(1), 10);
  1369. EXPECT_EQ(drag_origin, preview_items[0]->GetBoundsInScreen().CenterPoint());
  1370. EXPECT_EQ(window2.get(), GetTargetWindow());
  1371. // Drag from the middle of the second item to the left. The item should follow
  1372. // the cursor and the focus ring should not move.
  1373. drag_origin = preview_items[1]->GetBoundsInScreen().CenterPoint();
  1374. drag_dest = preview_items[0]->GetBoundsInScreen().CenterPoint();
  1375. event_generator->GestureScrollSequence(drag_origin, drag_dest,
  1376. base::Seconds(1), 10);
  1377. EXPECT_TRUE(base::IsApproximatelyEqual(
  1378. drag_dest.x(), preview_items[1]->GetBoundsInScreen().CenterPoint().x(),
  1379. 10));
  1380. EXPECT_TRUE(preview_items[0]->GetBoundsInScreen().CenterPoint().x() <
  1381. cycle_view_bounds.x());
  1382. EXPECT_EQ(window2.get(), GetTargetWindow());
  1383. // The last preview item should now be visible, but it shouldn't be contained.
  1384. EXPECT_TRUE(preview_items[4]->GetBoundsInScreen().x() <
  1385. cycle_view_bounds.right());
  1386. EXPECT_TRUE(cycle_view_bounds.right() <
  1387. preview_items[4]->GetBoundsInScreen().right());
  1388. // Drag from the middle of the fourth item to the left one preview item's
  1389. // width. Since the last item is already visible, the mirror container should
  1390. // not be dragged the full amount and the last item's right edge should be at
  1391. // the end of the cycle view.
  1392. drag_origin = preview_items[3]->GetBoundsInScreen().CenterPoint();
  1393. drag_dest = preview_items[1]->GetBoundsInScreen().CenterPoint();
  1394. event_generator->GestureScrollSequence(drag_origin, drag_dest,
  1395. base::Seconds(1), 10);
  1396. EXPECT_EQ(cycle_view_bounds.right(),
  1397. preview_items[4]->GetBoundsInScreen().right() +
  1398. WindowCycleView::kInsideBorderHorizontalPaddingDp);
  1399. EXPECT_EQ(window2.get(), GetTargetWindow());
  1400. // Diagonally drag from the middle of the fourth item to the right, ending up
  1401. // outside of the cycle view. This should still drag the full distance.
  1402. drag_origin = preview_items[3]->GetBoundsInScreen().CenterPoint();
  1403. drag_dest = preview_items[4]->GetBoundsInScreen().CenterPoint();
  1404. drag_dest.set_y(cycle_view_bounds.bottom() + 100);
  1405. event_generator->GestureScrollSequence(drag_origin, drag_dest,
  1406. base::Seconds(1), 10);
  1407. EXPECT_TRUE(base::IsApproximatelyEqual(
  1408. drag_dest.x(), preview_items[3]->GetBoundsInScreen().CenterPoint().x(),
  1409. 10));
  1410. }
  1411. // Tests that a vertical touch scroll doesn't crash. See crbug.com/1224969.
  1412. TEST_F(WindowCycleControllerTest, VerticalTouchScroll) {
  1413. const gfx::Rect bounds(0, 0, 200, 200);
  1414. std::unique_ptr<aura::Window> window4 = CreateTestWindow(bounds);
  1415. std::unique_ptr<aura::Window> window3 = CreateTestWindow(bounds);
  1416. std::unique_ptr<aura::Window> window2 = CreateTestWindow(bounds);
  1417. std::unique_ptr<aura::Window> window1 = CreateTestWindow(bounds);
  1418. auto* cycle_controller = Shell::Get()->window_cycle_controller();
  1419. auto* event_generator = GetEventGenerator();
  1420. // Start cycling.
  1421. cycle_controller->StartCycling();
  1422. cycle_controller->HandleCycleWindow(
  1423. WindowCycleController::WindowCyclingDirection::kForward);
  1424. ASSERT_TRUE(cycle_controller->IsCycling());
  1425. ASSERT_EQ(window2.get(), GetTargetWindow());
  1426. // Vertical touch scroll from the second item. This will cause a
  1427. // ui::ET_SCROLL_FLING_START event to be generated. This should not crash and
  1428. // do nothing to the window cycle list.
  1429. auto preview_items = GetWindowCycleItemViews();
  1430. auto drag_origin = preview_items[0]->GetBoundsInScreen().CenterPoint();
  1431. auto drag_dest = drag_origin + gfx::Vector2d(0, 200);
  1432. event_generator->GestureScrollSequence(drag_origin, drag_dest,
  1433. base::Milliseconds(10), 10);
  1434. EXPECT_EQ(drag_origin, preview_items[0]->GetBoundsInScreen().CenterPoint());
  1435. EXPECT_EQ(window2.get(), GetTargetWindow());
  1436. }
  1437. // When a user taps on an item, it should set the focus ring to that item. After
  1438. // they release their finger it should confirm the selection.
  1439. TEST_F(WindowCycleControllerTest, TapSelect) {
  1440. std::unique_ptr<aura::Window> w0 = CreateTestWindow();
  1441. std::unique_ptr<aura::Window> w1 = CreateTestWindow();
  1442. std::unique_ptr<aura::Window> w2 = CreateTestWindow();
  1443. ui::test::EventGenerator* generator = GetEventGenerator();
  1444. WindowCycleController* controller = Shell::Get()->window_cycle_controller();
  1445. auto generate_gesture_event = [](ui::test::EventGenerator* generator,
  1446. const gfx::Point& location,
  1447. ui::EventType type) {
  1448. ui::GestureEvent event(location.x(), location.y(),
  1449. /*flags=*/0, base::TimeTicks::Now(),
  1450. ui::GestureEventDetails{type});
  1451. generator->Dispatch(&event);
  1452. };
  1453. auto tap_without_release = [generate_gesture_event](
  1454. ui::test::EventGenerator* generator,
  1455. const gfx::Point& location) {
  1456. // Generates the following events at |location| in the given order:
  1457. // ET_GESTURE_BEGIN, ET_GESTURE_TAP_DOWN, ET_GESTURE_SHOW_PRESS
  1458. generate_gesture_event(generator, location, ui::ET_GESTURE_BEGIN);
  1459. generate_gesture_event(generator, location, ui::ET_GESTURE_TAP_DOWN);
  1460. generate_gesture_event(generator, location, ui::ET_GESTURE_SHOW_PRESS);
  1461. };
  1462. // Start cycle and tap third item without releasing finger. On tap down, the
  1463. // focus ring should be set to the third item. Selection should not be
  1464. // confirmed since finger was not released. Starting order of windows in cycle
  1465. // list is [2,1,0].
  1466. controller->StartCycling();
  1467. gfx::Point center_point =
  1468. GetWindowCycleItemViews()[2]->GetBoundsInScreen().CenterPoint();
  1469. tap_without_release(generator, center_point);
  1470. EXPECT_TRUE(controller->IsCycling());
  1471. EXPECT_EQ(GetTargetWindow(), w0.get());
  1472. // Complete cycling and confirm window 0 is active.
  1473. CompleteCycling(controller);
  1474. EXPECT_FALSE(controller->IsCycling());
  1475. EXPECT_TRUE(wm::IsActiveWindow(w0.get()));
  1476. // Start cycle and tap second item without releasing finger. On tap down, the
  1477. // focus ring should be set to the second item. Selection should not be
  1478. // confirmed since finger was not released. Starting order of windows in cycle
  1479. // list is [0,2,1].
  1480. controller->StartCycling();
  1481. center_point =
  1482. GetWindowCycleItemViews()[1]->GetBoundsInScreen().CenterPoint();
  1483. tap_without_release(generator, center_point);
  1484. EXPECT_TRUE(controller->IsCycling());
  1485. EXPECT_EQ(GetTargetWindow(), w2.get());
  1486. // Complete cycling and confirm window 2 is active.
  1487. CompleteCycling(controller);
  1488. EXPECT_FALSE(controller->IsCycling());
  1489. EXPECT_TRUE(wm::IsActiveWindow(w2.get()));
  1490. // Start cycling again and tap and release. This should confirm the
  1491. // selection. Starting order of windows in cycle list is [2,0,1].
  1492. controller->StartCycling();
  1493. center_point =
  1494. GetWindowCycleItemViews()[1]->GetBoundsInScreen().CenterPoint();
  1495. generator->GestureTapDownAndUp(center_point);
  1496. EXPECT_FALSE(controller->IsCycling());
  1497. EXPECT_TRUE(wm::IsActiveWindow(w0.get()));
  1498. }
  1499. // Tests that releasing alt key while continuing tapping on the window cycle
  1500. // list doesn't lead to a crash. Regression test for https://crbug.com/1228381.
  1501. TEST_F(WindowCycleControllerTest, AltReleaseWithoutReleasingTap) {
  1502. std::unique_ptr<Window> w0(CreateTestWindowInShellWithId(0));
  1503. std::unique_ptr<Window> w1(CreateTestWindowInShellWithId(1));
  1504. WindowCycleController* controller = Shell::Get()->window_cycle_controller();
  1505. // Start window cycling by press Alt + Tab key.
  1506. ui::test::EventGenerator* generator = GetEventGenerator();
  1507. WindowState::Get(w0.get())->Activate();
  1508. generator->PressKey(ui::VKEY_MENU, ui::EF_NONE);
  1509. generator->PressKey(ui::VKEY_TAB, ui::EF_ALT_DOWN);
  1510. EXPECT_TRUE(controller->IsCycling());
  1511. generator->ReleaseKey(ui::VKEY_TAB, ui::EF_ALT_DOWN);
  1512. EXPECT_TRUE(controller->IsCycling());
  1513. // Tapping on the window cycle list without releasing the tap.
  1514. gfx::Point center_point =
  1515. GetWindowCycleItemViews()[1]->GetBoundsInScreen().CenterPoint();
  1516. generator->PressTouch(center_point);
  1517. // Release the alt key. Make sure no crash happens.
  1518. generator->ReleaseKey(ui::VKEY_MENU, ui::EF_NONE);
  1519. EXPECT_FALSE(controller->IsCycling());
  1520. }
  1521. // Tests that pressing arrow key before cycle view UI is ready doesn't lead to a
  1522. // crash. Regression test for https://crbug.com/1246251.
  1523. TEST_F(WindowCycleControllerTest, ArrowKeyBeforeCycleViewUI) {
  1524. auto* desks_controller = DesksController::Get();
  1525. desks_controller->NewDesk(DesksCreationRemovalSource::kButton);
  1526. std::unique_ptr<Window> w0(CreateTestWindowInShellWithId(0));
  1527. std::unique_ptr<Window> w1(CreateTestWindowInShellWithId(1));
  1528. WindowCycleController* controller = Shell::Get()->window_cycle_controller();
  1529. // Enable initial delay for testing so that once it starts cycling, the cycle
  1530. // view UI will not be shown right away.
  1531. WindowCycleList::SetDisableInitialDelayForTesting(false);
  1532. controller->StartCycling();
  1533. EXPECT_TRUE(controller->IsCycling());
  1534. EXPECT_FALSE(CycleViewExists());
  1535. controller->HandleKeyboardNavigation(
  1536. WindowCycleController::KeyboardNavDirection::kUp);
  1537. controller->HandleKeyboardNavigation(
  1538. WindowCycleController::KeyboardNavDirection::kDown);
  1539. controller->HandleKeyboardNavigation(
  1540. WindowCycleController::KeyboardNavDirection::kLeft);
  1541. controller->HandleKeyboardNavigation(
  1542. WindowCycleController::KeyboardNavDirection::kRight);
  1543. CompleteCycling(controller);
  1544. }
  1545. class ReverseGestureWindowCycleControllerTest
  1546. : public WindowCycleControllerTest {
  1547. public:
  1548. ReverseGestureWindowCycleControllerTest() = default;
  1549. ReverseGestureWindowCycleControllerTest(
  1550. const ReverseGestureWindowCycleControllerTest&) = delete;
  1551. ReverseGestureWindowCycleControllerTest& operator=(
  1552. const ReverseGestureWindowCycleControllerTest&) = delete;
  1553. ~ReverseGestureWindowCycleControllerTest() override = default;
  1554. // AshTestBase:
  1555. void SetUp() override {
  1556. scoped_feature_list_.InitAndEnableFeature(features::kReverseScrollGestures);
  1557. AshTestBase::SetUp();
  1558. // Set natural scroll on.
  1559. PrefService* pref =
  1560. Shell::Get()->session_controller()->GetActivePrefService();
  1561. pref->SetBoolean(prefs::kTouchpadEnabled, true);
  1562. pref->SetBoolean(prefs::kNaturalScroll, true);
  1563. pref->SetBoolean(prefs::kMouseReverseScroll, true);
  1564. }
  1565. private:
  1566. base::test::ScopedFeatureList scoped_feature_list_;
  1567. };
  1568. // Tests mouse wheel scroll gesture to move selection left or right. Mouse
  1569. // reverse scroll should reverse its direction.
  1570. TEST_F(ReverseGestureWindowCycleControllerTest,
  1571. MouseWheelScrollInWindowCycleList) {
  1572. const gfx::Rect bounds(0, 0, 400, 400);
  1573. std::unique_ptr<aura::Window> window1 = CreateTestWindow(bounds);
  1574. std::unique_ptr<aura::Window> window2 = CreateTestWindow(bounds);
  1575. std::unique_ptr<aura::Window> window3 = CreateTestWindow(bounds);
  1576. std::unique_ptr<aura::Window> window4 = CreateTestWindow(bounds);
  1577. std::unique_ptr<aura::Window> window5 = CreateTestWindow(bounds);
  1578. const float horizontal_scroll =
  1579. WindowCycleEventFilter::kHorizontalThresholdDp;
  1580. auto scroll_until_window_highlighted_and_confirm = [this](float x_offset,
  1581. float y_offset,
  1582. int num_of_times) {
  1583. WindowCycleController* controller = Shell::Get()->window_cycle_controller();
  1584. controller->StartCycling();
  1585. MouseWheelScroll(x_offset, y_offset, num_of_times);
  1586. CompleteCycling(controller);
  1587. };
  1588. // Start cycle, simulating alt key being held down. Scroll right to fourth
  1589. // item.
  1590. // Current order is [5,4,3,2,1].
  1591. scroll_until_window_highlighted_and_confirm(0, horizontal_scroll, 3);
  1592. EXPECT_TRUE(wm::IsActiveWindow(window2.get()));
  1593. // Start cycle. Scroll left to third item.
  1594. // Current order is [2,5,4,3,1].
  1595. scroll_until_window_highlighted_and_confirm(0, -horizontal_scroll, 3);
  1596. EXPECT_TRUE(wm::IsActiveWindow(window4.get()));
  1597. // Start cycle. Scroll right to second item.
  1598. // Current order is [4,2,5,3,1].
  1599. scroll_until_window_highlighted_and_confirm(0, horizontal_scroll, 1);
  1600. EXPECT_TRUE(wm::IsActiveWindow(window2.get()));
  1601. // Turn mouse reverse scroll off.
  1602. PrefService* pref =
  1603. Shell::Get()->session_controller()->GetActivePrefService();
  1604. pref->SetBoolean(prefs::kMouseReverseScroll, false);
  1605. // Start cycle. Scroll left once.
  1606. // Current order is [2,4,5,3,1].
  1607. scroll_until_window_highlighted_and_confirm(0, horizontal_scroll, 1);
  1608. EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
  1609. // Start cycle. Scroll right once.
  1610. // Current order is [1,2,4,5,3].
  1611. scroll_until_window_highlighted_and_confirm(0, -horizontal_scroll, 1);
  1612. EXPECT_TRUE(wm::IsActiveWindow(window2.get()));
  1613. }
  1614. // Tests that natural scroll doesn't affect two and three finger horizontal
  1615. // scroll gestures for cycling window cycle list.
  1616. TEST_F(ReverseGestureWindowCycleControllerTest,
  1617. WindowCycleListTrackpadGestures) {
  1618. const gfx::Rect bounds(0, 0, 400, 400);
  1619. std::unique_ptr<aura::Window> window1 = CreateTestWindow(bounds);
  1620. std::unique_ptr<aura::Window> window2 = CreateTestWindow(bounds);
  1621. std::unique_ptr<aura::Window> window3 = CreateTestWindow(bounds);
  1622. std::unique_ptr<aura::Window> window4 = CreateTestWindow(bounds);
  1623. std::unique_ptr<aura::Window> window5 = CreateTestWindow(bounds);
  1624. const float horizontal_scroll =
  1625. WindowCycleEventFilter::kHorizontalThresholdDp;
  1626. auto scroll_until_window_highlighted_and_confirm = [this](float x_offset,
  1627. float y_offset,
  1628. int num_fingers) {
  1629. WindowCycleController* controller = Shell::Get()->window_cycle_controller();
  1630. controller->StartCycling();
  1631. Scroll(x_offset, y_offset, num_fingers);
  1632. CompleteCycling(controller);
  1633. };
  1634. // Start cycle, scroll right with two finger gesture.
  1635. // Current order is [5,4,3,2,1].
  1636. scroll_until_window_highlighted_and_confirm(horizontal_scroll, 0,
  1637. kNumFingersForMouseWheel);
  1638. EXPECT_TRUE(wm::IsActiveWindow(window4.get()));
  1639. // Start cycle, scroll right with three finger gesture.
  1640. // Current order is [4,5,3,2,1].
  1641. scroll_until_window_highlighted_and_confirm(horizontal_scroll, 0,
  1642. kNumFingersForTrackpad);
  1643. EXPECT_TRUE(wm::IsActiveWindow(window5.get()));
  1644. // Turn natural scroll off.
  1645. PrefService* pref =
  1646. Shell::Get()->session_controller()->GetActivePrefService();
  1647. pref->SetBoolean(prefs::kNaturalScroll, false);
  1648. // Start cycle, scroll right with two finger gesture. Note: two figner swipes
  1649. // are negated, so negate in tests to mimic how this actually behaves on
  1650. // devices.
  1651. // Current order is [5,4,3,2,1].
  1652. scroll_until_window_highlighted_and_confirm(-horizontal_scroll, 0,
  1653. kNumFingersForMouseWheel);
  1654. EXPECT_TRUE(wm::IsActiveWindow(window4.get()));
  1655. // Start cycle, scroll right with three finger gesture.
  1656. // Current order is [4,5,3,2,1].
  1657. scroll_until_window_highlighted_and_confirm(horizontal_scroll, 0,
  1658. kNumFingersForTrackpad);
  1659. EXPECT_TRUE(wm::IsActiveWindow(window5.get()));
  1660. }
  1661. class ModeSelectionWindowCycleControllerTest
  1662. : public WindowCycleControllerTest {
  1663. public:
  1664. ModeSelectionWindowCycleControllerTest() = default;
  1665. ModeSelectionWindowCycleControllerTest(
  1666. const ModeSelectionWindowCycleControllerTest&) = delete;
  1667. ModeSelectionWindowCycleControllerTest& operator=(
  1668. const ModeSelectionWindowCycleControllerTest&) = delete;
  1669. ~ModeSelectionWindowCycleControllerTest() override = default;
  1670. // WindowCycleControllerTest:
  1671. void SetUp() override {
  1672. WindowCycleControllerTest::SetUp();
  1673. generator_ = GetEventGenerator();
  1674. }
  1675. void SwitchPerDeskAltTabMode(bool per_desk_mode,
  1676. bool use_slow_duration = false) {
  1677. ui::ScopedAnimationDurationScaleMode animation_scale(
  1678. use_slow_duration
  1679. ? ui::ScopedAnimationDurationScaleMode::SLOW_DURATION
  1680. : ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
  1681. gfx::Point button_center =
  1682. GetWindowCycleTabSliderButtons()[per_desk_mode ? 1 : 0]
  1683. ->GetBoundsInScreen()
  1684. .CenterPoint();
  1685. generator_->MoveMouseTo(button_center);
  1686. generator_->ClickLeftButton();
  1687. EXPECT_EQ(per_desk_mode,
  1688. Shell::Get()->window_cycle_controller()->IsAltTabPerActiveDesk());
  1689. }
  1690. bool IsAnimatingModeSwitch() const {
  1691. return WindowCycleListTestApi(GetCycleList()).IsCycleViewAnimating();
  1692. }
  1693. private:
  1694. ui::test::EventGenerator* generator_;
  1695. };
  1696. // Tests that when user taps tab slider buttons, the active mode should
  1697. // correspondingly change.
  1698. TEST_F(ModeSelectionWindowCycleControllerTest, ModeChangesOnTap) {
  1699. WindowCycleController* cycle_controller =
  1700. Shell::Get()->window_cycle_controller();
  1701. ui::test::EventGenerator* generator = GetEventGenerator();
  1702. // Create one window for desk1 and two windows for desk2.
  1703. auto win0 = CreateAppWindow(gfx::Rect(0, 0, 250, 100));
  1704. auto* desks_controller = DesksController::Get();
  1705. desks_controller->NewDesk(DesksCreationRemovalSource::kButton);
  1706. ASSERT_EQ(2u, desks_controller->desks().size());
  1707. const Desk* desk_2 = desks_controller->desks()[1].get();
  1708. ActivateDesk(desk_2);
  1709. EXPECT_EQ(desk_2, desks_controller->active_desk());
  1710. auto win1 = CreateAppWindow(gfx::Rect(0, 0, 300, 200));
  1711. auto win2 = CreateAppWindow(gfx::Rect(10, 30, 400, 200));
  1712. auto generate_gesture_event = [](ui::test::EventGenerator* generator,
  1713. const gfx::Point& location,
  1714. ui::EventType type) {
  1715. ui::GestureEvent event(location.x(), location.y(),
  1716. /*flags=*/0, base::TimeTicks::Now(),
  1717. ui::GestureEventDetails{type});
  1718. generator->Dispatch(&event);
  1719. };
  1720. auto tap = [generate_gesture_event](ui::test::EventGenerator* generator,
  1721. const gfx::Point& location) {
  1722. // Generates the following events at |location| in the given order:
  1723. // ET_GESTURE_BEGIN, ET_GESTURE_TAP_DOWN, ui::ET_GESTURE_SHOW_PRESS,
  1724. // ET_GESTURE_END
  1725. generate_gesture_event(generator, location, ui::ET_GESTURE_BEGIN);
  1726. generate_gesture_event(generator, location, ui::ET_GESTURE_TAP_DOWN);
  1727. generate_gesture_event(generator, location, ui::ET_GESTURE_SHOW_PRESS);
  1728. generate_gesture_event(generator, location, ui::ET_GESTURE_TAP);
  1729. generate_gesture_event(generator, location, ui::ET_GESTURE_END);
  1730. };
  1731. // Start cycle. Alt-tab should contain windows from all desks with tab slider.
  1732. cycle_controller->StartCycling();
  1733. auto cycle_windows = GetWindows(cycle_controller);
  1734. EXPECT_FALSE(cycle_controller->IsAltTabPerActiveDesk());
  1735. EXPECT_EQ(3u, cycle_windows.size());
  1736. EXPECT_EQ(cycle_windows.size(), GetWindowCycleItemViews().size());
  1737. auto tab_slider_buttons = GetWindowCycleTabSliderButtons();
  1738. EXPECT_EQ(2u, tab_slider_buttons.size());
  1739. // Tap current desk tab slider button. Switch to current desk mode.
  1740. gfx::Point current_desk_button_center_point =
  1741. tab_slider_buttons[1]->GetBoundsInScreen().CenterPoint();
  1742. tap(generator, current_desk_button_center_point);
  1743. EXPECT_TRUE(cycle_controller->IsAltTabPerActiveDesk());
  1744. EXPECT_EQ(2u, GetWindowCycleItemViews().size());
  1745. CompleteCycling(cycle_controller);
  1746. // Tap all desks tab slider button. Switch back to all desks mode.
  1747. cycle_controller->StartCycling();
  1748. EXPECT_TRUE(cycle_controller->IsAltTabPerActiveDesk());
  1749. tab_slider_buttons = GetWindowCycleTabSliderButtons();
  1750. gfx::Point all_desks_button_center_point =
  1751. tab_slider_buttons[0]->GetBoundsInScreen().CenterPoint();
  1752. tap(generator, all_desks_button_center_point);
  1753. cycle_windows = GetWindows(cycle_controller);
  1754. EXPECT_FALSE(cycle_controller->IsAltTabPerActiveDesk());
  1755. EXPECT_EQ(3u, GetWindowCycleItemViews().size());
  1756. EXPECT_EQ(cycle_windows.size(), GetWindowCycleItemViews().size());
  1757. CompleteCycling(cycle_controller);
  1758. }
  1759. // Tests that when user taps tab slider buttons, but then scrolles and releases
  1760. // finger on a window. Mode change should not happen in this use case.
  1761. TEST_F(ModeSelectionWindowCycleControllerTest,
  1762. TapTabSliderButtonButReleaseOnWindow) {
  1763. WindowCycleController* cycle_controller =
  1764. Shell::Get()->window_cycle_controller();
  1765. ui::test::EventGenerator* generator = GetEventGenerator();
  1766. // Create one window for desk1 and two windows for desk2.
  1767. auto win0 = CreateAppWindow(gfx::Rect(0, 0, 250, 100));
  1768. auto* desks_controller = DesksController::Get();
  1769. desks_controller->NewDesk(DesksCreationRemovalSource::kButton);
  1770. ASSERT_EQ(2u, desks_controller->desks().size());
  1771. const Desk* desk_2 = desks_controller->desks()[1].get();
  1772. ActivateDesk(desk_2);
  1773. EXPECT_EQ(desk_2, desks_controller->active_desk());
  1774. auto win1 = CreateAppWindow(gfx::Rect(0, 0, 300, 200));
  1775. auto win2 = CreateAppWindow(gfx::Rect(10, 30, 400, 200));
  1776. auto generate_gesture_event = [](ui::test::EventGenerator* generator,
  1777. const gfx::Point& location,
  1778. ui::EventType type) {
  1779. ui::GestureEvent event(location.x(), location.y(),
  1780. /*flags=*/0, base::TimeTicks::Now(),
  1781. ui::GestureEventDetails{type});
  1782. generator->Dispatch(&event);
  1783. };
  1784. auto tap_then_scroll = [generate_gesture_event](
  1785. ui::test::EventGenerator* generator,
  1786. const gfx::Point& location) {
  1787. // Generates the following events at |location| in the given order:
  1788. // ET_GESTURE_BEGIN, ET_GESTURE_TAP_DOWN, T_GESTURE_SCROLL_BEGIN,
  1789. // ui::ET_GESTURE_SCROLL_UPDATE
  1790. generate_gesture_event(generator, location, ui::ET_GESTURE_BEGIN);
  1791. generate_gesture_event(generator, location, ui::ET_GESTURE_TAP_DOWN);
  1792. generate_gesture_event(generator, location, ui::ET_GESTURE_SCROLL_BEGIN);
  1793. generate_gesture_event(generator, location, ui::ET_GESTURE_SCROLL_UPDATE);
  1794. };
  1795. auto scroll_update = [generate_gesture_event](
  1796. ui::test::EventGenerator* generator,
  1797. const gfx::Point& location) {
  1798. // Generates the following events at |location| in the given order:
  1799. // ET_GESTURE_SCROLL_UPDATE, ET_GESTURE_SCROLL_END, ET_GESTURE_END
  1800. generate_gesture_event(generator, location, ui::ET_GESTURE_SCROLL_UPDATE);
  1801. generate_gesture_event(generator, location, ui::ET_GESTURE_SCROLL_END);
  1802. generate_gesture_event(generator, location, ui::ET_GESTURE_END);
  1803. };
  1804. // Start cycle. Alt-tab should contain windows from all desks with tab slider.
  1805. cycle_controller->StartCycling();
  1806. auto cycle_windows = GetWindows(cycle_controller);
  1807. EXPECT_FALSE(cycle_controller->IsAltTabPerActiveDesk());
  1808. EXPECT_EQ(3u, cycle_windows.size());
  1809. EXPECT_EQ(cycle_windows.size(), GetWindowCycleItemViews().size());
  1810. auto tab_slider_buttons = GetWindowCycleTabSliderButtons();
  1811. EXPECT_EQ(2u, tab_slider_buttons.size());
  1812. // Tap current desk tab slider button, scroll from it to one window,
  1813. // mode change should not happen. It's still the all desks mode.
  1814. gfx::Point current_desk_button_center_point =
  1815. tab_slider_buttons[1]->GetBoundsInScreen().CenterPoint();
  1816. EXPECT_FALSE(cycle_controller->IsAltTabPerActiveDesk());
  1817. tab_slider_buttons = GetWindowCycleTabSliderButtons();
  1818. cycle_windows = GetWindows(cycle_controller);
  1819. current_desk_button_center_point =
  1820. tab_slider_buttons[1]->GetBoundsInScreen().CenterPoint();
  1821. gfx::Point window_center_point =
  1822. cycle_windows[0]->GetBoundsInScreen().CenterPoint();
  1823. tap_then_scroll(generator, current_desk_button_center_point);
  1824. scroll_update(generator, window_center_point);
  1825. EXPECT_FALSE(cycle_controller->IsAltTabPerActiveDesk());
  1826. EXPECT_EQ(3u, GetWindowCycleItemViews().size());
  1827. EXPECT_EQ(cycle_windows.size(), GetWindowCycleItemViews().size());
  1828. CompleteCycling(cycle_controller);
  1829. }
  1830. // Tests that if user uses only one desk, the tab slider and no recent items
  1831. // are not shown. Moreover, `SetAltTabMode()` should not change the windows
  1832. // list.
  1833. TEST_F(ModeSelectionWindowCycleControllerTest, SingleDeskHidesInteractiveMode) {
  1834. WindowCycleController* cycle_controller =
  1835. Shell::Get()->window_cycle_controller();
  1836. // Create two windows in the current desk.
  1837. auto win0 = CreateAppWindow(gfx::Rect(0, 0, 250, 100));
  1838. auto win1 = CreateAppWindow(gfx::Rect(50, 50, 200, 200));
  1839. auto* desks_controller = DesksController::Get();
  1840. ASSERT_EQ(1u, desks_controller->desks().size());
  1841. // Alt-tab should contain windows from all desks without any the tab slider
  1842. // and no-recent-items view.
  1843. cycle_controller->StartCycling();
  1844. EXPECT_TRUE(!GetWindowCycleNoRecentItemsLabel());
  1845. EXPECT_FALSE(cycle_controller->IsAltTabPerActiveDesk());
  1846. auto cycle_windows = GetWindows(cycle_controller);
  1847. EXPECT_EQ(2u, cycle_windows.size());
  1848. EXPECT_EQ(cycle_windows.size(), GetWindowCycleItemViews().size());
  1849. const gfx::Rect alttab_bounds_without_tab_slider =
  1850. GetWindowCycleListWidget()->GetWindowBoundsInScreen();
  1851. CompleteCycling(cycle_controller);
  1852. // Create an empty desk_2 and start alt-tab to enter the all-desks mode.
  1853. desks_controller->NewDesk(DesksCreationRemovalSource::kButton);
  1854. const Desk* desk_2 = desks_controller->desks()[1].get();
  1855. ActivateDesk(desk_2);
  1856. EXPECT_EQ(desk_2, desks_controller->active_desk());
  1857. cycle_controller->StartCycling();
  1858. EXPECT_FALSE(cycle_controller->IsAltTabPerActiveDesk());
  1859. EXPECT_EQ(2u, cycle_windows.size());
  1860. EXPECT_EQ(cycle_windows.size(), GetWindowCycleItemViews().size());
  1861. // Expect mode-switching buttons and no-recent-item label to exist.
  1862. EXPECT_FALSE(!GetWindowCycleNoRecentItemsLabel());
  1863. auto tab_slider_buttons = GetWindowCycleTabSliderButtons();
  1864. EXPECT_EQ(2u, tab_slider_buttons.size());
  1865. const gfx::Rect alttab_bounds_with_tab_slider =
  1866. GetWindowCycleListWidget()->GetWindowBoundsInScreen();
  1867. const int window_cycle_list_y =
  1868. GetWindowCycleItemViews()[0]->GetBoundsInScreen().y();
  1869. const gfx::Rect tab_slider_button_bound =
  1870. tab_slider_buttons[0]->GetBoundsInScreen();
  1871. // Expect that alt-tab views height is larger due to the tab slider insertion
  1872. // and expect that window cycle list is placed below the tab slider.
  1873. EXPECT_LT(alttab_bounds_without_tab_slider.height(),
  1874. alttab_bounds_with_tab_slider.height());
  1875. EXPECT_LT(tab_slider_button_bound.y() + tab_slider_button_bound.height(),
  1876. window_cycle_list_y);
  1877. CompleteCyclingAndDeskSwitching(cycle_controller);
  1878. }
  1879. // Tests that alt-tab shows all windows in an all-desk mode by default and
  1880. // shows only windows in the current desk in a current-desk mode. Switching
  1881. // between two modes should refresh the window list, while re-entering alt-tab
  1882. // should display the most recently selected mode.
  1883. TEST_F(ModeSelectionWindowCycleControllerTest, CycleShowsWindowsPerMode) {
  1884. WindowCycleController* cycle_controller =
  1885. Shell::Get()->window_cycle_controller();
  1886. // Create two windows for desk1 and three windows for desk2.
  1887. auto win0 = CreateAppWindow(gfx::Rect(0, 0, 250, 100));
  1888. auto win1 = CreateAppWindow(gfx::Rect(50, 50, 200, 200));
  1889. auto* desks_controller = DesksController::Get();
  1890. desks_controller->NewDesk(DesksCreationRemovalSource::kButton);
  1891. ASSERT_EQ(2u, desks_controller->desks().size());
  1892. const Desk* desk_2 = desks_controller->desks()[1].get();
  1893. ActivateDesk(desk_2);
  1894. EXPECT_EQ(desk_2, desks_controller->active_desk());
  1895. auto win2 = CreateAppWindow(gfx::Rect(0, 0, 300, 200));
  1896. auto win3 = CreateAppWindow(gfx::Rect(10, 30, 400, 200));
  1897. auto win4 = CreateAppWindow(gfx::Rect(10, 30, 400, 200));
  1898. // By default should contain windows from all desks.
  1899. auto* generator = GetEventGenerator();
  1900. // Press and hold an alt key to test that alt + left clicking a button works.
  1901. generator->PressKey(ui::VKEY_MENU, ui::EF_NONE);
  1902. cycle_controller->StartCycling();
  1903. EXPECT_FALSE(cycle_controller->IsAltTabPerActiveDesk());
  1904. auto cycle_windows = GetWindows(cycle_controller);
  1905. EXPECT_EQ(5u, cycle_windows.size());
  1906. EXPECT_EQ(cycle_windows.size(), GetWindowCycleItemViews().size());
  1907. EXPECT_TRUE(base::Contains(cycle_windows, win0.get()));
  1908. EXPECT_TRUE(base::Contains(cycle_windows, win1.get()));
  1909. EXPECT_TRUE(base::Contains(cycle_windows, win2.get()));
  1910. EXPECT_TRUE(base::Contains(cycle_windows, win3.get()));
  1911. EXPECT_TRUE(base::Contains(cycle_windows, win4.get()));
  1912. // Switching alt-tab to the current-desk mode should show windows in the
  1913. // active desk.
  1914. SwitchPerDeskAltTabMode(true);
  1915. cycle_windows = GetWindows(cycle_controller);
  1916. EXPECT_EQ(3u, GetWindowCycleItemViews().size());
  1917. EXPECT_EQ(cycle_windows.size(), GetWindowCycleItemViews().size());
  1918. EXPECT_TRUE(base::Contains(cycle_windows, win2.get()));
  1919. EXPECT_TRUE(base::Contains(cycle_windows, win3.get()));
  1920. EXPECT_TRUE(base::Contains(cycle_windows, win4.get()));
  1921. CompleteCycling(cycle_controller);
  1922. // Activate desk1 and start alt-tab.
  1923. const Desk* desk_1 = desks_controller->desks()[0].get();
  1924. ActivateDesk(desk_1);
  1925. cycle_controller->StartCycling();
  1926. // Should start alt-tab with the current-desk mode and show only two windows
  1927. // from desk1.
  1928. EXPECT_TRUE(cycle_controller->IsAltTabPerActiveDesk());
  1929. cycle_windows = GetWindows(cycle_controller);
  1930. EXPECT_EQ(2u, GetWindowCycleItemViews().size());
  1931. EXPECT_EQ(cycle_windows.size(), GetWindowCycleItemViews().size());
  1932. EXPECT_TRUE(base::Contains(cycle_windows, win0.get()));
  1933. EXPECT_TRUE(base::Contains(cycle_windows, win1.get()));
  1934. // Switch to the all-desks mode, check and stop alt-tab.
  1935. SwitchPerDeskAltTabMode(false);
  1936. cycle_windows = GetWindows(cycle_controller);
  1937. EXPECT_EQ(5u, cycle_windows.size());
  1938. EXPECT_EQ(cycle_windows.size(), GetWindowCycleItemViews().size());
  1939. CompleteCyclingAndDeskSwitching(cycle_controller);
  1940. generator->ReleaseKey(ui::VKEY_MENU, ui::EF_NONE);
  1941. }
  1942. // For one window in the current-desk mode, if there are other windows in other
  1943. // desk, tests that alt-tab view always shows up, so the user can switch mode
  1944. // and select other windows.
  1945. TEST_F(ModeSelectionWindowCycleControllerTest, OneWindowInActiveDesk) {
  1946. WindowCycleController* cycle_controller =
  1947. Shell::Get()->window_cycle_controller();
  1948. // Create two desks with a window each.
  1949. auto win0 = CreateAppWindow(gfx::Rect(0, 0, 250, 100));
  1950. auto* desks_controller = DesksController::Get();
  1951. desks_controller->NewDesk(DesksCreationRemovalSource::kButton);
  1952. ASSERT_EQ(2u, desks_controller->desks().size());
  1953. const Desk* desk_2 = desks_controller->desks()[1].get();
  1954. ActivateDesk(desk_2);
  1955. EXPECT_EQ(desk_2, desks_controller->active_desk());
  1956. auto win1 = CreateAppWindow(gfx::Rect(0, 0, 300, 200));
  1957. // Starting alt-tab should shows all desks.
  1958. cycle_controller->StartCycling();
  1959. auto cycle_windows = GetWindows(cycle_controller);
  1960. EXPECT_EQ(2u, GetWindowCycleItemViews().size());
  1961. EXPECT_EQ(cycle_windows.size(), GetWindowCycleItemViews().size());
  1962. // Switching to an active desk mode should shows a single window in desk2.
  1963. SwitchPerDeskAltTabMode(true);
  1964. EXPECT_TRUE(cycle_controller->IsCycling());
  1965. cycle_windows = GetWindows(cycle_controller);
  1966. EXPECT_EQ(1u, GetWindowCycleItemViews().size());
  1967. EXPECT_EQ(cycle_windows.size(), GetWindowCycleItemViews().size());
  1968. EXPECT_TRUE(base::Contains(cycle_windows, win1.get()));
  1969. CompleteCycling(cycle_controller);
  1970. // Re-opening alt-tab again in the current-desk mode should work because the
  1971. // user should be able to switch to the window in other desks.
  1972. cycle_controller->HandleCycleWindow(
  1973. WindowCycleController::WindowCyclingDirection::kForward);
  1974. EXPECT_TRUE(cycle_controller->IsCycling());
  1975. cycle_windows = GetWindows(cycle_controller);
  1976. EXPECT_EQ(1u, GetWindowCycleItemViews().size());
  1977. EXPECT_EQ(cycle_windows.size(), GetWindowCycleItemViews().size());
  1978. EXPECT_TRUE(base::Contains(cycle_windows, win1.get()));
  1979. CompleteCycling(cycle_controller);
  1980. }
  1981. // For one window in the current-desk mode, if there is no other window in
  1982. // other desks, tests that alt-tab does not show up, but still activates the
  1983. // window properly.
  1984. TEST_F(ModeSelectionWindowCycleControllerTest, OneWindowTotalInActiveDesk) {
  1985. WindowCycleController* cycle_controller =
  1986. Shell::Get()->window_cycle_controller();
  1987. // Create two desk with only one window in the current desk.
  1988. auto* desks_controller = DesksController::Get();
  1989. desks_controller->NewDesk(DesksCreationRemovalSource::kButton);
  1990. ASSERT_EQ(2u, desks_controller->desks().size());
  1991. const Desk* desk_2 = desks_controller->desks()[1].get();
  1992. ActivateDesk(desk_2);
  1993. EXPECT_EQ(desk_2, desks_controller->active_desk());
  1994. auto win0 = CreateAppWindow(gfx::Rect(0, 0, 300, 200));
  1995. // Starting alt-tab should not show the view and only activate the window.
  1996. cycle_controller->StartCycling();
  1997. EXPECT_TRUE(cycle_controller->IsCycling());
  1998. EXPECT_FALSE(CycleViewExists());
  1999. EXPECT_TRUE(wm::IsActiveWindow(win0.get()));
  2000. EXPECT_TRUE(WindowState::Get(win0.get())->IsActive());
  2001. CompleteCycling(cycle_controller);
  2002. // Tests that the same behavior for an inactive window.
  2003. WindowState::Get(win0.get())->Minimize();
  2004. EXPECT_FALSE(wm::IsActiveWindow(win0.get()));
  2005. cycle_controller->HandleCycleWindow(
  2006. WindowCycleController::WindowCyclingDirection::kForward);
  2007. EXPECT_TRUE(cycle_controller->IsCycling());
  2008. EXPECT_FALSE(CycleViewExists());
  2009. EXPECT_TRUE(wm::IsActiveWindow(win0.get()));
  2010. EXPECT_TRUE(WindowState::Get(win0.get())->IsActive());
  2011. CompleteCycling(cycle_controller);
  2012. }
  2013. // For no window in the current-desk mode, if there are other windows in other
  2014. // desk, tests that alt-tab view always shows up, so the user can switch mode
  2015. // and select other windows. Additionally, tests that while the focus is on the
  2016. // tab slider button, pressing the Down arrow key does nothing.
  2017. TEST_F(ModeSelectionWindowCycleControllerTest, NoWindowInActiveDesk) {
  2018. WindowCycleController* cycle_controller =
  2019. Shell::Get()->window_cycle_controller();
  2020. ui::test::EventGenerator* generator = GetEventGenerator();
  2021. // Create two desks with a window in desk1.
  2022. auto win0 = CreateAppWindow(gfx::Rect(0, 0, 250, 100));
  2023. auto win1 = CreateAppWindow(gfx::Rect(50, 50, 200, 200));
  2024. auto* desks_controller = DesksController::Get();
  2025. desks_controller->NewDesk(DesksCreationRemovalSource::kButton);
  2026. ASSERT_EQ(2u, desks_controller->desks().size());
  2027. const Desk* desk_2 = desks_controller->desks()[1].get();
  2028. // Activate desk2.
  2029. ActivateDesk(desk_2);
  2030. EXPECT_EQ(desk_2, desks_controller->active_desk());
  2031. // Starting alt-tab should show all windows from all desks.
  2032. cycle_controller->StartCycling();
  2033. auto cycle_windows = GetWindows(cycle_controller);
  2034. EXPECT_EQ(2u, GetWindowCycleItemViews().size());
  2035. EXPECT_EQ(cycle_windows.size(), GetWindowCycleItemViews().size());
  2036. EXPECT_FALSE(GetWindowCycleNoRecentItemsLabel()->GetVisible());
  2037. // Switching to an current-desk mode should not show any mirror window
  2038. // and should display "no recent items" label.
  2039. SwitchPerDeskAltTabMode(true);
  2040. EXPECT_TRUE(cycle_controller->IsCycling());
  2041. cycle_windows = GetWindows(cycle_controller);
  2042. EXPECT_EQ(0u, GetWindowCycleItemViews().size());
  2043. EXPECT_EQ(cycle_windows.size(), GetWindowCycleItemViews().size());
  2044. EXPECT_TRUE(GetWindowCycleNoRecentItemsLabel()->GetVisible());
  2045. // Switching back to an all-desks mode should hide the label.
  2046. SwitchPerDeskAltTabMode(false);
  2047. EXPECT_FALSE(GetWindowCycleNoRecentItemsLabel()->GetVisible());
  2048. // Focus the current-desk button and make sure that pressing Down arrow
  2049. // key does nothing, i.e. the focus remains on the mode button.
  2050. generator->PressKey(ui::VKEY_UP, ui::EF_NONE);
  2051. generator->PressKey(ui::VKEY_RIGHT, ui::EF_NONE);
  2052. generator->PressKey(ui::VKEY_DOWN, ui::EF_NONE);
  2053. EXPECT_TRUE(cycle_controller->IsTabSliderFocused());
  2054. EXPECT_TRUE(cycle_controller->IsAltTabPerActiveDesk());
  2055. CompleteCycling(cycle_controller);
  2056. // Entering alt-tab in the current-desk mode with zero window should work and
  2057. // show no-recent-item label.
  2058. cycle_controller->StartCycling();
  2059. cycle_windows = GetWindows(cycle_controller);
  2060. EXPECT_EQ(0u, GetWindowCycleItemViews().size());
  2061. EXPECT_EQ(cycle_windows.size(), GetWindowCycleItemViews().size());
  2062. EXPECT_EQ(nullptr, GetTargetWindow());
  2063. EXPECT_TRUE(GetWindowCycleNoRecentItemsLabel()->GetVisible());
  2064. }
  2065. // For no window in the current-desk mode, if there is no other window in
  2066. // other desks, tests that alt-tab does not show up.
  2067. TEST_F(ModeSelectionWindowCycleControllerTest, NoWindowTotalInActiveDesk) {
  2068. WindowCycleController* cycle_controller =
  2069. Shell::Get()->window_cycle_controller();
  2070. // Create two desks with all two windows in desk1.
  2071. auto* desks_controller = DesksController::Get();
  2072. desks_controller->NewDesk(DesksCreationRemovalSource::kButton);
  2073. ASSERT_EQ(2u, desks_controller->desks().size());
  2074. const Desk* desk_2 = desks_controller->desks()[1].get();
  2075. // Activate desk2.
  2076. ActivateDesk(desk_2);
  2077. EXPECT_EQ(desk_2, desks_controller->active_desk());
  2078. // Starting alt-tab should show all windows from all desks.
  2079. cycle_controller->HandleCycleWindow(
  2080. WindowCycleController::WindowCyclingDirection::kForward);
  2081. EXPECT_TRUE(cycle_controller->IsCycling());
  2082. EXPECT_FALSE(CycleViewExists());
  2083. CompleteCycling(cycle_controller);
  2084. }
  2085. // Tests that switching between modes correctly reset the alt-tab-highlighted
  2086. // window to the second most recently used window, i.e. the next window to tab
  2087. // into from the currently used window. Since the window cycle list is ordered
  2088. // by MRU, such window is therefore the second window in the MRU list.
  2089. TEST_F(ModeSelectionWindowCycleControllerTest,
  2090. SwitchingModeUpdatesWindowHighlight) {
  2091. WindowCycleController* cycle_controller =
  2092. Shell::Get()->window_cycle_controller();
  2093. // Create two windows for desk1 and three windows for desk2 in the reversed
  2094. // order of the most recently active window.
  2095. auto win4 = CreateAppWindow(gfx::Rect(0, 0, 250, 100));
  2096. auto win3 = CreateAppWindow(gfx::Rect(50, 50, 200, 200));
  2097. auto* desks_controller = DesksController::Get();
  2098. desks_controller->NewDesk(DesksCreationRemovalSource::kButton);
  2099. ASSERT_EQ(2u, desks_controller->desks().size());
  2100. const Desk* desk_2 = desks_controller->desks()[1].get();
  2101. ActivateDesk(desk_2);
  2102. EXPECT_EQ(desk_2, desks_controller->active_desk());
  2103. auto win2 = CreateAppWindow(gfx::Rect(0, 0, 300, 200));
  2104. auto win1 = CreateAppWindow(gfx::Rect(10, 30, 400, 200));
  2105. auto win0 = CreateAppWindow(gfx::Rect(10, 30, 400, 200));
  2106. // Enter the all-desk mode by default with the window order [0, 1, 2, 3 ,4].
  2107. cycle_controller->StartCycling();
  2108. cycle_controller->HandleCycleWindow(
  2109. WindowCycleController::WindowCyclingDirection::kForward);
  2110. EXPECT_FALSE(cycle_controller->IsAltTabPerActiveDesk());
  2111. auto cycle_windows = GetWindows(cycle_controller);
  2112. // The window list is MRU ordered.
  2113. EXPECT_EQ(win0.get(), cycle_windows[0]);
  2114. EXPECT_EQ(win1.get(), cycle_windows[1]);
  2115. EXPECT_EQ(win2.get(), cycle_windows[2]);
  2116. EXPECT_EQ(win3.get(), cycle_windows[3]);
  2117. EXPECT_EQ(win4.get(), cycle_windows[4]);
  2118. // Alt-Tab should highlight the second most recently used window, which is
  2119. // the second window in the MRU list, win1.
  2120. EXPECT_EQ(win1.get(), GetTargetWindow());
  2121. // Step to win2 and win3, so we are now select a window in a non-active desk.
  2122. cycle_controller->HandleCycleWindow(
  2123. WindowCycleController::WindowCyclingDirection::kForward);
  2124. EXPECT_EQ(win2.get(), GetTargetWindow());
  2125. cycle_controller->HandleCycleWindow(
  2126. WindowCycleController::WindowCyclingDirection::kForward);
  2127. EXPECT_EQ(win3.get(), GetTargetWindow());
  2128. // Switching from the all-desks mode, which highlights a non-current-desk
  2129. // window to the current-desk mode [0, 1, 2] should resolve the highlight
  2130. // correctly to win1, the second window in the cycle list.
  2131. SwitchPerDeskAltTabMode(true);
  2132. EXPECT_EQ(win1.get(), GetTargetWindow());
  2133. EXPECT_EQ(win1.get(), cycle_windows[1]);
  2134. // Step to win2.
  2135. cycle_controller->HandleCycleWindow(
  2136. WindowCycleController::WindowCyclingDirection::kForward);
  2137. EXPECT_EQ(win2.get(), GetTargetWindow());
  2138. // Switching back to the all-desk mode should reset highlight to win1 again.
  2139. SwitchPerDeskAltTabMode(false);
  2140. EXPECT_EQ(win1.get(), GetTargetWindow());
  2141. CompleteCycling(cycle_controller);
  2142. }
  2143. // Similar to `SwitchingModeUpdatesWindowHighlight`, tests that switching the
  2144. // alt-tab mode updates the highlighted window to the first window (most
  2145. // recently used) in the special case where all windows are minimized.
  2146. // When they are minimized, cycling forward should help unminimize the most
  2147. // recently used window rather than trying to open the second most recently
  2148. // used window.
  2149. TEST_F(ModeSelectionWindowCycleControllerTest,
  2150. SwitchingModeUpdatesMinimizedWindowHighlight) {
  2151. WindowCycleController* cycle_controller =
  2152. Shell::Get()->window_cycle_controller();
  2153. // Create two windows for desk1 and three windows for desk2 in the reversed
  2154. // order of the most recently active window.
  2155. auto win4 = CreateAppWindow(gfx::Rect(0, 0, 250, 100));
  2156. auto win3 = CreateAppWindow(gfx::Rect(50, 50, 200, 200));
  2157. auto* desks_controller = DesksController::Get();
  2158. desks_controller->NewDesk(DesksCreationRemovalSource::kButton);
  2159. ASSERT_EQ(2u, desks_controller->desks().size());
  2160. const Desk* desk_2 = desks_controller->desks()[1].get();
  2161. ActivateDesk(desk_2);
  2162. EXPECT_EQ(desk_2, desks_controller->active_desk());
  2163. auto win2 = CreateAppWindow(gfx::Rect(0, 0, 300, 200));
  2164. auto win1 = CreateAppWindow(gfx::Rect(10, 30, 400, 200));
  2165. auto win0 = CreateAppWindow(gfx::Rect(10, 30, 400, 200));
  2166. // Minimize all windows to test this special case.
  2167. WindowState::Get(win4.get())->Minimize();
  2168. WindowState::Get(win3.get())->Minimize();
  2169. WindowState::Get(win2.get())->Minimize();
  2170. WindowState::Get(win1.get())->Minimize();
  2171. WindowState::Get(win0.get())->Minimize();
  2172. EXPECT_FALSE(WindowState::Get(win0.get())->IsActive());
  2173. EXPECT_FALSE(WindowState::Get(win1.get())->IsActive());
  2174. EXPECT_FALSE(WindowState::Get(win2.get())->IsActive());
  2175. EXPECT_FALSE(WindowState::Get(win3.get())->IsActive());
  2176. EXPECT_FALSE(WindowState::Get(win4.get())->IsActive());
  2177. // Enter the all-desk mode by default with the window order [0, 1, 2, 3 ,4].
  2178. cycle_controller->HandleCycleWindow(
  2179. WindowCycleController::WindowCyclingDirection::kForward);
  2180. EXPECT_EQ(win0.get(), GetTargetWindow());
  2181. EXPECT_FALSE(cycle_controller->IsAltTabPerActiveDesk());
  2182. auto cycle_windows = GetWindows(cycle_controller);
  2183. EXPECT_EQ(5u, GetWindowCycleItemViews().size());
  2184. // The window list is MRU ordered.
  2185. EXPECT_EQ(win0.get(), cycle_windows[0]);
  2186. EXPECT_EQ(win1.get(), cycle_windows[1]);
  2187. EXPECT_EQ(win2.get(), cycle_windows[2]);
  2188. EXPECT_EQ(win3.get(), cycle_windows[3]);
  2189. EXPECT_EQ(win4.get(), cycle_windows[4]);
  2190. // Step forward a few times and switch to all-desks mode. This should
  2191. // highlight win0, the first window in the current-desk cycle list.
  2192. cycle_controller->HandleCycleWindow(
  2193. WindowCycleController::WindowCyclingDirection::kForward);
  2194. EXPECT_EQ(win1.get(), GetTargetWindow());
  2195. cycle_controller->HandleCycleWindow(
  2196. WindowCycleController::WindowCyclingDirection::kForward);
  2197. EXPECT_EQ(win2.get(), GetTargetWindow());
  2198. SwitchPerDeskAltTabMode(true);
  2199. EXPECT_EQ(3u, GetWindowCycleItemViews().size());
  2200. EXPECT_EQ(win0.get(), GetTargetWindow());
  2201. EXPECT_EQ(win0.get(), cycle_windows[0]);
  2202. // Stepping to win1 and switching back to the all-desk mode should reset
  2203. // a highlight to win0 again.
  2204. cycle_controller->HandleCycleWindow(
  2205. WindowCycleController::WindowCyclingDirection::kForward);
  2206. EXPECT_EQ(win1.get(), GetTargetWindow());
  2207. SwitchPerDeskAltTabMode(false);
  2208. EXPECT_EQ(5u, GetWindowCycleItemViews().size());
  2209. EXPECT_EQ(win0.get(), GetTargetWindow());
  2210. CompleteCycling(cycle_controller);
  2211. }
  2212. // Tests that pressing an up arrow focus the active tab slider button.
  2213. // While a tab slider button is focus, user can switch to the other button
  2214. // via left or right key. Note that if user already selects the left button,
  2215. // attempting to go further left would do nothing.
  2216. TEST_F(ModeSelectionWindowCycleControllerTest, KeyboardNavigation) {
  2217. ui::test::EventGenerator* generator = GetEventGenerator();
  2218. WindowCycleController* cycle_controller =
  2219. Shell::Get()->window_cycle_controller();
  2220. // Create two windows for desk1 and three windows for desk2 in the reversed
  2221. // order of the most recently active window.
  2222. auto win4 = CreateAppWindow(gfx::Rect(0, 0, 250, 100));
  2223. auto win3 = CreateAppWindow(gfx::Rect(50, 50, 200, 200));
  2224. auto* desks_controller = DesksController::Get();
  2225. desks_controller->NewDesk(DesksCreationRemovalSource::kButton);
  2226. ASSERT_EQ(2u, desks_controller->desks().size());
  2227. const Desk* desk_2 = desks_controller->desks()[1].get();
  2228. ActivateDesk(desk_2);
  2229. EXPECT_EQ(desk_2, desks_controller->active_desk());
  2230. auto win2 = CreateAppWindow(gfx::Rect(0, 0, 300, 200));
  2231. auto win1 = CreateAppWindow(gfx::Rect(10, 30, 400, 200));
  2232. auto win0 = CreateAppWindow(gfx::Rect(10, 30, 400, 200));
  2233. // Start alt-tab.
  2234. cycle_controller->HandleCycleWindow(
  2235. WindowCycleController::WindowCyclingDirection::kForward);
  2236. EXPECT_EQ(win1.get(), GetTargetWindow());
  2237. views::View::Views tab_slider_buttons = GetWindowCycleTabSliderButtons();
  2238. EXPECT_FALSE(cycle_controller->IsTabSliderFocused());
  2239. EXPECT_FALSE(cycle_controller->IsAltTabPerActiveDesk());
  2240. // Focus tab slider mode: pressing the up arrow key should focus the
  2241. // default all-desks, which is the left button. This should not affect
  2242. // the focus on the window cycle.
  2243. generator->PressKey(ui::VKEY_UP, ui::EF_NONE);
  2244. EXPECT_TRUE(cycle_controller->IsTabSliderFocused());
  2245. EXPECT_FALSE(cycle_controller->IsAltTabPerActiveDesk());
  2246. EXPECT_EQ(win1.get(), GetTargetWindow());
  2247. // Switching to the right, current-desk button via a right arrow key changes
  2248. // to current-desk mode and does not affect the highlighted window.
  2249. generator->PressKey(ui::VKEY_RIGHT, ui::EF_NONE);
  2250. EXPECT_TRUE(cycle_controller->IsTabSliderFocused());
  2251. EXPECT_TRUE(cycle_controller->IsAltTabPerActiveDesk());
  2252. EXPECT_EQ(3u, GetWindowCycleItemViews().size());
  2253. EXPECT_EQ(win1.get(), GetTargetWindow());
  2254. // Trying to move the focus further right should do nothing since it is
  2255. // already on the right most button.
  2256. generator->PressKey(ui::VKEY_RIGHT, ui::EF_NONE);
  2257. EXPECT_TRUE(cycle_controller->IsTabSliderFocused());
  2258. EXPECT_TRUE(cycle_controller->IsAltTabPerActiveDesk());
  2259. EXPECT_FALSE(wm::IsActiveWindow(win1.get()));
  2260. EXPECT_EQ(win1.get(), GetTargetWindow());
  2261. CompleteCycling(cycle_controller);
  2262. // Exit alt-tab while focusing the tab slider and check that the keyboard
  2263. // navigation within the tab slider does not affect the window activation.
  2264. EXPECT_TRUE(wm::IsActiveWindow(win1.get()));
  2265. // Start alt-tab and focus the tab slider. The order of cycle window is now
  2266. // [1, 0, 2, 3, 4].
  2267. cycle_controller->HandleCycleWindow(
  2268. WindowCycleController::WindowCyclingDirection::kForward);
  2269. generator->PressKey(ui::VKEY_UP, ui::EF_NONE);
  2270. EXPECT_TRUE(cycle_controller->IsTabSliderFocused());
  2271. EXPECT_TRUE(cycle_controller->IsAltTabPerActiveDesk());
  2272. EXPECT_EQ(win0.get(), GetTargetWindow());
  2273. // Switching to the left, all-desks button via a left arrow key changes
  2274. // to current-desk mode and does not affect the highlighted window.
  2275. generator->PressKey(ui::VKEY_LEFT, ui::EF_NONE);
  2276. EXPECT_TRUE(cycle_controller->IsTabSliderFocused());
  2277. EXPECT_FALSE(cycle_controller->IsAltTabPerActiveDesk());
  2278. EXPECT_EQ(5u, GetWindowCycleItemViews().size());
  2279. EXPECT_EQ(win0.get(), GetTargetWindow());
  2280. // Trying to move the focus further left should do nothing since it is
  2281. // already on the left most button.
  2282. generator->PressKey(ui::VKEY_LEFT, ui::EF_NONE);
  2283. EXPECT_TRUE(cycle_controller->IsTabSliderFocused());
  2284. EXPECT_FALSE(cycle_controller->IsAltTabPerActiveDesk());
  2285. EXPECT_EQ(win0.get(), GetTargetWindow());
  2286. // Stop focusing the tab slider button by pressing a down arrow key to
  2287. // continue navigation in the window cycle list.
  2288. generator->PressKey(ui::VKEY_DOWN, ui::EF_NONE);
  2289. EXPECT_FALSE(cycle_controller->IsTabSliderFocused());
  2290. EXPECT_FALSE(cycle_controller->IsAltTabPerActiveDesk());
  2291. EXPECT_EQ(5u, GetWindowCycleItemViews().size());
  2292. EXPECT_EQ(win0.get(), GetTargetWindow());
  2293. // Now navigating left and right should only affect the highlighted window
  2294. // but not the tab slider buttons.
  2295. // Pressing right twice should move the focus to win3.
  2296. generator->PressKey(ui::VKEY_RIGHT, ui::EF_NONE);
  2297. generator->PressKey(ui::VKEY_RIGHT, ui::EF_NONE);
  2298. EXPECT_FALSE(cycle_controller->IsTabSliderFocused());
  2299. EXPECT_FALSE(cycle_controller->IsAltTabPerActiveDesk());
  2300. EXPECT_EQ(win3.get(), GetTargetWindow());
  2301. // Pressing left once should move focus back to win2.
  2302. generator->PressKey(ui::VKEY_LEFT, ui::EF_NONE);
  2303. EXPECT_FALSE(cycle_controller->IsTabSliderFocused());
  2304. EXPECT_FALSE(cycle_controller->IsAltTabPerActiveDesk());
  2305. EXPECT_EQ(win2.get(), GetTargetWindow());
  2306. CompleteCycling(cycle_controller);
  2307. EXPECT_TRUE(wm::IsActiveWindow(win2.get()));
  2308. }
  2309. // Tests that clicking the alt-tab slider button removes the focus from the
  2310. // button and resets the focus to the target window in the cycle list. After
  2311. // clicking the button, the user then needs to press tge Up arrow key again if
  2312. // the user want to switch between the alt-tab modes via keyboard navigation.
  2313. TEST_F(ModeSelectionWindowCycleControllerTest, KeyboardNavigationAfterClick) {
  2314. ui::test::EventGenerator* generator = GetEventGenerator();
  2315. WindowCycleController* cycle_controller =
  2316. Shell::Get()->window_cycle_controller();
  2317. // Create two windows for desk1 and three windows for desk2 in the reversed
  2318. // order of the most recently active window.
  2319. auto win4 = CreateAppWindow(gfx::Rect(0, 0, 250, 100));
  2320. auto win3 = CreateAppWindow(gfx::Rect(50, 50, 200, 200));
  2321. auto* desks_controller = DesksController::Get();
  2322. desks_controller->NewDesk(DesksCreationRemovalSource::kButton);
  2323. ASSERT_EQ(2u, desks_controller->desks().size());
  2324. const Desk* desk_2 = desks_controller->desks()[1].get();
  2325. ActivateDesk(desk_2);
  2326. EXPECT_EQ(desk_2, desks_controller->active_desk());
  2327. auto win2 = CreateAppWindow(gfx::Rect(0, 0, 300, 200));
  2328. auto win1 = CreateAppWindow(gfx::Rect(10, 30, 400, 200));
  2329. auto win0 = CreateAppWindow(gfx::Rect(10, 30, 400, 200));
  2330. // Start alt-tab.
  2331. cycle_controller->HandleCycleWindow(
  2332. WindowCycleController::WindowCyclingDirection::kForward);
  2333. EXPECT_EQ(win1.get(), GetTargetWindow());
  2334. views::View::Views tab_slider_buttons = GetWindowCycleTabSliderButtons();
  2335. EXPECT_FALSE(cycle_controller->IsTabSliderFocused());
  2336. EXPECT_FALSE(cycle_controller->IsAltTabPerActiveDesk());
  2337. // Focus tab slider mode: pressing the Up arrow key should focus the
  2338. // default all-desks, which is the left button. This should not affect
  2339. // the focus on the window cycle.
  2340. generator->PressKey(ui::VKEY_UP, ui::EF_NONE);
  2341. EXPECT_TRUE(cycle_controller->IsTabSliderFocused());
  2342. EXPECT_FALSE(cycle_controller->IsAltTabPerActiveDesk());
  2343. EXPECT_EQ(win1.get(), GetTargetWindow());
  2344. // Switching to the right, current-desk button via the Right arrow key changes
  2345. // to the current-desk mode and does not affect the highlighted window.
  2346. generator->PressKey(ui::VKEY_RIGHT, ui::EF_NONE);
  2347. EXPECT_TRUE(cycle_controller->IsTabSliderFocused());
  2348. EXPECT_TRUE(cycle_controller->IsAltTabPerActiveDesk());
  2349. EXPECT_EQ(3u, GetWindowCycleItemViews().size());
  2350. EXPECT_EQ(win1.get(), GetTargetWindow());
  2351. // Clicking the same current-desk button should do nothing.
  2352. SwitchPerDeskAltTabMode(true);
  2353. EXPECT_TRUE(cycle_controller->IsTabSliderFocused());
  2354. EXPECT_TRUE(cycle_controller->IsAltTabPerActiveDesk());
  2355. EXPECT_EQ(3u, GetWindowCycleItemViews().size());
  2356. EXPECT_EQ(win1.get(), GetTargetWindow());
  2357. // Clicking the all-desk button should remove the focus from the alt-tab
  2358. // slider and pressing the Left or Right arrow change the target cycle window
  2359. // rather than switching the mode.
  2360. SwitchPerDeskAltTabMode(false);
  2361. EXPECT_FALSE(cycle_controller->IsTabSliderFocused());
  2362. EXPECT_FALSE(cycle_controller->IsAltTabPerActiveDesk());
  2363. EXPECT_EQ(5u, GetWindowCycleItemViews().size());
  2364. EXPECT_EQ(win1.get(), GetTargetWindow());
  2365. // Pressing the Right arrow key should cycle forward rather than switch to
  2366. // the current-desk mode.
  2367. generator->PressKey(ui::VKEY_RIGHT, ui::EF_NONE);
  2368. EXPECT_FALSE(cycle_controller->IsTabSliderFocused());
  2369. EXPECT_FALSE(cycle_controller->IsAltTabPerActiveDesk());
  2370. EXPECT_EQ(5u, GetWindowCycleItemViews().size());
  2371. EXPECT_EQ(win2.get(), GetTargetWindow());
  2372. CompleteCycling(cycle_controller);
  2373. // Make sure that cycling navigation after a click resets the focus does
  2374. // not affect the correctness of window activation.
  2375. EXPECT_TRUE(wm::IsActiveWindow(win2.get()));
  2376. // The window order is now [2, 0, 1, 3, 4] in the all-desks mode.
  2377. // Similar to the test above but focus the all-desks button before clicking
  2378. // and make sure that exiting alt-tab after a click resets the focus
  2379. // activates the right window.
  2380. // Start alt-tab and press the Up arrow key to focus the all-desks button.
  2381. cycle_controller->HandleCycleWindow(
  2382. WindowCycleController::WindowCyclingDirection::kForward);
  2383. EXPECT_FALSE(cycle_controller->IsTabSliderFocused());
  2384. EXPECT_FALSE(cycle_controller->IsAltTabPerActiveDesk());
  2385. EXPECT_EQ(win0.get(), GetTargetWindow());
  2386. generator->PressKey(ui::VKEY_UP, ui::EF_NONE);
  2387. EXPECT_TRUE(cycle_controller->IsTabSliderFocused());
  2388. EXPECT_FALSE(cycle_controller->IsAltTabPerActiveDesk());
  2389. EXPECT_EQ(win0.get(), GetTargetWindow());
  2390. // Click the current-desk button.
  2391. SwitchPerDeskAltTabMode(true);
  2392. EXPECT_FALSE(cycle_controller->IsTabSliderFocused());
  2393. EXPECT_TRUE(cycle_controller->IsAltTabPerActiveDesk());
  2394. EXPECT_EQ(3u, GetWindowCycleItemViews().size());
  2395. EXPECT_EQ(win0.get(), GetTargetWindow());
  2396. CompleteCycling(cycle_controller);
  2397. // Exiting after the click resets the focus should activate the right window.
  2398. EXPECT_TRUE(wm::IsActiveWindow(win0.get()));
  2399. }
  2400. // Tests that ChromeVox alerts the mode change, new target window and
  2401. // Down-arrow directional cue correctly when the user uses keyboard navigation
  2402. // and button clicking.
  2403. TEST_F(ModeSelectionWindowCycleControllerTest, ChromeVox) {
  2404. ui::test::EventGenerator* generator = GetEventGenerator();
  2405. WindowCycleController* cycle_controller =
  2406. Shell::Get()->window_cycle_controller();
  2407. Shell::Get()->accessibility_controller()->SetSpokenFeedbackEnabled(
  2408. true, A11Y_NOTIFICATION_NONE);
  2409. // Create two windows for desk1 and one window for desk2 in the reversed
  2410. // order of the most recently active window.
  2411. auto win2 = CreateAppWindow(gfx::Rect(0, 0, 300, 200));
  2412. auto win1 = CreateAppWindow(gfx::Rect(10, 30, 400, 200));
  2413. auto* desks_controller = DesksController::Get();
  2414. desks_controller->NewDesk(DesksCreationRemovalSource::kButton);
  2415. ASSERT_EQ(2u, desks_controller->desks().size());
  2416. const Desk* desk_2 = desks_controller->desks()[1].get();
  2417. ActivateDesk(desk_2);
  2418. EXPECT_EQ(desk_2, desks_controller->active_desk());
  2419. auto win0 = CreateAppWindow(gfx::Rect(10, 30, 400, 200));
  2420. TestAccessibilityControllerClient client;
  2421. const std::string kAllDesksSelected =
  2422. l10n_util::GetStringUTF8(IDS_ASH_ALT_TAB_ALL_DESKS_MODE_SELECTED_TITLE);
  2423. const std::string kCurrentDeskSelected = l10n_util::GetStringUTF8(
  2424. IDS_ASH_ALT_TAB_CURRENT_DESK_MODE_SELECTED_TITLE);
  2425. const std::string kFocusWindowDirectionalCue =
  2426. l10n_util::GetStringUTF8(IDS_ASH_ALT_TAB_FOCUS_WINDOW_LIST_TITLE);
  2427. // Start alt-tab in the default all-desks mode.
  2428. cycle_controller->HandleCycleWindow(
  2429. WindowCycleController::WindowCyclingDirection::kForward);
  2430. EXPECT_EQ(win1.get(), GetTargetWindow());
  2431. EXPECT_FALSE(cycle_controller->IsTabSliderFocused());
  2432. EXPECT_FALSE(cycle_controller->IsAltTabPerActiveDesk());
  2433. EXPECT_EQ(l10n_util::GetStringUTF8(IDS_ASH_ALT_TAB_FOCUS_ALL_DESKS_MODE),
  2434. client.last_alert_message());
  2435. // Pressing the up arrow key should focus and alert all-desks mode.
  2436. generator->PressKey(ui::VKEY_UP, ui::EF_NONE);
  2437. EXPECT_TRUE(cycle_controller->IsTabSliderFocused());
  2438. EXPECT_FALSE(cycle_controller->IsAltTabPerActiveDesk());
  2439. EXPECT_EQ(win1.get(), GetTargetWindow());
  2440. EXPECT_EQ(kAllDesksSelected, client.last_alert_message());
  2441. // Pressing (->) announces the new mode, the new focused window, and the
  2442. // Down-arrow directional cue.
  2443. generator->PressKey(ui::VKEY_RIGHT, ui::EF_NONE);
  2444. EXPECT_TRUE(cycle_controller->IsTabSliderFocused());
  2445. EXPECT_TRUE(cycle_controller->IsAltTabPerActiveDesk());
  2446. EXPECT_EQ(1u, GetWindowCycleItemViews().size());
  2447. EXPECT_EQ(win0.get(), GetTargetWindow());
  2448. std::string last_alert_message = client.last_alert_message();
  2449. EXPECT_TRUE(last_alert_message.find(kCurrentDeskSelected) !=
  2450. std::string::npos);
  2451. EXPECT_TRUE(last_alert_message.find(l10n_util::GetStringFUTF8(
  2452. IDS_ASH_ALT_TAB_WINDOW_SELECTED_TITLE, win0->GetTitle())) !=
  2453. std::string::npos);
  2454. EXPECT_TRUE(last_alert_message.find(kFocusWindowDirectionalCue) !=
  2455. std::string::npos);
  2456. // Pressing (<-) announces the new mode, the new focused window and the
  2457. // Down-arrow directional cue.
  2458. generator->PressKey(ui::VKEY_LEFT, ui::EF_NONE);
  2459. EXPECT_TRUE(cycle_controller->IsTabSliderFocused());
  2460. EXPECT_FALSE(cycle_controller->IsAltTabPerActiveDesk());
  2461. EXPECT_EQ(3u, GetWindowCycleItemViews().size());
  2462. EXPECT_EQ(win1.get(), GetTargetWindow());
  2463. last_alert_message = client.last_alert_message();
  2464. EXPECT_TRUE(last_alert_message.find(kAllDesksSelected) != std::string::npos);
  2465. EXPECT_TRUE(last_alert_message.find(l10n_util::GetStringFUTF8(
  2466. IDS_ASH_ALT_TAB_WINDOW_SELECTED_TITLE, win1->GetTitle())) !=
  2467. std::string::npos);
  2468. EXPECT_TRUE(last_alert_message.find(kFocusWindowDirectionalCue) !=
  2469. std::string::npos);
  2470. // Clicking the current-desk button notifies the new mode and the new focused
  2471. // window but not the Down-arrow directional cue because the focus is moved
  2472. // to the window, which is the bottom most component.
  2473. SwitchPerDeskAltTabMode(true);
  2474. EXPECT_FALSE(cycle_controller->IsTabSliderFocused());
  2475. EXPECT_TRUE(cycle_controller->IsAltTabPerActiveDesk());
  2476. EXPECT_EQ(1u, GetWindowCycleItemViews().size());
  2477. EXPECT_EQ(win0.get(), GetTargetWindow());
  2478. last_alert_message = client.last_alert_message();
  2479. EXPECT_TRUE(last_alert_message.find(kCurrentDeskSelected) !=
  2480. std::string::npos);
  2481. EXPECT_TRUE(last_alert_message.find(l10n_util::GetStringFUTF8(
  2482. IDS_ASH_ALT_TAB_WINDOW_SELECTED_TITLE, win0->GetTitle())) !=
  2483. std::string::npos);
  2484. EXPECT_FALSE(last_alert_message.find(kFocusWindowDirectionalCue) !=
  2485. std::string::npos);
  2486. // Pressing the Down arrow key while focusing the tab slider button should
  2487. // alert only the focused window.
  2488. generator->PressKey(ui::VKEY_UP, ui::EF_NONE);
  2489. EXPECT_TRUE(cycle_controller->IsTabSliderFocused());
  2490. generator->PressKey(ui::VKEY_DOWN, ui::EF_NONE);
  2491. EXPECT_FALSE(cycle_controller->IsTabSliderFocused());
  2492. EXPECT_TRUE(cycle_controller->IsAltTabPerActiveDesk());
  2493. EXPECT_EQ(win0.get(), GetTargetWindow());
  2494. last_alert_message = client.last_alert_message();
  2495. EXPECT_FALSE(last_alert_message.find(kCurrentDeskSelected) !=
  2496. std::string::npos);
  2497. EXPECT_TRUE(last_alert_message.find(l10n_util::GetStringFUTF8(
  2498. IDS_ASH_ALT_TAB_WINDOW_SELECTED_TITLE, win0->GetTitle())) !=
  2499. std::string::npos);
  2500. EXPECT_FALSE(last_alert_message.find(kFocusWindowDirectionalCue) !=
  2501. std::string::npos);
  2502. CompleteCycling(cycle_controller);
  2503. EXPECT_TRUE(wm::IsActiveWindow(win0.get()));
  2504. // Start alt-tab in the current-desk mode.
  2505. // Need to create one more window so we have >1 window to enter alt-tab.
  2506. auto win3 = CreateAppWindow(gfx::Rect(10, 30, 400, 200));
  2507. cycle_controller->HandleCycleWindow(
  2508. WindowCycleController::WindowCyclingDirection::kForward);
  2509. EXPECT_EQ(win0.get(), GetTargetWindow());
  2510. EXPECT_FALSE(cycle_controller->IsTabSliderFocused());
  2511. EXPECT_TRUE(cycle_controller->IsAltTabPerActiveDesk());
  2512. EXPECT_EQ(l10n_util::GetStringUTF8(IDS_ASH_ALT_TAB_FOCUS_CURRENT_DESK_MODE),
  2513. client.last_alert_message());
  2514. CompleteCyclingAndDeskSwitching(cycle_controller);
  2515. EXPECT_TRUE(wm::IsActiveWindow(win0.get()));
  2516. }
  2517. // Regression test to make sure there is no crash if a desk is added while the
  2518. // window cycle ui is visible. Regression test for https://crbug.com/1216238.
  2519. TEST_F(ModeSelectionWindowCycleControllerTest, NoCrashAfterAddingDesk) {
  2520. WindowCycleController* cycle_controller =
  2521. Shell::Get()->window_cycle_controller();
  2522. // Create enough windows so that cycling will result in the WindowCycleView
  2523. // being layouted.
  2524. const size_t num_windows = 10;
  2525. std::vector<std::unique_ptr<aura::Window>> windows(num_windows);
  2526. for (size_t i = 0; i < num_windows; ++i)
  2527. windows[i] = CreateAppWindow(gfx::Rect(200, 200));
  2528. auto* desks_controller = DesksController::Get();
  2529. ASSERT_EQ(1u, desks_controller->desks().size());
  2530. // Start window cycle, the desk mode switcher UI should not be shown.
  2531. cycle_controller->HandleCycleWindow(
  2532. WindowCycleController::WindowCyclingDirection::kForward);
  2533. ASSERT_TRUE(GetWindowCycleTabSliderButtons().empty());
  2534. ASSERT_FALSE(GetWindowCycleNoRecentItemsLabel());
  2535. // Create a new desk while cycling, which should stop cycling.
  2536. desks_controller->NewDesk(DesksCreationRemovalSource::kButton);
  2537. ASSERT_EQ(2u, desks_controller->desks().size());
  2538. EXPECT_FALSE(cycle_controller->IsCycling());
  2539. // Cycling forward should trigger a relayout, which should not crash.
  2540. cycle_controller->HandleCycleWindow(
  2541. WindowCycleController::WindowCyclingDirection::kForward);
  2542. EXPECT_FALSE(GetWindowCycleTabSliderButtons().empty());
  2543. EXPECT_TRUE(GetWindowCycleNoRecentItemsLabel());
  2544. }
  2545. // Tests that destroying all windows while cycling does not cause a crash.
  2546. TEST_F(ModeSelectionWindowCycleControllerTest, WindowDestructionWhileCycling) {
  2547. WindowCycleController* cycle_controller =
  2548. Shell::Get()->window_cycle_controller();
  2549. auto win1 = CreateAppWindow(gfx::Rect(200, 200));
  2550. auto win2 = CreateAppWindow(gfx::Rect(200, 200));
  2551. // Start window cycle, the desk mode switcher UI should not be shown.
  2552. cycle_controller->HandleCycleWindow(
  2553. WindowCycleController::WindowCyclingDirection::kForward);
  2554. ASSERT_TRUE(GetWindowCycleTabSliderButtons().empty());
  2555. ASSERT_FALSE(GetWindowCycleNoRecentItemsLabel());
  2556. win1.reset();
  2557. win2.reset();
  2558. }
  2559. // Tests that ChromeVox alerts correctly when the current desk has no window
  2560. // during alt-tab mode switching via both keyboard navigation and button click.
  2561. TEST_F(ModeSelectionWindowCycleControllerTest, ChromeVoxNoWindow) {
  2562. ui::test::EventGenerator* generator = GetEventGenerator();
  2563. WindowCycleController* cycle_controller =
  2564. Shell::Get()->window_cycle_controller();
  2565. Shell::Get()->accessibility_controller()->SetSpokenFeedbackEnabled(
  2566. true, A11Y_NOTIFICATION_NONE);
  2567. // Create two desks with all two windows in the non-active desk.
  2568. auto win1 = CreateAppWindow(gfx::Rect(0, 0, 300, 200));
  2569. auto win0 = CreateAppWindow(gfx::Rect(10, 30, 400, 200));
  2570. win1->SetTitle(u"win1");
  2571. win0->SetTitle(u"win0");
  2572. auto* desks_controller = DesksController::Get();
  2573. desks_controller->NewDesk(DesksCreationRemovalSource::kButton);
  2574. ASSERT_EQ(2u, desks_controller->desks().size());
  2575. const Desk* desk_2 = desks_controller->desks()[1].get();
  2576. ActivateDesk(desk_2);
  2577. EXPECT_EQ(desk_2, desks_controller->active_desk());
  2578. TestAccessibilityControllerClient client;
  2579. const std::string kAllDesksSelected =
  2580. l10n_util::GetStringUTF8(IDS_ASH_ALT_TAB_ALL_DESKS_MODE_SELECTED_TITLE);
  2581. const std::string kCurrentDeskSelected = l10n_util::GetStringUTF8(
  2582. IDS_ASH_ALT_TAB_CURRENT_DESK_MODE_SELECTED_TITLE);
  2583. const std::string kFocusWindowDirectionalCue =
  2584. l10n_util::GetStringUTF8(IDS_ASH_ALT_TAB_FOCUS_WINDOW_LIST_TITLE);
  2585. const std::string kNoRecentItems =
  2586. l10n_util::GetStringUTF8(IDS_ASH_OVERVIEW_NO_RECENT_ITEMS);
  2587. // Start alt-tab.
  2588. cycle_controller->HandleCycleWindow(
  2589. WindowCycleController::WindowCyclingDirection::kForward);
  2590. EXPECT_EQ(win0.get(), GetTargetWindow());
  2591. EXPECT_FALSE(cycle_controller->IsTabSliderFocused());
  2592. EXPECT_FALSE(cycle_controller->IsAltTabPerActiveDesk());
  2593. EXPECT_NE(kAllDesksSelected, client.last_alert_message());
  2594. EXPECT_EQ(l10n_util::GetStringUTF8(IDS_ASH_ALT_TAB_FOCUS_ALL_DESKS_MODE),
  2595. client.last_alert_message());
  2596. // Pressing the up arrow key should focus and alert all-desks mode.
  2597. generator->PressKey(ui::VKEY_UP, ui::EF_NONE);
  2598. EXPECT_TRUE(cycle_controller->IsTabSliderFocused());
  2599. EXPECT_FALSE(cycle_controller->IsAltTabPerActiveDesk());
  2600. EXPECT_EQ(win0.get(), GetTargetWindow());
  2601. EXPECT_EQ(kAllDesksSelected, client.last_alert_message());
  2602. // Pressing (->) announces the new mode and the new focused window but not
  2603. // the Down-arrow directional cue, which is a useless move.
  2604. generator->PressKey(ui::VKEY_RIGHT, ui::EF_NONE);
  2605. EXPECT_TRUE(cycle_controller->IsTabSliderFocused());
  2606. EXPECT_TRUE(cycle_controller->IsAltTabPerActiveDesk());
  2607. EXPECT_EQ(0u, GetWindowCycleItemViews().size());
  2608. EXPECT_EQ(nullptr, GetTargetWindow());
  2609. EXPECT_TRUE(GetWindowCycleNoRecentItemsLabel()->GetVisible());
  2610. std::string last_alert_message = client.last_alert_message();
  2611. EXPECT_TRUE(last_alert_message.find(kCurrentDeskSelected) !=
  2612. std::string::npos);
  2613. EXPECT_TRUE(last_alert_message.find(kNoRecentItems) != std::string::npos);
  2614. EXPECT_FALSE(last_alert_message.find(kFocusWindowDirectionalCue) !=
  2615. std::string::npos);
  2616. // Pressing (<-) announces the new mode, the new focused window and the
  2617. // Down-arrow directional cue.
  2618. generator->PressKey(ui::VKEY_LEFT, ui::EF_NONE);
  2619. EXPECT_TRUE(cycle_controller->IsTabSliderFocused());
  2620. EXPECT_FALSE(cycle_controller->IsAltTabPerActiveDesk());
  2621. EXPECT_EQ(2u, GetWindowCycleItemViews().size());
  2622. // Expect alt-tab to select the first window in the MRU because it is in
  2623. // another desk.
  2624. EXPECT_EQ(win0.get(), GetTargetWindow());
  2625. EXPECT_FALSE(GetWindowCycleNoRecentItemsLabel()->GetVisible());
  2626. // Similar to (->), Clicking the current-desk button notifies the new mode
  2627. // and the new focused window but not the Down-arrow directional cue.
  2628. SwitchPerDeskAltTabMode(true);
  2629. EXPECT_FALSE(cycle_controller->IsTabSliderFocused());
  2630. EXPECT_TRUE(cycle_controller->IsAltTabPerActiveDesk());
  2631. EXPECT_EQ(0u, GetWindowCycleItemViews().size());
  2632. EXPECT_EQ(nullptr, GetTargetWindow());
  2633. EXPECT_TRUE(GetWindowCycleNoRecentItemsLabel()->GetVisible());
  2634. last_alert_message = client.last_alert_message();
  2635. EXPECT_TRUE(last_alert_message.find(kCurrentDeskSelected) !=
  2636. std::string::npos);
  2637. EXPECT_TRUE(last_alert_message.find(kNoRecentItems) != std::string::npos);
  2638. EXPECT_FALSE(last_alert_message.find(kFocusWindowDirectionalCue) !=
  2639. std::string::npos);
  2640. CompleteCycling(cycle_controller);
  2641. EXPECT_FALSE(wm::IsActiveWindow(win0.get()));
  2642. EXPECT_FALSE(wm::IsActiveWindow(win1.get()));
  2643. }
  2644. // Tests that alt-tab handles window destruction during mode switch.
  2645. TEST_F(ModeSelectionWindowCycleControllerTest, WindowDestruction) {
  2646. UpdateDisplay("1200x800");
  2647. // Create four windows on the current desk.
  2648. const gfx::Rect default_rect(0, 0, 100, 200);
  2649. std::unique_ptr<Window> w0 = CreateAppWindow(default_rect);
  2650. std::unique_ptr<Window> w1 = CreateAppWindow(default_rect);
  2651. std::unique_ptr<Window> w2 = CreateAppWindow(default_rect);
  2652. std::unique_ptr<Window> w3 = CreateAppWindow(default_rect);
  2653. // Create a second desk, switch to it and create 2 windows.
  2654. auto* desks_controller = DesksController::Get();
  2655. desks_controller->NewDesk(DesksCreationRemovalSource::kButton);
  2656. ASSERT_EQ(2u, desks_controller->desks().size());
  2657. const Desk* desk_2 = desks_controller->desks()[1].get();
  2658. ActivateDesk(desk_2);
  2659. EXPECT_EQ(desk_2, desks_controller->active_desk());
  2660. std::unique_ptr<Window> w4 = CreateAppWindow(default_rect);
  2661. std::unique_ptr<Window> w5 = CreateAppWindow(default_rect);
  2662. // Start cycling. The default mode is all desks so there should be 6 windows
  2663. // in the window cycle list currently.
  2664. auto* cycle_controller = Shell::Get()->window_cycle_controller();
  2665. cycle_controller->StartCycling();
  2666. EXPECT_FALSE(cycle_controller->IsAltTabPerActiveDesk());
  2667. EXPECT_EQ(6u, GetWindows(cycle_controller).size());
  2668. // Switch modes to per-desk alt-tab. During the scaling animation, destroy
  2669. // |w5|. This shouldn't crash, the mode should be switched and we should still
  2670. // be cycling.
  2671. SwitchPerDeskAltTabMode(true, /*use_slow_duration=*/true);
  2672. EXPECT_TRUE(IsAnimatingModeSwitch());
  2673. w5.reset();
  2674. EXPECT_EQ(1u, GetWindows(cycle_controller).size());
  2675. EXPECT_TRUE(cycle_controller->IsAltTabPerActiveDesk());
  2676. EXPECT_TRUE(cycle_controller->IsCycling());
  2677. }
  2678. namespace {
  2679. constexpr char kUser1Email[] = "user1@alttab";
  2680. constexpr char kUser2Email[] = "user2@alttab";
  2681. } // namespace
  2682. class MultiUserWindowCycleControllerTest
  2683. : public NoSessionAshTestBase,
  2684. public MultiUserWindowManagerDelegate {
  2685. public:
  2686. MultiUserWindowCycleControllerTest() = default;
  2687. MultiUserWindowCycleControllerTest(
  2688. const MultiUserWindowCycleControllerTest&) = delete;
  2689. MultiUserWindowCycleControllerTest& operator=(
  2690. const MultiUserWindowCycleControllerTest&) = delete;
  2691. ~MultiUserWindowCycleControllerTest() override = default;
  2692. MultiUserWindowManager* multi_user_window_manager() {
  2693. return multi_user_window_manager_.get();
  2694. }
  2695. TestingPrefServiceSimple* user_1_prefs() { return user_1_prefs_; }
  2696. TestingPrefServiceSimple* user_2_prefs() { return user_2_prefs_; }
  2697. void SetUp() override {
  2698. NoSessionAshTestBase::SetUp();
  2699. WindowCycleList::SetDisableInitialDelayForTesting(true);
  2700. shelf_view_test_ = std::make_unique<ShelfViewTestAPI>(
  2701. GetPrimaryShelf()->GetShelfViewForTesting());
  2702. shelf_view_test_->SetAnimationDuration(base::Milliseconds(1));
  2703. generator_ = GetEventGenerator();
  2704. TestSessionControllerClient* session_controller =
  2705. GetSessionControllerClient();
  2706. session_controller->Reset();
  2707. // Inject our own PrefServices for each user which enables us to setup the
  2708. // desks restore data before the user signs in.
  2709. auto user_1_prefs = std::make_unique<TestingPrefServiceSimple>();
  2710. user_1_prefs_ = user_1_prefs.get();
  2711. RegisterUserProfilePrefs(user_1_prefs_->registry(), /*for_test=*/true);
  2712. auto user_2_prefs = std::make_unique<TestingPrefServiceSimple>();
  2713. user_2_prefs_ = user_2_prefs.get();
  2714. RegisterUserProfilePrefs(user_2_prefs_->registry(), /*for_test=*/true);
  2715. session_controller->AddUserSession(kUser1Email,
  2716. user_manager::USER_TYPE_REGULAR,
  2717. /*provide_pref_service=*/false);
  2718. session_controller->SetUserPrefService(GetUser1AccountId(),
  2719. std::move(user_1_prefs));
  2720. session_controller->AddUserSession(kUser2Email,
  2721. user_manager::USER_TYPE_REGULAR,
  2722. /*provide_pref_service=*/false);
  2723. session_controller->SetUserPrefService(GetUser2AccountId(),
  2724. std::move(user_2_prefs));
  2725. }
  2726. void TearDown() override {
  2727. multi_user_window_manager_.reset();
  2728. NoSessionAshTestBase::TearDown();
  2729. }
  2730. // MultiUserWindowManagerDelegate:
  2731. void OnWindowOwnerEntryChanged(aura::Window* window,
  2732. const AccountId& account_id,
  2733. bool was_minimized,
  2734. bool teleported) override {}
  2735. void OnTransitionUserShelfToNewAccount() override {}
  2736. void SwitchPerDeskAltTabModeFromUIAndCheckPrefs(bool per_desk_mode) {
  2737. auto* cycle_controller = Shell::Get()->window_cycle_controller();
  2738. EXPECT_TRUE(cycle_controller->IsCycling());
  2739. gfx::Point button_center =
  2740. GetWindowCycleTabSliderButtons()[per_desk_mode ? 1 : 0]
  2741. ->GetBoundsInScreen()
  2742. .CenterPoint();
  2743. generator_->MoveMouseTo(button_center);
  2744. generator_->ClickLeftButton();
  2745. // Check that alt-tab mode in UI and user prefs are updated.
  2746. EXPECT_EQ(per_desk_mode, cycle_controller->IsAltTabPerActiveDesk());
  2747. EXPECT_EQ(per_desk_mode, IsActivePrefsPerDeskMode());
  2748. EXPECT_TRUE(cycle_controller->IsCycling());
  2749. }
  2750. AccountId GetUser1AccountId() const {
  2751. return AccountId::FromUserEmail(kUser1Email);
  2752. }
  2753. AccountId GetUser2AccountId() const {
  2754. return AccountId::FromUserEmail(kUser2Email);
  2755. }
  2756. bool IsActivePrefsPerDeskMode() {
  2757. PrefService* active_user_prefs =
  2758. Shell::Get()->session_controller()->GetActivePrefService();
  2759. DCHECK(active_user_prefs);
  2760. return active_user_prefs->GetBoolean(prefs::kAltTabPerDesk);
  2761. }
  2762. void SetActivePrefsPerDeskMode(bool per_desk) {
  2763. PrefService* active_user_prefs =
  2764. Shell::Get()->session_controller()->GetActivePrefService();
  2765. DCHECK(active_user_prefs);
  2766. active_user_prefs->SetBoolean(prefs::kAltTabPerDesk, per_desk);
  2767. }
  2768. PrefService* GetUserPrefsService(bool primary) {
  2769. return Shell::Get()->session_controller()->GetUserPrefServiceForUser(
  2770. primary ? GetUser1AccountId() : GetUser2AccountId());
  2771. }
  2772. void SwitchActiveUser(const AccountId& account_id) {
  2773. GetSessionControllerClient()->SwitchActiveUser(account_id);
  2774. }
  2775. void SimulateUserLogin(const AccountId& account_id) {
  2776. SwitchActiveUser(account_id);
  2777. multi_user_window_manager_ =
  2778. MultiUserWindowManager::Create(this, account_id);
  2779. MultiUserWindowManagerImpl::Get()->SetAnimationSpeedForTest(
  2780. MultiUserWindowManagerImpl::ANIMATION_SPEED_DISABLED);
  2781. GetSessionControllerClient()->SetSessionState(
  2782. session_manager::SessionState::ACTIVE);
  2783. }
  2784. const aura::Window::Windows GetWindows(WindowCycleController* controller) {
  2785. return WindowCycleListTestApi(controller->window_cycle_list()).windows();
  2786. }
  2787. const views::View::Views& GetWindowCycleItemViews() const {
  2788. return WindowCycleListTestApi(GetCycleList()).GetWindowCycleItemViews();
  2789. }
  2790. const views::View::Views& GetWindowCycleTabSliderButtons() const {
  2791. return WindowCycleListTestApi(GetCycleList()).GetTabSliderButtons();
  2792. }
  2793. const aura::Window* GetTargetWindow() const {
  2794. return WindowCycleListTestApi(GetCycleList()).target_window();
  2795. }
  2796. void CompleteCycling(WindowCycleController* controller) {
  2797. controller->CompleteCycling();
  2798. base::RunLoop().RunUntilIdle();
  2799. }
  2800. void CompleteCyclingAndDeskSwitching(WindowCycleController* controller) {
  2801. DeskSwitchAnimationWaiter waiter;
  2802. controller->CompleteCycling();
  2803. base::RunLoop().RunUntilIdle();
  2804. auto* desks_controller = Shell::Get()->desks_controller();
  2805. if (desks_controller->AreDesksBeingModified())
  2806. waiter.Wait();
  2807. }
  2808. private:
  2809. ui::test::EventGenerator* generator_;
  2810. std::unique_ptr<ShelfViewTestAPI> shelf_view_test_;
  2811. std::unique_ptr<MultiUserWindowManager> multi_user_window_manager_;
  2812. TestingPrefServiceSimple* user_1_prefs_ = nullptr;
  2813. TestingPrefServiceSimple* user_2_prefs_ = nullptr;
  2814. };
  2815. // Tests that when the active user prefs' |prefs::kAltTabPerDesk| is updated,
  2816. // the tab slider UI and the window cycle list are refreshed.
  2817. TEST_F(MultiUserWindowCycleControllerTest, AltTabModePrefsUpdateUI) {
  2818. WindowCycleController* cycle_controller =
  2819. Shell::Get()->window_cycle_controller();
  2820. auto* desks_controller = DesksController::Get();
  2821. // Login with user_1 and create two desks and three windows where two windows
  2822. // are in the current desk to avoid failure to enter alt-tab.
  2823. SimulateUserLogin(GetUser1AccountId());
  2824. auto win0 = CreateAppWindow(gfx::Rect(0, 0, 250, 100));
  2825. multi_user_window_manager()->SetWindowOwner(win0.get(), GetUser1AccountId());
  2826. desks_controller->NewDesk(DesksCreationRemovalSource::kButton);
  2827. ASSERT_EQ(2u, desks_controller->desks().size());
  2828. // Activate desk2 and create two windows.
  2829. const Desk* desk_2 = desks_controller->desks()[1].get();
  2830. ActivateDesk(desk_2);
  2831. EXPECT_EQ(desk_2, desks_controller->active_desk());
  2832. auto win1 = CreateAppWindow(gfx::Rect(50, 50, 200, 200));
  2833. multi_user_window_manager()->SetWindowOwner(win1.get(), GetUser1AccountId());
  2834. auto win2 = CreateAppWindow(gfx::Rect(0, 0, 300, 200));
  2835. multi_user_window_manager()->SetWindowOwner(win2.get(), GetUser1AccountId());
  2836. // user_1 prefs and alt-tab mode should default to the all-desk mode.
  2837. cycle_controller->StartCycling();
  2838. EXPECT_TRUE(cycle_controller->IsCycling());
  2839. EXPECT_EQ(3u, GetWindowCycleItemViews().size());
  2840. EXPECT_FALSE(IsActivePrefsPerDeskMode());
  2841. // Setting alt-tab mode prefs to current-desk should update the alt-tab UI to
  2842. // current-desk mode.
  2843. bool per_desk = true;
  2844. SetActivePrefsPerDeskMode(per_desk);
  2845. EXPECT_TRUE(cycle_controller->IsCycling());
  2846. EXPECT_EQ(per_desk, IsActivePrefsPerDeskMode());
  2847. EXPECT_EQ(IsActivePrefsPerDeskMode(),
  2848. cycle_controller->IsAltTabPerActiveDesk());
  2849. EXPECT_EQ(2u, GetWindowCycleItemViews().size());
  2850. // Setting alt-tab mode prefs to all-desks should update the alt-tab UI to
  2851. // all-desks mode.
  2852. per_desk = false;
  2853. SetActivePrefsPerDeskMode(per_desk);
  2854. EXPECT_TRUE(cycle_controller->IsCycling());
  2855. EXPECT_EQ(per_desk, IsActivePrefsPerDeskMode());
  2856. EXPECT_EQ(IsActivePrefsPerDeskMode(),
  2857. cycle_controller->IsAltTabPerActiveDesk());
  2858. EXPECT_EQ(3u, GetWindowCycleItemViews().size());
  2859. CompleteCycling(cycle_controller);
  2860. // Switch to the secondary user_2 and setup the profile with four windows.
  2861. SwitchActiveUser(GetUser2AccountId());
  2862. const Desk* desk_1 = desks_controller->desks()[0].get();
  2863. EXPECT_TRUE(desk_1->is_active());
  2864. auto win3 = CreateAppWindow(gfx::Rect(0, 0, 250, 200));
  2865. multi_user_window_manager()->SetWindowOwner(win3.get(), GetUser2AccountId());
  2866. auto win4 = CreateAppWindow(gfx::Rect(0, 0, 250, 200));
  2867. multi_user_window_manager()->SetWindowOwner(win4.get(), GetUser2AccountId());
  2868. ActivateDesk(desk_2);
  2869. EXPECT_EQ(desk_2, desks_controller->active_desk());
  2870. auto win5 = CreateAppWindow(gfx::Rect(50, 50, 200, 200));
  2871. multi_user_window_manager()->SetWindowOwner(win5.get(), GetUser2AccountId());
  2872. auto win6 = CreateAppWindow(gfx::Rect(0, 0, 300, 200));
  2873. multi_user_window_manager()->SetWindowOwner(win6.get(), GetUser2AccountId());
  2874. // user_2 prefs and alt-tab mode should default to the all-desk mode.
  2875. cycle_controller->StartCycling();
  2876. EXPECT_TRUE(cycle_controller->IsCycling());
  2877. EXPECT_EQ(4u, GetWindowCycleItemViews().size());
  2878. EXPECT_FALSE(IsActivePrefsPerDeskMode());
  2879. // Setting alt-tab mode prefs to current-desk should update the alt-tab UI to
  2880. // current-desk mode.
  2881. per_desk = true;
  2882. SetActivePrefsPerDeskMode(per_desk);
  2883. EXPECT_TRUE(cycle_controller->IsCycling());
  2884. EXPECT_EQ(per_desk, IsActivePrefsPerDeskMode());
  2885. EXPECT_EQ(IsActivePrefsPerDeskMode(),
  2886. cycle_controller->IsAltTabPerActiveDesk());
  2887. EXPECT_EQ(2u, GetWindowCycleItemViews().size());
  2888. // Setting alt-tab mode prefs to all-desks should update the alt-tab UI to
  2889. // all-desks mode.
  2890. per_desk = false;
  2891. SetActivePrefsPerDeskMode(per_desk);
  2892. EXPECT_TRUE(cycle_controller->IsCycling());
  2893. EXPECT_EQ(per_desk, IsActivePrefsPerDeskMode());
  2894. EXPECT_EQ(IsActivePrefsPerDeskMode(),
  2895. cycle_controller->IsAltTabPerActiveDesk());
  2896. EXPECT_EQ(4u, GetWindowCycleItemViews().size());
  2897. CompleteCycling(cycle_controller);
  2898. }
  2899. // Tests that switching between users restores each user's alt-tab mode
  2900. // correctly. In addition, pressing a tab slider button to switch the mode,
  2901. // `SwitchPerDeskAltTabModeFromUIAndCheckPrefs()` checks that alt-tab
  2902. // successfully switches the mode and updates the user prefs.
  2903. TEST_F(MultiUserWindowCycleControllerTest,
  2904. AltTabModeUserSwitchAndUIUpdatesPref) {
  2905. WindowCycleController* cycle_controller =
  2906. Shell::Get()->window_cycle_controller();
  2907. // Setup user_1 with two windows out of three in the current desk and
  2908. // set the mode to non-default current-desk for test preparation.
  2909. SimulateUserLogin(GetUser1AccountId());
  2910. auto win0 = CreateAppWindow(gfx::Rect(0, 0, 250, 100));
  2911. multi_user_window_manager()->SetWindowOwner(win0.get(), GetUser1AccountId());
  2912. auto* desks_controller = DesksController::Get();
  2913. desks_controller->NewDesk(DesksCreationRemovalSource::kButton);
  2914. ASSERT_EQ(2u, desks_controller->desks().size());
  2915. const Desk* desk_2 = desks_controller->desks()[1].get();
  2916. ActivateDesk(desk_2);
  2917. EXPECT_EQ(desk_2, desks_controller->active_desk());
  2918. auto win1 = CreateAppWindow(gfx::Rect(50, 50, 200, 200));
  2919. multi_user_window_manager()->SetWindowOwner(win1.get(), GetUser1AccountId());
  2920. auto win2 = CreateAppWindow(gfx::Rect(0, 0, 300, 200));
  2921. multi_user_window_manager()->SetWindowOwner(win2.get(), GetUser1AccountId());
  2922. // In preparation for multi-user alt-tab mode switching, start alt-tab with
  2923. // user_1 prefs set to current-desk mode.
  2924. bool per_desk = true;
  2925. SetActivePrefsPerDeskMode(per_desk);
  2926. cycle_controller->StartCycling();
  2927. EXPECT_TRUE(cycle_controller->IsCycling());
  2928. EXPECT_EQ(per_desk, IsActivePrefsPerDeskMode());
  2929. EXPECT_EQ(IsActivePrefsPerDeskMode(),
  2930. cycle_controller->IsAltTabPerActiveDesk());
  2931. EXPECT_EQ(2u, GetWindowCycleItemViews().size());
  2932. CompleteCycling(cycle_controller);
  2933. // Switch to user_2 and open up two windows out of four in the current desk.
  2934. SwitchActiveUser(GetUser2AccountId());
  2935. const Desk* desk_1 = desks_controller->desks()[0].get();
  2936. EXPECT_TRUE(desk_1->is_active());
  2937. auto win3 = CreateAppWindow(gfx::Rect(0, 0, 250, 200));
  2938. multi_user_window_manager()->SetWindowOwner(win3.get(), GetUser2AccountId());
  2939. auto win4 = CreateAppWindow(gfx::Rect(0, 0, 250, 200));
  2940. multi_user_window_manager()->SetWindowOwner(win4.get(), GetUser2AccountId());
  2941. ActivateDesk(desk_2);
  2942. EXPECT_EQ(desk_2, desks_controller->active_desk());
  2943. auto win5 = CreateAppWindow(gfx::Rect(0, 0, 250, 200));
  2944. multi_user_window_manager()->SetWindowOwner(win5.get(), GetUser2AccountId());
  2945. auto win6 = CreateAppWindow(gfx::Rect(0, 0, 250, 200));
  2946. multi_user_window_manager()->SetWindowOwner(win6.get(), GetUser2AccountId());
  2947. // In preparation for multi-user alt-tab mode switching, start alt-tab with
  2948. // user_2 prefs set to current-desk mode.
  2949. SetActivePrefsPerDeskMode(per_desk);
  2950. cycle_controller->StartCycling();
  2951. EXPECT_TRUE(cycle_controller->IsCycling());
  2952. EXPECT_EQ(per_desk, IsActivePrefsPerDeskMode());
  2953. EXPECT_EQ(IsActivePrefsPerDeskMode(),
  2954. cycle_controller->IsAltTabPerActiveDesk());
  2955. EXPECT_EQ(2u, GetWindowCycleItemViews().size());
  2956. // Test that the primary user_1's mode is loaded correctly after switch
  2957. // from secondary user_2, who just changes the mode to the opposite.
  2958. // Currently, both users choose the current-desk mode, so we try change
  2959. // user_2 to all-desks mode from the tab slider UI to see if user_1's mode
  2960. // remains correctly unaffected.
  2961. SwitchPerDeskAltTabModeFromUIAndCheckPrefs(false);
  2962. EXPECT_EQ(4u, GetWindowCycleItemViews().size());
  2963. CompleteCycling(cycle_controller);
  2964. // Switch back to user_1. Make sure that user_1 prefs remains unaffected
  2965. // and the alt-tab enter with the correct current-desk mode.
  2966. SwitchActiveUser(GetUser1AccountId());
  2967. cycle_controller->StartCycling();
  2968. EXPECT_TRUE(cycle_controller->IsCycling());
  2969. EXPECT_TRUE(IsActivePrefsPerDeskMode());
  2970. EXPECT_EQ(IsActivePrefsPerDeskMode(),
  2971. cycle_controller->IsAltTabPerActiveDesk());
  2972. EXPECT_EQ(2u, GetWindowCycleItemViews().size());
  2973. CompleteCycling(cycle_controller);
  2974. // In preparation for the next test, change user_2 back the current-desk mode
  2975. // to make sure both users start at the same mode selection.
  2976. SwitchActiveUser(GetUser2AccountId());
  2977. EXPECT_EQ(desk_2, desks_controller->active_desk());
  2978. cycle_controller->StartCycling();
  2979. EXPECT_TRUE(cycle_controller->IsCycling());
  2980. EXPECT_FALSE(cycle_controller->IsAltTabPerActiveDesk());
  2981. SwitchPerDeskAltTabModeFromUIAndCheckPrefs(true);
  2982. EXPECT_EQ(2u, GetWindowCycleItemViews().size());
  2983. CompleteCycling(cycle_controller);
  2984. // Test that the secondary user_2's mode is loaded correctly after switching
  2985. // from primary user_1, who just changes the mode to the opposite.
  2986. // Currently, both users choose the current-desk mode, so we try change
  2987. // user_1 to all-desks mode to see if user_2's mode will change.
  2988. SwitchActiveUser(GetUser1AccountId());
  2989. EXPECT_EQ(desk_2, desks_controller->active_desk());
  2990. cycle_controller->StartCycling();
  2991. EXPECT_TRUE(cycle_controller->IsCycling());
  2992. EXPECT_TRUE(cycle_controller->IsAltTabPerActiveDesk());
  2993. SwitchPerDeskAltTabModeFromUIAndCheckPrefs(false);
  2994. EXPECT_EQ(3u, GetWindowCycleItemViews().size());
  2995. CompleteCyclingAndDeskSwitching(cycle_controller);
  2996. // Switch back to user_2 and make sure that the mode is restored
  2997. // to the current-desk mode correctly.
  2998. SwitchActiveUser(GetUser2AccountId());
  2999. EXPECT_EQ(desk_2, desks_controller->active_desk());
  3000. cycle_controller->StartCycling();
  3001. EXPECT_TRUE(cycle_controller->IsCycling());
  3002. EXPECT_TRUE(cycle_controller->IsAltTabPerActiveDesk());
  3003. EXPECT_EQ(2u, GetWindowCycleItemViews().size());
  3004. CompleteCycling(cycle_controller);
  3005. }
  3006. } // namespace ash