@@ -19,26 +19,42 @@ import QtQuick.Layouts 1.1
1919import QtTest 1.0
2020import Unity.Test 0.1
2121import Ubuntu.Components 1.3
22+import Ubuntu.Components.ListItems 1.3 as ListItem
2223import Unity.Application 0.1
23−import Unity.Indicators 0.1 as Indicators
24+import QMenuModel 0.1
2425import Ubuntu.Telephony 0.1 as Telephony
26+import AccountsService 0.1
27+import Unity.InputInfo 0.1
2528import "../../../qml/Panel"
2629import "../../../qml/Components/PanelState"
30+import "../Stage"
31+import ".."
2732
28−IndicatorTest {
33+PanelTest {
2934 id: root
30− width: units.gu(100)
35+ width: units.gu(120)
3136 height: units.gu(71)
3237 color: "black"
3338
34− Component.onCompleted: theme.name = "Ubuntu.Components.Themes.SuruDark"
39+ Binding {
40+ target: QuickUtils
41+ property: "keyboardAttached"
42+ value: keyboardAttached.checked
43+ }
3544
36− SurfaceManager {}
45+ SurfaceManager { id: sMgr }
46+ ApplicationMenuDataLoader {
47+ id: appMenuData
48+ surfaceManager: sMgr
49+ }
3750
38− Binding {
39− target: mouseEmulation
40− property: "checked"
41− value: !windowControlsCB.checked
51+ Component.onCompleted: {
52+ theme.name = "Ubuntu.Components.Themes.SuruDark"
53+ }
54+
55+ Rectangle {
56+ anchors.fill: parent
57+ color: "darkgrey"
4258 }
4359
4460 RowLayout {
@@ -61,12 +77,23 @@ IndicatorTest {
6177 Panel {
6278 id: panel
6379 anchors.fill: parent
64− indicators {
65− width: parent.width > units.gu(60) ? units.gu(40) : parent.width
66− indicatorsModel: root.indicatorsModel
80+ mode: modeSelector.model[modeSelector.selectedIndex]
81+
82+ indicatorMenuWidth: parent.width > units.gu(60) ? units.gu(40) : parent.width
83+ applicationMenuWidth: parent.width > units.gu(60) ? units.gu(40) : parent.width
84+
85+ applicationMenus {
86+ model: UnityMenuModel {
87+ modelData: appMenuData.generateTestData(5, 4, 2, 3, "menu")
88+ }
89+
90+ hides: [ panel.indicators ]
6791 }
6892
69− property real panelAndSeparatorHeight: panel.indicators.minimizedPanelHeight
93+ indicators {
94+ model: root.indicatorsModel
95+ hides: [ panel.applicationMenus ]
96+ }
7097 }
7198 }
7299 }
@@ -75,6 +102,18 @@ IndicatorTest {
75102 Layout.alignment: Qt.AlignTop
76103 Layout.fillWidth: false
77104
105+ ListItem.ItemSelector {
106+ id: modeSelector
107+ anchors { left: parent.left; right: parent.right }
108+ activeFocusOnPress: false
109+ text: "Mode"
110+ model: ["staged", "windowed" ]
111+ onSelectedIndexChanged: {
112+ panel.mode = model[selectedIndex];
113+ keyboardAttached.checked = panel.mode == "windowed"
114+ }
115+ }
116+
78117 Button {
79118 Layout.fillWidth: true
80119 text: panel.indicators.shown ? "Hide" : "Show"
@@ -109,25 +148,22 @@ IndicatorTest {
109148 Layout.fillWidth: true
110149 CheckBox {
111150 id: windowControlsCB
112− onClicked: PanelState.buttonsVisible = checked
151+ onClicked: PanelState.decorationsVisible = checked
113152 }
114153 Label {
115− text: "Show window controls"
154+ text: "Show window decorations"
155+ color: "white"
116156 }
117157 }
118158
119159 RowLayout {
120160 Layout.fillWidth: true
121161 CheckBox {
122− onClicked: {
123− if (checked)
124− PanelState.title = "Fake window title"
125− else
126− PanelState.title = ""
127− }
162+ onClicked: PanelState.title = checked ? "Fake window title" : ""
128163 }
129164 Label {
130165 text: "Show fake window title"
166+ color: "white"
131167 }
132168 }
133169
@@ -137,6 +173,12 @@ IndicatorTest {
137173 color: "black"
138174 }
139175
176+ Rectangle {
177+ Layout.preferredHeight: units.dp(1);
178+ Layout.fillWidth: true;
179+ color: "black"
180+ }
181+
140182 Repeater {
141183 model: root.originalModelData
142184 RowLayout {
@@ -147,6 +189,7 @@ IndicatorTest {
147189 Label {
148190 Layout.fillWidth: true
149191 text: modelData["identifier"]
192+ color: "white"
150193 }
151194
152195 CheckBox {
@@ -155,6 +198,7 @@ IndicatorTest {
155198 }
156199 Label {
157200 text: "visible"
201+ color: "white"
158202 }
159203 }
160204 }
@@ -165,7 +209,22 @@ IndicatorTest {
165209 color: "black"
166210 }
167211
168− MouseTouchEmulationCheckbox { id: mouseEmulation }
212+ MouseTouchEmulationCheckbox {
213+ id: mouseEmulation
214+ color: "white"
215+ checked: panel.mode == "staged"
216+ }
217+
218+ RowLayout {
219+ Layout.fillWidth: true
220+ CheckBox {
221+ id: keyboardAttached
222+ }
223+ Label {
224+ text: "Keyboard Attached"
225+ color: "white"
226+ }
227+ }
169228 }
170229 }
171230
@@ -191,22 +250,31 @@ IndicatorTest {
191250 }
192251
193252 function init() {
253+ panel.mode = "staged";
254+ mouseEmulation.checked = true;
194255 panel.fullscreenMode = false;
195256 callManager.foregroundCall = null;
196257
197− panel.indicators.hide();
198− // Wait for animation to complete
199− tryCompare(panel.indicators.hideAnimation, "running", false);
258+ PanelState.title = "";
259+ PanelState.decorationsVisible = false;
200260
201261 // Wait for the indicators to get into position.
202262 // (switches between normal and fullscreen modes are animated)
203− var indicatorArea = findChild(panel, "indicatorArea");
204− tryCompare(indicatorArea, "y", 0);
263+ var panelArea = findChild(panel, "panelArea");
264+ tryCompare(panelArea, "y", 0);
205265
206266 backgroundPressedSpy.clear();
207267 compare(backgroundPressedSpy.valid, true);
208268 windowControlButtonsSpy.clear();
209269 compare(windowControlButtonsSpy.valid, true);
270+
271+ waitForRendering(panel);
272+ }
273+
274+ function cleanup() {
275+ panel.indicators.hide();
276+ panel.applicationMenus.hide();
277+ waitForAllAnimationToComplete("initial");
210278 }
211279
212280 function get_indicator_item(index) {
@@ -216,8 +284,28 @@ IndicatorTest {
216284 return indicatorItem;
217285 }
218286
287+ function waitForAllAnimationToComplete(state) {
288+
289+ waitUntilTransitionsEnd(panel);
290+ tryCompare(panel.indicators.hideAnimation, "running", false);
291+ tryCompare(panel.indicators.showAnimation, "running", false);
292+ tryCompare(panel.indicators, "state", state);
293+
294+ for (var i = 0; i < root.originalModelData.length; i++) {
295+ var indicatorItem = get_indicator_item(i);
296+
297+ var itemState = findInvisibleChild(indicatorItem, "indicatorItemState");
298+ verify(itemState !== null);
299+
300+ waitUntilTransitionsEnd(itemState);
301+ }
302+
303+ tryCompare(panel.applicationMenus.hideAnimation, "running", false);
304+ tryCompare(panel.applicationMenus, "state", state);
305+ }
306+
219307 function pullDownIndicatorsMenu() {
220− var showDragHandle = findChild(panel, "showDragHandle");
308+ var showDragHandle = findChild(panel.indicators, "showDragHandle");
221309 touchFlick(showDragHandle,
222310 showDragHandle.width / 2,
223311 showDragHandle.height / 2,
@@ -226,16 +314,22 @@ IndicatorTest {
226314 tryCompare(panel.indicators, "fullyOpened", true);
227315 }
228316
229− function test_drag_show_data() {
317+ function pullDownApplicationsMenu() {
318+ var showDragHandle = findChild(panel.applicationMenus, "showDragHandle");
319+ touchFlick(showDragHandle,
320+ showDragHandle.width / 2,
321+ showDragHandle.height / 2,
322+ showDragHandle.width / 2,
323+ showDragHandle.height / 2 + (showDragHandle.autoCompleteDragThreshold * 1.1));
324+ tryCompare(panel.applicationMenus, "fullyOpened", true);
325+ }
326+
327+ function test_drag_indicator_item_down_shows_menu_data() {
230328 return [
231− { tag: "pinned", fullscreen: false, call: null,
232− indicatorY: 0 },
233− { tag: "fullscreen", fullscreen: true, call: null,
234− indicatorY: -panel.panelAndSeparatorHeight },
235− { tag: "pinned-callActive", fullscreen: false, call: phoneCall,
236− indicatorY: 0},
237− { tag: "fullscreen-callActive", fullscreen: true, call: phoneCall,
238− indicatorY: -panel.panelAndSeparatorHeight }
329+ { tag: "pinned", fullscreen: false, call: null, y: 0 },
330+ { tag: "fullscreen", fullscreen: true, call: null, y: -panel.minimizedPanelHeight },
331+ { tag: "pinned-callActive", fullscreen: false, call: phoneCall, y: 0},
332+ { tag: "fullscreen-callActive", fullscreen: true, call: phoneCall, y: -panel.minimizedPanelHeight }
239333 ];
240334 }
241335
@@ -243,24 +337,26 @@ IndicatorTest {
243337 // indicators, first by running the hint animation, then after dragging down will
244338 // expose more of the panel, binding it to the selected indicator and opening it's menu.
245339 // Tested from first Y pixel to check for swipe from offscreen.
246− function test_drag_show(data) {
340+ function test_drag_indicator_item_down_shows_menu(data) {
247341 panel.fullscreenMode = data.fullscreen;
248342 callManager.foregroundCall = data.call;
249343
250− var indicatorRow = findChild(panel.indicators, "indicatorItemRow");
251− verify(indicatorRow !== null);
344+ var panelRow = findChild(panel.indicators, "panelItemRow");
345+ verify(panelRow !== null);
252346
253347 var menuContent = findChild(panel.indicators, "menuContent");
254348 verify(menuContent !== null);
255349
256− var indicatorArea = findChild(panel, "indicatorArea");
257− verify(indicatorArea !== null);
350+ var panelArea = findChild(panel, "panelArea");
351+ verify(panelArea !== null);
258352
259353 // Wait for the indicators to get into position.
260354 // (switches between normal and fullscreen modes are animated)
261− tryCompareFunction(function() { return indicatorArea.y }, data.indicatorY);
355+ tryCompareFunction(function() { return panelArea.y }, data.y);
262356
263357 for (var i = 0; i < root.originalModelData.length; i++) {
358+ waitForAllAnimationToComplete("initial");
359+
264360 var indicatorItem = get_indicator_item(i);
265361
266362 var startXPosition = panel.mapFromItem(indicatorItem, indicatorItem.width / 2, 0).x;
@@ -268,7 +364,7 @@ IndicatorTest {
268364 touchFlick(panel,
269365 startXPosition, 0,
270366 startXPosition, panel.height,
271− true /* beginTouch */, false /* endTouch */, units.gu(5), 15);
367+ true /* beginTouch */, false /* endTouch */, 1, 15);
272368
273369 // Indicators height should follow the drag, and therefore increase accordingly.
274370 // They should be at least half-way through the screen
@@ -278,105 +374,152 @@ IndicatorTest {
278374
279375 touchRelease(panel, startXPosition, panel.height);
280376
281− compare(indicatorRow.currentItemIndex, i, "Indicator item should be activated at position " + i);
377+ tryCompare(panelRow, "currentItemIndex", i, undefined, "Indicator item should be activated at position " + i);
282378 compare(menuContent.currentMenuIndex, i, "Menu conetent should be activated for item at position " + i);
283379
284380 // init for next indicatorItem
285381 panel.indicators.hide();
286− tryCompare(panel.indicators.hideAnimation, "running", false);
287− tryCompare(panel.indicators, "state", "initial");
288382 }
289383 }
290384
291− function test_drag_hide_data() {
385+ function test_drag_panel_handle_up_hides_menu_data() {
292386 return [
293− { tag: "pinned", fullscreen: false, call: null,
294− indicatorY: 0 },
295− { tag: "fullscreen", fullscreen: true, call: null,
296− indicatorY: -panel.panelAndSeparatorHeight },
297− { tag: "pinned-callActive", fullscreen: false, call: phoneCall,
298− indicatorY: 0},
299− { tag: "fullscreen-callActive", fullscreen: true, call: phoneCall,
300− indicatorY: -panel.panelAndSeparatorHeight }
387+ { tag: "indicators-pinned", section: panel.indicators, fullscreen: false, call: null },
388+ { tag: "indicators-fullscreen", section: panel.indicators, fullscreen: true, call: null },
389+ { tag: "indicators-pinned-callActive", section: panel.indicators, fullscreen: false, call: phoneCall },
390+ { tag: "indicators-fullscreen-callActive", section: panel.indicators, fullscreen: true, call: phoneCall },
391+ { tag: "appMenus-pinned", section: panel.applicationMenus, fullscreen: false, call: null },
392+ { tag: "appMenus-fullscreen", section: panel.applicationMenus, fullscreen: true, call: null },
393+ { tag: "appMenus-pinned-callActive", section: panel.applicationMenus, fullscreen: false, call: phoneCall },
394+ { tag: "appMenus-fullscreen-callActive", section: panel.applicationMenus, fullscreen: true, call: phoneCall }
301395 ];
302396 }
303397
304398 // Dragging the shown indicators up from bottom of panel will hide the indicators
305399 // Tested from last Y pixel to check for swipe from offscreen.
306− function test_drag_hide(data) {
400+ function test_drag_panel_handle_up_hides_menu(data) {
307401 panel.fullscreenMode = data.fullscreen;
308402 callManager.foregroundCall = data.call;
309403
310− var indicatorRow = findChild(panel.indicators, "indicatorItemRow");
311− verify(indicatorRow !== null);
404+ var panelRow = findChild(data.section, "panelItemRow");
405+ verify(panelRow !== null);
312406
313− var menuContent = findChild(panel.indicators, "menuContent");
314− verify(menuContent !== null);
315−
316− var indicatorArea = findChild(panel, "indicatorArea");
317− verify(indicatorArea !== null);
407+ var panelArea = findChild(panel, "panelArea");
408+ verify(panelArea !== null);
318409
319410 // Wait for the indicators to get into position.
320411 // (switches between normal and fullscreen modes are animated)
321− tryCompareFunction(function() { return indicatorArea.y }, data.indicatorY);
412+ tryCompareFunction(function() { return panelArea.y }, data.fullscreen ? -panel.minimizedPanelHeight : 0);
322413
323− panel.indicators.show();
324− tryCompare(panel.indicators.showAnimation, "running", false);
325− tryCompare(panel.indicators, "unitProgress", 1);
414+ data.section.show();
415+ tryCompare(data.section.showAnimation, "running", false);
416+ tryCompare(data.section, "unitProgress", 1);
326417
327− touchFlick(panel.indicators,
328− panel.indicators.width / 2, panel.height,
329− panel.indicators.width / 2, 0,
418+ touchFlick(data.section,
419+ data.section.width / 2, panel.height,
420+ data.section.width / 2, 0,
330421 true /* beginTouch */, false /* endTouch */, units.gu(5), 15);
331422
332423 // Indicators height should follow the drag, and therefore increase accordingly.
333424 // They should be at least half-way through the screen
334425 tryCompareFunction(
335− function() {return panel.indicators.height <= panel.height * 0.5},
426+ function() {return data.section.height <= panel.height * 0.5},
336427 true);
337428
338− touchRelease(panel.indicators, panel.indicators.width / 2, 0);
429+ touchRelease(data.section, data.section.width / 2, 0);
339430
340− tryCompare(panel.indicators.hideAnimation, "running", true);
341− tryCompare(panel.indicators.hideAnimation, "running", false);
342− tryCompare(panel.indicators, "state", "initial");
431+ tryCompare(data.section.hideAnimation, "running", true);
432+ tryCompare(data.section.hideAnimation, "running", false);
433+ tryCompare(data.section, "state", "initial");
343434 }
344435
345436 function test_hint_data() {
346437 return [
347− { tag: "normal", fullscreen: false, call: null, hintExpected: true},
348− { tag: "fullscreen", fullscreen: true, call: null, hintExpected: false},
349− { tag: "call hint", fullscreen: false, call: phoneCall, hintExpected: false},
438+ { tag: "indicators-normal", section: panel.indicators, fullscreen: false, call: null, hintExpected: true},
439+ { tag: "indicators-fullscreen", section: panel.indicators, fullscreen: true, call: null, hintExpected: false},
440+ { tag: "indicators-callActive", section: panel.indicators, fullscreen: false, call: phoneCall, hintExpected: false},
441+ { tag: "appMenus-normal", section: panel.applicationMenus, fullscreen: false, call: null, hintExpected: true},
442+ { tag: "appMenus-fullscreen", section: panel.applicationMenus, fullscreen: true, call: null, hintExpected: false},
443+ { tag: "appMenus-callActive", section: panel.applicationMenus, fullscreen: false, call: phoneCall, hintExpected: false},
350444 ];
351445 }
352446
353447 function test_hint(data) {
448+ PanelState.title = "Fake Title"
354449 panel.fullscreenMode = data.fullscreen;
355450 callManager.foregroundCall = data.call;
356451
357452 if (data.fullscreen) {
358453 // Wait for the indicators to get into position.
359454 // (switches between normal and fullscreen modes are animated)
360− var indicatorArea = findChild(panel, "indicatorArea");
361− tryCompare(indicatorArea, "y", -panel.panelHeight);
455+ var panelArea = findChild(panel, "panelArea");
456+ tryCompare(panelArea, "y", -panel.minimizedPanelHeight);
362457 }
363458
364− var indicatorItem = get_indicator_item(0);
365− var mappedPosition = root.mapFromItem(indicatorItem, indicatorItem.width / 2, indicatorItem.height / 2);
459+ var mappedPosition = root.mapFromItem(data.section,
460+ data.section.barWidth / 2, data.section.minimizedPanelHeight / 2);
461+
462+ touchPress(panel, mappedPosition.x, panel.minimizedPanelHeight / 2);
366463
367− touchPress(panel, mappedPosition.x, panel.indicators.minimizedPanelHeight / 2);
464+ var showDragHandle = findChild(data.section, "showDragHandle")
465+ var hintingAnimation = findInvisibleChild(showDragHandle, "hintingAnimation");
466+ verify(hintingAnimation);
368467
369− // Give some time for a hint animation to change things, if any
370− wait(500);
468+ compare(hintingAnimation.running, data.hintExpected)
469+ tryCompare(hintingAnimation, "running", false); // wait till animation completes
371470
372471 // no hint animation when fullscreen
373− compare(panel.indicators.fullyClosed, !data.hintExpected, "Indicator should be fully closed");
374− compare(panel.indicators.partiallyOpened, data.hintExpected, "Indicator should be partialy opened");
375− compare(panel.indicators.fullyOpened, false, "Indicator should not be fully opened");
472+ compare(data.section.partiallyOpened, data.hintExpected, "Indicator should be partialy opened");
473+ compare(data.section.fullyOpened, false, "Indicator should not be fully opened");
376474
377475 touchRelease(panel, mappedPosition.x, panel.minimizedPanelHeight / 2);
378476 }
379477
478+ function test_drag_applicationMenu_down_shows_menu_data() {
479+ return [
480+ { tag: "normal", fullscreen: false, call: null, hintExpected: true},
481+ { tag: "fullscreen", fullscreen: true, call: null, hintExpected: false},
482+ { tag: "callActive", fullscreen: false, call: phoneCall, hintExpected: false}
483+ ];
484+ }
485+
486+ // Dragging the application menu will gradually expose the
487+ // menus, first by running the hint animation, then after dragging down will
488+ // expose more of the panel. Releasing the touch will complete the show.
489+ function test_drag_applicationMenu_down_shows_menu(data) {
490+ PanelState.title = "Fake Title";
491+ panel.fullscreenMode = data.fullscreen;
492+ callManager.foregroundCall = data.call;
493+
494+ var panelRow = findChild(panel.indicators, "panelItemRow");
495+ verify(panelRow !== null);
496+
497+ var menuContent = findChild(panel.indicators, "menuContent");
498+ verify(menuContent !== null);
499+
500+ var panelArea = findChild(panel, "panelArea");
501+ verify(panelArea !== null);
502+
503+ // Wait for the indicators to get into position.
504+ // (switches between normal and fullscreen modes are animated)
505+ tryCompareFunction(function() { return panelArea.y }, data.fullscreen ? -panel.minimizedPanelHeight : 0);
506+
507+ touchFlick(panel,
508+ units.gu(1), 0,
509+ units.gu(1), panel.height,
510+ true /* beginTouch */, false /* endTouch */, units.gu(5), 15);
511+
512+ // Indicators height should follow the drag, and therefore increase accordingly.
513+ // They should be at least half-way through the screen
514+ tryCompareFunction(
515+ function() {return panel.applicationMenus.height >= panel.height * 0.5},
516+ true);
517+
518+ touchRelease(panel, units.gu(1), panel.height);
519+
520+ tryCompare(panel.applicationMenus, "fullyOpened", true)
521+ }
522+
380523 /* Checks that no input reaches items behind the indicator bar.
381524 Ie., the indicator bar should eat all input events that hit it.
382525 */
@@ -385,20 +528,20 @@ IndicatorTest {
385528 // that it doesn't have a "weak spot" from where taps pass through.
386529 var numTaps = 5;
387530 var stepLength = (panel.width / (numTaps + 1));
388− var tapY = panel.indicators.minimizedPanelHeight / 2;
531+ var tapY = panel.minimizedPanelHeight / 2;
389532 for (var i = 1; i <= numTaps; ++i) {
390533 tap(panel, stepLength * i, tapY);
391534 tryCompare(panel.indicators, "fullyClosed", true);
392535 }
393536 }
394537
395− function test_darkenedAreaEatsAllEvents() {
538+ function test_darkenedAreaEatsAllIndicatorEvents() {
396539
397540 // The center of the area not covered by the indicators menu
398541 // Ie, the visible darkened area behind the menu
399542 var touchPosX = (panel.width - panel.indicators.width) / 2
400− var touchPosY = panel.indicators.minimizedPanelHeight +
401− ((panel.height - panel.indicators.minimizedPanelHeight) / 2)
543+ var touchPosY = panel.minimizedPanelHeight +
544+ ((panel.height - panel.minimizedPanelHeight) / 2)
402545
403546 // input goes through while the indicators menu is closed
404547 tryCompare(panel.indicators, "fullyClosed", true);
@@ -434,6 +577,50 @@ IndicatorTest {
434577 compare(backgroundPressedSpy.count, 2);
435578 }
436579
580+ function test_darkenedAreaEatsAllApplicationMenuEvents() {
581+ PanelState.title = "Fake Title"
582+
583+ // The center of the area not covered by the indicators menu
584+ // Ie, the visible darkened area behind the menu
585+ var touchPosX = panel.applicationMenus.width + (panel.width - panel.applicationMenus.width) / 2
586+ var touchPosY = panel.minimizedPanelHeight +
587+ ((panel.height - panel.minimizedPanelHeight) / 2)
588+
589+ // input goes through while the indicators menu is closed
590+ tryCompare(panel.applicationMenus, "fullyClosed", true);
591+ compare(backgroundPressedSpy.count, 0);
592+ tap(panel, touchPosX, touchPosY);
593+ compare(backgroundPressedSpy.count, 2);
594+
595+ pullDownApplicationsMenu();
596+
597+ // Darkened area eats input when the indicators menu is fully opened
598+ tap(panel, touchPosX, touchPosY);
599+ compare(backgroundPressedSpy.count, 2);
600+ backgroundPressedSpy.clear();
601+
602+ // And should continue to eat inpunt until the indicators menu is fully closed
603+ wait(10);
604+ while (!panel.applicationMenus.fullyClosed) {
605+ tap(panel, touchPosX, touchPosY);
606+
607+ // it could have got fully closed during the tap
608+ // so we have to double check here
609+ if (!panel.applicationMenus.fullyClosed) {
610+ compare(backgroundPressedSpy.count, 0);
611+ }
612+
613+ // let the animation go a bit further
614+ wait(50);
615+ }
616+
617+ // Now that's fully closed, input should go through again
618+ backgroundPressedSpy.clear();
619+ tap(panel, touchPosX, touchPosY);
620+ compare(backgroundPressedSpy.count, 2);
621+ }
622+
623+
437624 /*
438625 Regression test for https://bugs.launchpad.net/ubuntu/+source/unity8/+bug/1439318
439626 When the panel is in fullscreen mode and the user taps near the top edge,
@@ -441,14 +628,12 @@ IndicatorTest {
441628 panel.
442629 */
443630 function test_tapNearTopEdgeWithPanelInFullscreenMode() {
444− var indicatorArea = findChild(panel, "indicatorArea");
445− verify(indicatorArea);
446− var panelPriv = findInvisibleChild(panel, "panelPriv");
447− verify(panelPriv);
631+ var panelArea = findChild(panel, "panelArea");
632+ verify(panelArea);
448633
449634 panel.fullscreenMode = true;
450635 // wait until if finishes hiding itself
451− tryCompare(indicatorArea, "y", -panelPriv.indicatorHeight);
636+ tryCompare(panelArea, "y", -panel.minimizedPanelHeight);
452637
453638 compare(panel.indicators.shown, false);
454639 verify(panel.indicators.fullyClosed);
@@ -479,7 +664,7 @@ IndicatorTest {
479664
480665 mouseClick(panel.indicators,
481666 panel.indicators.width / 2,
482− panel.indicators.minimizedPanelHeight / 2);
667+ panel.minimizedPanelHeight / 2);
483668
484669 compare(panel.indicators.shown, false);
485670 verify(panel.indicators.fullyClosed);
@@ -494,7 +679,7 @@ IndicatorTest {
494679
495680 mouseClick(panel.indicators,
496681 panel.indicators.width / 2,
497− panel.indicators.minimizedPanelHeight / 2);
682+ panel.minimizedPanelHeight / 2);
498683
499684 compare(panel.indicators.shown, true);
500685 tryCompare(panel.indicators, "fullyOpened", true);
@@ -510,13 +695,109 @@ IndicatorTest {
510695
511696 // https://bugs.launchpad.net/ubuntu/+source/unity8/+bug/1611959
512697 function test_windowControlButtonsFittsLaw() {
513− var buttonsVisible = PanelState.buttonsVisible;
514− PanelState.buttonsVisible = true;
698+ panel.mode = "windowed";
699+ var windowControlArea = findChild(panel, "windowControlArea");
700+ verify(windowControlArea, "Window control area should have been created in windowed mode")
701+
702+ PanelState.decorationsVisible = true;
515703 // click in very topleft corner and verify the close button got clicked too
516704 mouseMove(panel, 0, 0);
517705 mouseClick(panel, 0, 0, undefined /*button*/, undefined /*modifiers*/, 100 /*short delay*/);
518706 compare(windowControlButtonsSpy.count, 1);
519− PanelState.buttonsVisible = buttonsVisible;
707+ }
708+
709+ function test_hidingKeyboardIndicator_data() {
710+ return [
711+ { tag: "No keyboard, no keymap", keyboard: false, keymaps: [], hidden: true },
712+ { tag: "No keyboard, one keymap", keyboard: false, keymaps: ["us"], hidden: true },
713+ { tag: "No keyboard, 2 keymaps", keyboard: false, keymaps: ["us", "cs"], hidden: true },
714+ { tag: "Keyboard, no keymap", keyboard: true, keymaps: [], hidden: true },
715+ { tag: "Keyboard, one keymap", keyboard: true, keymaps: ["us"], hidden: true },
716+ { tag: "Keyboard, 2 keymaps", keyboard: true, keymaps: ["us", "cs"], hidden: false }
717+ ];
718+ }
719+
720+ function test_hidingKeyboardIndicator(data) {
721+ var item = findChild(panel, "indicator-keyboard-panelItem");
722+ AccountsService.keymaps = data.keymaps;
723+ if (data.keyboard) {
724+ MockInputDeviceBackend.addMockDevice("/indicator_kbd0", InputInfo.Keyboard);
725+ } else {
726+ MockInputDeviceBackend.removeDevice("/indicator_kbd0");
727+ }
728+
729+ compare(item.hidden, data.hidden);
730+ }
731+
732+ function test_visibleIndicators_data() {
733+ return [
734+ { visible: [true, false, true, false, true, true, false, true] },
735+ { visible: [false, false, false, false, false, false, true, false] }
736+ ];
737+ }
738+
739+ function test_visibleIndicators(data) {
740+ for (var i = 0; i < data.visible.length; i++) {
741+ var visible = data.visible[i];
742+ root.setIndicatorVisible(i, visible);
743+
744+ var dataItem = findChild(panel, root.originalModelData[i]["identifier"] + "-panelItem");
745+ tryCompare(dataItem, "opacity", visible ? 1.0 : 0.0);
746+ tryCompareFunction(function() { return dataItem.width > 0.0; }, visible);
747+ }
748+
749+ panel.indicators.show();
750+ tryCompare(panel.indicators.showAnimation, "running", false);
751+ tryCompare(panel.indicators, "unitProgress", 1);
752+
753+ for (var i = 0; i < data.visible.length; i++) {
754+ root.setIndicatorVisible(i, data.visible[i]);
755+
756+ var dataItem = findChild(panel, root.originalModelData[i]["identifier"] + "-panelItem");
757+ tryCompareFunction(function() { return dataItem.opacity > 0.0; }, true);
758+ tryCompareFunction(function() { return dataItem.width > 0.0; }, true);
759+ }
760+ }
761+
762+ function test_stagedApplicationMenuBarShowOnMouseHover() {
763+ PanelState.title = "Fake Title";
764+ panel.mode = "staged";
765+ mouseEmulation.checked = false;
766+
767+ var appTitle = findChild(panel.applicationMenus, "panelTitle"); verify(appTitle);
768+ var appMenuRow = findChild(panel.applicationMenus, "panelRow"); verify(appMenuRow);
769+ var appMenuBar = findChild(panel, "menuBar"); verify(appMenuBar);
770+
771+ tryCompare(appTitle, "visible", true, undefined, "App title should be visible");
772+ tryCompare(appMenuBar, "visible", false, undefined, "App menu bar should not be visible");
773+
774+ mouseMove(panel, panel.width/2, panel.panelHeight);
775+
776+ tryCompare(appTitle, "visible", false, undefined, "App title should not be visible on mouse hover");
777+ tryCompare(appMenuBar, "visible", true, undefined, "App menu bar should be visible on mouse hover");
778+ }
779+
780+ function test_windowedApplicationMenuShowOnMouseHoverWhenDecorationsShown() {
781+ PanelState.title = "Fake Title";
782+ panel.mode = "windowed";
783+ mouseEmulation.checked = false;
784+
785+ var appTitle = findChild(panel.applicationMenus, "panelTitle"); verify(appTitle);
786+ var appMenuRow = findChild(panel.applicationMenus, "panelRow"); verify(appMenuRow);
787+ var appMenuBar = findChild(panel, "menuBar"); verify(appMenuBar);
788+
789+ tryCompare(appTitle, "visible", true, undefined, "App title should be visible");
790+ tryCompare(appMenuBar, "visible", false, undefined, "App menu bar should not be visible");
791+
792+ mouseMove(panel, panel.width/2, panel.panelHeight);
793+
794+ tryCompare(appTitle, "visible", true, undefined, "App title should still be visible on mouse hover when panel decorations are not visible");
795+ tryCompare(appMenuBar, "visible", false, undefined, "App menu bar should be visible on mouse hover when panel decorations are not visible");
796+
797+ PanelState.decorationsVisible = true;
798+
799+ tryCompare(appTitle, "visible", false, undefined, "App title should still be visible on mouse hover when panel decorations are visible");
800+ tryCompare(appMenuBar, "visible", true, undefined, "App menu bar should be visible on mouse hover when panel decorations not visible");
520801 }
521802 }
522803}