KeyboardTests.cs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753
  1. using UICatalog;
  2. using Xunit.Abstractions;
  3. namespace Terminal.Gui.ApplicationTests;
  4. /// <summary>
  5. /// Application tests for keyboard support.
  6. /// </summary>
  7. public class KeyboardTests
  8. {
  9. private readonly ITestOutputHelper _output;
  10. public KeyboardTests (ITestOutputHelper output)
  11. {
  12. _output = output;
  13. #if DEBUG_IDISPOSABLE
  14. Responder.Instances.Clear ();
  15. RunState.Instances.Clear ();
  16. #endif
  17. }
  18. [Fact]
  19. [AutoInitShutdown]
  20. public void QuitKey_Getter_Setter ()
  21. {
  22. Toplevel top = new ();
  23. var isQuiting = false;
  24. top.Closing += (s, e) =>
  25. {
  26. isQuiting = true;
  27. e.Cancel = true;
  28. };
  29. Application.Begin (top);
  30. top.Running = true;
  31. Key prevKey = Application.QuitKey;
  32. Application.OnKeyDown (Application.QuitKey);
  33. Assert.True (isQuiting);
  34. isQuiting = false;
  35. Application.OnKeyDown (Application.QuitKey);
  36. Assert.True (isQuiting);
  37. isQuiting = false;
  38. Application.QuitKey = Key.C.WithCtrl;
  39. Application.OnKeyDown (prevKey); // Should not quit
  40. Assert.False (isQuiting);
  41. Application.OnKeyDown (Key.Q.WithCtrl);// Should not quit
  42. Assert.False (isQuiting);
  43. Application.OnKeyDown (Application.QuitKey);
  44. Assert.True (isQuiting);
  45. // Reset the QuitKey to avoid throws errors on another tests
  46. Application.QuitKey = prevKey;
  47. top.Dispose ();
  48. }
  49. [Fact]
  50. public void QuitKey_Default_Is_Esc ()
  51. {
  52. Application.ResetState (true);
  53. // Before Init
  54. Assert.Equal (Key.Esc, Application.QuitKey);
  55. Application.Init (new FakeDriver ());
  56. // After Init
  57. Assert.Equal (Key.Esc, Application.QuitKey);
  58. Application.Shutdown ();
  59. }
  60. private object _timeoutLock;
  61. [Fact]
  62. public void QuitKey_Quits ()
  63. {
  64. Assert.Null (_timeoutLock);
  65. _timeoutLock = new object ();
  66. uint abortTime = 500;
  67. bool initialized = false;
  68. int iteration = 0;
  69. bool shutdown = false;
  70. object timeout = null;
  71. Application.InitializedChanged += OnApplicationOnInitializedChanged;
  72. Application.Init (new FakeDriver ());
  73. Assert.True (initialized);
  74. Assert.False (shutdown);
  75. _output.WriteLine ("Application.Run<Toplevel> ().Dispose ()..");
  76. Application.Run<Toplevel> ().Dispose ();
  77. _output.WriteLine ("Back from Application.Run<Toplevel> ().Dispose ()");
  78. Assert.True (initialized);
  79. Assert.False (shutdown);
  80. Assert.Equal (1, iteration);
  81. Application.Shutdown ();
  82. Application.InitializedChanged -= OnApplicationOnInitializedChanged;
  83. lock (_timeoutLock)
  84. {
  85. if (timeout is { })
  86. {
  87. Application.RemoveTimeout (timeout);
  88. timeout = null;
  89. }
  90. }
  91. Assert.True (initialized);
  92. Assert.True (shutdown);
  93. #if DEBUG_IDISPOSABLE
  94. Assert.Empty (Responder.Instances);
  95. #endif
  96. lock (_timeoutLock)
  97. {
  98. _timeoutLock = null;
  99. }
  100. return;
  101. void OnApplicationOnInitializedChanged (object s, EventArgs<bool> a)
  102. {
  103. _output.WriteLine ("OnApplicationOnInitializedChanged: {0}", a.CurrentValue);
  104. if (a.CurrentValue)
  105. {
  106. Application.Iteration += OnApplicationOnIteration;
  107. initialized = true;
  108. lock (_timeoutLock)
  109. {
  110. timeout = Application.AddTimeout (TimeSpan.FromMilliseconds (abortTime), ForceCloseCallback);
  111. }
  112. }
  113. else
  114. {
  115. Application.Iteration -= OnApplicationOnIteration;
  116. shutdown = true;
  117. }
  118. }
  119. bool ForceCloseCallback ()
  120. {
  121. lock (_timeoutLock)
  122. {
  123. _output.WriteLine ($"ForceCloseCallback. iteration: {iteration}");
  124. if (timeout is { })
  125. {
  126. timeout = null;
  127. }
  128. }
  129. Application.ResetState (true);
  130. Assert.Fail ($"Failed to Quit with {Application.QuitKey} after {abortTime}ms. Force quit.");
  131. return false;
  132. }
  133. void OnApplicationOnIteration (object s, IterationEventArgs a)
  134. {
  135. _output.WriteLine ("Iteration: {0}", iteration);
  136. iteration++;
  137. Assert.True (iteration < 2, "Too many iterations, something is wrong.");
  138. if (Application.IsInitialized)
  139. {
  140. _output.WriteLine (" Pressing QuitKey");
  141. Application.OnKeyDown (Application.QuitKey);
  142. }
  143. }
  144. }
  145. [Fact]
  146. public void NextTabKey_Moves_Focus_To_Next_TabStop ()
  147. {
  148. // Arrange
  149. Application.Navigation = new ApplicationNavigation ();
  150. var top = new Toplevel ();
  151. var view1 = new View () { Id = "view1", CanFocus = true };
  152. var view2 = new View () { Id = "view2", CanFocus = true };
  153. top.Add (view1, view2);
  154. Application.Top = top;
  155. Application.Current = top;
  156. view1.SetFocus ();
  157. // Act
  158. Application.OnKeyDown (Application.NextTabKey);
  159. // Assert
  160. Assert.True (view2.HasFocus);
  161. top.Dispose ();
  162. Application.Navigation = null;
  163. }
  164. [Fact]
  165. public void PrevTabKey_Moves_Focus_To_Prev_TabStop ()
  166. {
  167. // Arrange
  168. Application.Navigation = new ApplicationNavigation ();
  169. var top = new Toplevel ();
  170. var view1 = new View () { Id = "view1", CanFocus = true };
  171. var view2 = new View () { Id = "view2", CanFocus = true };
  172. top.Add (view1, view2);
  173. Application.Top = top;
  174. Application.Current = top;
  175. view1.SetFocus ();
  176. // Act
  177. Application.OnKeyDown (Application.NextTabKey);
  178. // Assert
  179. Assert.True (view2.HasFocus);
  180. top.Dispose ();
  181. Application.Navigation = null;
  182. }
  183. [Fact]
  184. public void NextTabGroupKey_Moves_Focus_To_TabStop_In_Next_TabGroup ()
  185. {
  186. // Arrange
  187. Application.Navigation = new ApplicationNavigation ();
  188. var top = new Toplevel ();
  189. var view1 = new View ()
  190. {
  191. Id = "view1",
  192. CanFocus = true,
  193. TabStop = TabBehavior.TabGroup
  194. };
  195. var subView1 = new View ()
  196. {
  197. Id = "subView1",
  198. CanFocus = true,
  199. TabStop = TabBehavior.TabStop
  200. };
  201. view1.Add (subView1);
  202. var view2 = new View ()
  203. {
  204. Id = "view2",
  205. CanFocus = true,
  206. TabStop = TabBehavior.TabGroup
  207. };
  208. var subView2 = new View ()
  209. {
  210. Id = "subView2",
  211. CanFocus = true,
  212. TabStop = TabBehavior.TabStop
  213. };
  214. view2.Add (subView2);
  215. top.Add (view1, view2);
  216. Application.Top = top;
  217. Application.Current = top;
  218. view1.SetFocus ();
  219. Assert.True (view1.HasFocus);
  220. Assert.True (subView1.HasFocus);
  221. // Act
  222. Application.OnKeyDown (Application.NextTabGroupKey);
  223. // Assert
  224. Assert.True (view2.HasFocus);
  225. Assert.True (subView2.HasFocus);
  226. top.Dispose ();
  227. Application.Navigation = null;
  228. }
  229. [Fact]
  230. public void PrevTabGroupKey_Moves_Focus_To_TabStop_In_Prev_TabGroup ()
  231. {
  232. // Arrange
  233. Application.Navigation = new ApplicationNavigation ();
  234. var top = new Toplevel ();
  235. var view1 = new View ()
  236. {
  237. Id = "view1",
  238. CanFocus = true,
  239. TabStop = TabBehavior.TabGroup
  240. };
  241. var subView1 = new View ()
  242. {
  243. Id = "subView1",
  244. CanFocus = true,
  245. TabStop = TabBehavior.TabStop
  246. };
  247. view1.Add (subView1);
  248. var view2 = new View ()
  249. {
  250. Id = "view2",
  251. CanFocus = true,
  252. TabStop = TabBehavior.TabGroup
  253. };
  254. var subView2 = new View ()
  255. {
  256. Id = "subView2",
  257. CanFocus = true,
  258. TabStop = TabBehavior.TabStop
  259. };
  260. view2.Add (subView2);
  261. top.Add (view1, view2);
  262. Application.Top = top;
  263. Application.Current = top;
  264. view1.SetFocus ();
  265. Assert.True (view1.HasFocus);
  266. Assert.True (subView1.HasFocus);
  267. // Act
  268. Application.OnKeyDown (Application.PrevTabGroupKey);
  269. // Assert
  270. Assert.True (view2.HasFocus);
  271. Assert.True (subView2.HasFocus);
  272. top.Dispose ();
  273. Application.Navigation = null;
  274. }
  275. [Fact]
  276. public void NextTabGroupKey_PrevTabGroupKey_Tests ()
  277. {
  278. Application.Init (new FakeDriver ());
  279. Toplevel top = new (); // TabGroup
  280. var w1 = new Window (); // TabGroup
  281. var v1 = new TextField (); // TabStop
  282. var v2 = new TextView (); // TabStop
  283. w1.Add (v1, v2);
  284. var w2 = new Window (); // TabGroup
  285. var v3 = new CheckBox (); // TabStop
  286. var v4 = new Button (); // TabStop
  287. w2.Add (v3, v4);
  288. top.Add (w1, w2);
  289. Application.Iteration += (s, a) =>
  290. {
  291. Assert.True (v1.HasFocus);
  292. // Across TabGroups
  293. Application.OnKeyDown (Key.F6);
  294. Assert.True (v3.HasFocus);
  295. Application.OnKeyDown (Key.F6);
  296. Assert.True (v1.HasFocus);
  297. Application.OnKeyDown (Key.F6.WithShift);
  298. Assert.True (v3.HasFocus);
  299. Application.OnKeyDown (Key.F6.WithShift);
  300. Assert.True (v1.HasFocus);
  301. // Restore?
  302. Application.OnKeyDown (Key.Tab);
  303. Assert.True (v2.HasFocus);
  304. Application.OnKeyDown (Key.F6);
  305. Assert.True (v3.HasFocus);
  306. Application.OnKeyDown (Key.F6);
  307. Assert.True (v2.HasFocus);
  308. Application.RequestStop ();
  309. };
  310. Application.Run (top);
  311. // Replacing the defaults keys to avoid errors on others unit tests that are using it.
  312. Application.NextTabGroupKey = Key.PageDown.WithCtrl;
  313. Application.PrevTabGroupKey = Key.PageUp.WithCtrl;
  314. Application.QuitKey = Key.Q.WithCtrl;
  315. Assert.Equal (KeyCode.PageDown | KeyCode.CtrlMask, Application.NextTabGroupKey.KeyCode);
  316. Assert.Equal (KeyCode.PageUp | KeyCode.CtrlMask, Application.PrevTabGroupKey.KeyCode);
  317. Assert.Equal (KeyCode.Q | KeyCode.CtrlMask, Application.QuitKey.KeyCode);
  318. top.Dispose ();
  319. // Shutdown must be called to safely clean up Application if Init has been called
  320. Application.Shutdown ();
  321. }
  322. [Fact(Skip = "No longer valid test.")]
  323. [AutoInitShutdown]
  324. public void EnsuresTopOnFront_CanFocus_False_By_Keyboard ()
  325. {
  326. Toplevel top = new ();
  327. var win = new Window
  328. {
  329. Title = "win",
  330. X = 0,
  331. Y = 0,
  332. Width = 20,
  333. Height = 10
  334. };
  335. var tf = new TextField { Width = 10 };
  336. win.Add (tf);
  337. var win2 = new Window
  338. {
  339. Title = "win2",
  340. X = 22,
  341. Y = 0,
  342. Width = 20,
  343. Height = 10
  344. };
  345. var tf2 = new TextField { Width = 10 };
  346. win2.Add (tf2);
  347. top.Add (win, win2);
  348. Application.Begin (top);
  349. Assert.True (win.CanFocus);
  350. Assert.True (win.HasFocus);
  351. Assert.True (win2.CanFocus);
  352. Assert.False (win2.HasFocus);
  353. Assert.Equal ("win", ((Window)top.Subviews [^1]).Title);
  354. win.CanFocus = false;
  355. Assert.False (win.CanFocus);
  356. Assert.False (win.HasFocus);
  357. Assert.True (win2.CanFocus);
  358. Assert.True (win2.HasFocus);
  359. Assert.Equal ("win2", ((Window)top.Subviews [^1]).Title);
  360. Application.OnKeyDown (Key.F6);
  361. Assert.True (win2.CanFocus);
  362. Assert.False (win.HasFocus);
  363. Assert.True (win2.CanFocus);
  364. Assert.True (win2.HasFocus);
  365. Assert.Equal ("win2", ((Window)top.Subviews [^1]).Title);
  366. Application.OnKeyDown (Key.F6);
  367. Assert.False (win.CanFocus);
  368. Assert.False (win.HasFocus);
  369. Assert.True (win2.CanFocus);
  370. Assert.True (win2.HasFocus);
  371. Assert.Equal ("win2", ((Window)top.Subviews [^1]).Title);
  372. top.Dispose ();
  373. }
  374. [Fact (Skip = "No longer valid test.")]
  375. [AutoInitShutdown]
  376. public void EnsuresTopOnFront_CanFocus_True_By_Keyboard ()
  377. {
  378. Toplevel top = new ();
  379. var win = new Window
  380. {
  381. Title = "win",
  382. X = 0,
  383. Y = 0,
  384. Width = 20,
  385. Height = 10
  386. };
  387. var tf = new TextField { Width = 10 };
  388. win.Add (tf);
  389. var win2 = new Window
  390. {
  391. Title = "win2",
  392. X = 22,
  393. Y = 0,
  394. Width = 20,
  395. Height = 10
  396. };
  397. var tf2 = new TextField { Width = 10 };
  398. win2.Add (tf2);
  399. top.Add (win, win2);
  400. Application.Begin (top);
  401. Assert.True (win.CanFocus);
  402. Assert.True (win.HasFocus);
  403. Assert.True (win2.CanFocus);
  404. Assert.False (win2.HasFocus);
  405. Assert.Equal ("win", ((Window)top.Subviews [^1]).Title);
  406. Application.OnKeyDown (Key.F6);
  407. Assert.True (win.CanFocus);
  408. Assert.False (win.HasFocus);
  409. Assert.True (win2.CanFocus);
  410. Assert.True (win2.HasFocus);
  411. Assert.Equal ("win2", ((Window)top.Subviews [^1]).Title);
  412. Application.OnKeyDown (Key.F6);
  413. Assert.True (win.CanFocus);
  414. Assert.True (win.HasFocus);
  415. Assert.True (win2.CanFocus);
  416. Assert.False (win2.HasFocus);
  417. Assert.Equal ("win", ((Window)top.Subviews [^1]).Title);
  418. top.Dispose ();
  419. }
  420. [Fact]
  421. public void KeyUp_Event ()
  422. {
  423. Application.Init (new FakeDriver ());
  424. // Setup some fake keypresses (This)
  425. var input = "Tests";
  426. Key originalQuitKey = Application.QuitKey;
  427. Application.QuitKey = Key.Q.WithCtrl;
  428. // Put a control-q in at the end
  429. FakeConsole.MockKeyPresses.Push (new ConsoleKeyInfo ('Q', ConsoleKey.Q, false, false, true));
  430. foreach (char c in input.Reverse ())
  431. {
  432. if (char.IsLetter (c))
  433. {
  434. FakeConsole.MockKeyPresses.Push (
  435. new ConsoleKeyInfo (
  436. c,
  437. (ConsoleKey)char.ToUpper (c),
  438. char.IsUpper (c),
  439. false,
  440. false
  441. )
  442. );
  443. }
  444. else
  445. {
  446. FakeConsole.MockKeyPresses.Push (
  447. new ConsoleKeyInfo (
  448. c,
  449. (ConsoleKey)c,
  450. false,
  451. false,
  452. false
  453. )
  454. );
  455. }
  456. }
  457. int stackSize = FakeConsole.MockKeyPresses.Count;
  458. var iterations = 0;
  459. Application.Iteration += (s, a) =>
  460. {
  461. iterations++;
  462. // Stop if we run out of control...
  463. if (iterations > 10)
  464. {
  465. Application.RequestStop ();
  466. }
  467. };
  468. var keyUps = 0;
  469. var output = string.Empty;
  470. var top = new Toplevel ();
  471. top.KeyUp += (sender, args) =>
  472. {
  473. if (args.KeyCode != (KeyCode.CtrlMask | KeyCode.Q))
  474. {
  475. output += args.AsRune;
  476. }
  477. keyUps++;
  478. };
  479. Application.Run (top);
  480. Application.QuitKey = originalQuitKey;
  481. // Input string should match output
  482. Assert.Equal (input, output);
  483. // # of key up events should match stack size
  484. //Assert.Equal (stackSize, keyUps);
  485. // We can't use numbers variables on the left side of an Assert.Equal/NotEqual,
  486. // it must be literal (Linux only).
  487. Assert.Equal (6, keyUps);
  488. // # of key up events should match # of iterations
  489. Assert.Equal (stackSize, iterations);
  490. top.Dispose ();
  491. Application.Shutdown ();
  492. Assert.Null (Application.Current);
  493. Assert.Null (Application.Top);
  494. Assert.Null (Application.MainLoop);
  495. Assert.Null (Application.Driver);
  496. }
  497. [Fact]
  498. [AutoInitShutdown]
  499. public void KeyBinding_OnKeyDown ()
  500. {
  501. var view = new ScopedKeyBindingView ();
  502. var invoked = false;
  503. view.InvokingKeyBindings += (s, e) => invoked = true;
  504. var top = new Toplevel ();
  505. top.Add (view);
  506. Application.Begin (top);
  507. Application.OnKeyDown (Key.A);
  508. Assert.False (invoked);
  509. Assert.True (view.ApplicationCommand);
  510. invoked = false;
  511. view.ApplicationCommand = false;
  512. Application.KeyBindings.Remove (KeyCode.A);
  513. Application.OnKeyDown (Key.A); // old
  514. Assert.False (invoked);
  515. Assert.False (view.ApplicationCommand);
  516. Application.KeyBindings.Add (Key.A.WithCtrl, view, Command.Save);
  517. Application.OnKeyDown (Key.A); // old
  518. Assert.False (invoked);
  519. Assert.False (view.ApplicationCommand);
  520. Application.OnKeyDown (Key.A.WithCtrl); // new
  521. Assert.False (invoked);
  522. Assert.True (view.ApplicationCommand);
  523. invoked = false;
  524. Application.OnKeyDown (Key.H);
  525. Assert.True (invoked);
  526. invoked = false;
  527. Assert.False (view.HasFocus);
  528. Application.OnKeyDown (Key.F);
  529. Assert.False (invoked);
  530. Assert.True (view.ApplicationCommand);
  531. Assert.True (view.HotKeyCommand);
  532. Assert.False (view.FocusedCommand);
  533. top.Dispose ();
  534. }
  535. [Fact]
  536. [AutoInitShutdown]
  537. public void KeyBinding_OnKeyDown_Negative ()
  538. {
  539. var view = new ScopedKeyBindingView ();
  540. var invoked = false;
  541. view.InvokingKeyBindings += (s, e) => invoked = true;
  542. var top = new Toplevel ();
  543. top.Add (view);
  544. Application.Begin (top);
  545. Application.OnKeyDown (Key.A.WithCtrl);
  546. Assert.False (invoked);
  547. Assert.False (view.ApplicationCommand);
  548. Assert.False (view.HotKeyCommand);
  549. Assert.False (view.FocusedCommand);
  550. invoked = false;
  551. Assert.False (view.HasFocus);
  552. Application.OnKeyDown (Key.Z);
  553. Assert.False (invoked);
  554. Assert.False (view.ApplicationCommand);
  555. Assert.False (view.HotKeyCommand);
  556. Assert.False (view.FocusedCommand);
  557. top.Dispose ();
  558. }
  559. [Fact]
  560. [AutoInitShutdown]
  561. public void KeyBinding_Application_KeyBindings_Add_Adds ()
  562. {
  563. Application.KeyBindings.Add (Key.A, KeyBindingScope.Application, Command.Accept);
  564. Application.KeyBindings.Add (Key.B, KeyBindingScope.Application, Command.Accept);
  565. Assert.True (Application.KeyBindings.TryGet (Key.A, out var binding));
  566. Assert.Null (binding.BoundView);
  567. Assert.True (Application.KeyBindings.TryGet (Key.B, out binding));
  568. Assert.Null (binding.BoundView);
  569. }
  570. [Fact]
  571. [AutoInitShutdown]
  572. public void KeyBinding_View_KeyBindings_Add_Adds ()
  573. {
  574. View view1 = new ();
  575. Application.KeyBindings.Add (Key.A, view1, Command.Accept);
  576. View view2 = new ();
  577. Application.KeyBindings.Add (Key.B, view2, Command.Accept);
  578. Assert.True (Application.KeyBindings.TryGet (Key.A, out var binding));
  579. Assert.Equal (view1, binding.BoundView);
  580. Assert.True (Application.KeyBindings.TryGet (Key.B, out binding));
  581. Assert.Equal (view2, binding.BoundView);
  582. }
  583. [Fact]
  584. [AutoInitShutdown]
  585. public void KeyBinding_Application_RemoveKeyBinding_Removes ()
  586. {
  587. Application.KeyBindings.Add (Key.A, KeyBindingScope.Application, Command.Accept);
  588. Assert.True (Application.KeyBindings.TryGet (Key.A, out _));
  589. Application.KeyBindings.Remove (Key.A);
  590. Assert.False (Application.KeyBindings.TryGet (Key.A, out _));
  591. }
  592. [Fact]
  593. [AutoInitShutdown]
  594. public void KeyBinding_View_KeyBindings_RemoveKeyBinding_Removes ()
  595. {
  596. View view1 = new ();
  597. Application.KeyBindings.Add (Key.A, view1, Command.Accept);
  598. View view2 = new ();
  599. Application.KeyBindings.Add (Key.B, view1, Command.Accept);
  600. Application.KeyBindings.Remove (Key.A, view1);
  601. Assert.False (Application.KeyBindings.TryGet (Key.A, out _));
  602. }
  603. // Test View for testing Application key Bindings
  604. public class ScopedKeyBindingView : View
  605. {
  606. public ScopedKeyBindingView ()
  607. {
  608. AddCommand (Command.Save, () => ApplicationCommand = true);
  609. AddCommand (Command.HotKey, () => HotKeyCommand = true);
  610. AddCommand (Command.Left, () => FocusedCommand = true);
  611. Application.KeyBindings.Add (Key.A, this, Command.Save);
  612. HotKey = KeyCode.H;
  613. KeyBindings.Add (Key.F, Command.Left);
  614. }
  615. public bool ApplicationCommand { get; set; }
  616. public bool FocusedCommand { get; set; }
  617. public bool HotKeyCommand { get; set; }
  618. }
  619. }