on xenial help sign in
Merge pull request #156 from ubports/xenial_-_edge_-_fixfocus

Make sure no apps have focus if stage is not active/focused

commita37d028e4c084ab1632967290aae2366468e5850 authorMarius Gripsgard <marius@ubports.com> dateSat 29 Jun 2019, 15:48 (7 years ago) parent305605c3686d8c
6 files changed+52−3
plugins/WindowManager/TopLevelWindowModel.cpp+7 plugins/WindowManager/TopLevelWindowModel.h+6 qml/Launcher/Launcher.qml+7−1 qml/Shell.qml+2−2 qml/Stage/Stage.qml+16 tests/qmltests/tst_Shell.qml+14
plugins/WindowManager/TopLevelWindowModel.cpp+7
@@ -38,6 +38,7 @@ Q_LOGGING_CATEGORY(TOPLEVELWINDOWMODEL, "toplevelwindowmodel", QtInfoMsg)
3838namespace unityapi = unity::shell::application;
3939
4040TopLevelWindowModel::TopLevelWindowModel()
41+ : m_nullWindow(createWindow(nullptr))
4142{
4243}
4344
@@ -719,3 +720,9 @@ void TopLevelWindowModel::activateTopMostWindowWithoutId(int forbiddenId)
719720 }
720721 }
721722}
723+
724+void TopLevelWindowModel::activateNullWindow()
725+{
726+ if (!m_nullWindow->focused())
727+ m_nullWindow->activate();
728+}
plugins/WindowManager/TopLevelWindowModel.h+6
@@ -164,6 +164,11 @@ public:
164164 */
165165 Q_INVOKABLE void raiseId(int id);
166166
167+ /**
168+ * @brief Raises and focuses a window with no surface
169+ */
170+ Q_INVOKABLE void activateNullWindow();
171+
167172Q_SIGNALS:
168173 void countChanged();
169174 void inputMethodSurfaceChanged(unity::shell::application::MirSurfaceInterface* inputMethodSurface);
@@ -239,6 +244,7 @@ private:
239244 QVector<ModelEntry> m_windowModel;
240245 Window* m_inputMethodWindow{nullptr};
241246 Window* m_focusedWindow{nullptr};
247+ Window* m_nullWindow;
242248
243249 int m_nextId{1};
244250 // Just something big enough that we don't risk running out of unused id numbers.
qml/Launcher/Launcher.qml+7−1
@@ -42,6 +42,7 @@ FocusScope {
4242
4343 property bool superPressed: false
4444 property bool superTabPressed: false
45+ property bool takesFocus: false;
4546
4647 readonly property bool dragging: dragArea.dragging
4748 readonly property real dragDistance: dragArea.dragging ? dragArea.touchPosition.x : 0
@@ -65,6 +66,8 @@ FocusScope {
6566 }
6667 }
6768
69+ onFocusChanged: {if (!focus) { root.takesFocus = false; }}
70+
6871 onSuperPressedChanged: {
6972 if (state == "drawer")
7073 return;
@@ -84,6 +87,7 @@ FocusScope {
8487 if (superTabPressed) {
8588 switchToNextState("visible")
8689 panel.highlightIndex = -1;
90+ root.takesFocus = true;
8791 root.focus = true;
8892 superPressTimer.stop();
8993 superLongPressTimer.stop();
@@ -128,6 +132,7 @@ FocusScope {
128132 } else {
129133 switchToNextState("")
130134 }
135+ root.focus = false;
131136 }
132137
133138 function fadeOut() {
@@ -164,6 +169,7 @@ FocusScope {
164169 function openForKeyboardNavigation() {
165170 panel.highlightIndex = -1; // The BFB
166171 drawer.focus = false;
172+ root.takesFocus = true;
167173 root.focus = true;
168174 switchToNextState("visible")
169175 }
@@ -176,6 +182,7 @@ FocusScope {
176182 panel.shortcutHintsShown = false;
177183 superPressTimer.stop();
178184 superLongPressTimer.stop();
185+ root.takesFocus = true;
179186 root.focus = true;
180187 if (focusInputField) {
181188 drawer.focusInput();
@@ -232,7 +239,6 @@ FocusScope {
232239 root.hide();
233240 panel.highlightIndex = -2
234241 event.accepted = true;
235− root.focus = false;
236242 }
237243 }
238244
qml/Shell.qml+2−2
@@ -173,6 +173,7 @@ StyledItem {
173173 } else {
174174 startApp(appId);
175175 }
176+ stage.focus = true;
176177 }
177178
178179 function activateURL(url) {
@@ -309,8 +310,7 @@ StyledItem {
309310 interactive: (!greeter || !greeter.shown)
310311 && panel.indicators.fullyClosed
311312 && !notifications.useModal
312−
313− onInteractiveChanged: { if (interactive) { focus = true; } }
313+ && !launcher.takesFocus
314314
315315 suspended: greeter.shown
316316 altTabPressed: physicalKeysMapper.altTabPressed
qml/Stage/Stage.qml+16
@@ -89,6 +89,22 @@ FocusScope {
8989 Qt.InvertedLandscapeOrientation;
9090 }
9191
92+ onInteractiveChanged: {
93+ // Stage must have focus before activating windows, including null
94+ if (interactive) {
95+ focus = true;
96+
97+ // Activate focused app once stage is active again
98+ // this makes sure the focused app have focus
99+ if (priv.focusedAppDelegate) {
100+ priv.focusedAppDelegate.window.activate();
101+ }
102+ } else {
103+ // Activate null window once stage is not active this makes
104+ // sure none of the apps have focus when stage is not active
105+ topLevelSurfaceList.activateNullWindow();
106+ }
107+ }
92108
93109 onAltTabPressedChanged: {
94110 root.focus = true;
tests/qmltests/tst_Shell.qml+14
@@ -3289,6 +3289,20 @@ Rectangle {
32893289 tryCompare(appDelegate2.surface, "activeFocus", true);
32903290 }
32913291
3292+ function test_launchFromDrawerPutsFocusOnStage() {
3293+ loadShell("desktop");
3294+ shell.usageScenario = "desktop";
3295+ waitForRendering(shell);
3296+ swipeAwayGreeter();
3297+
3298+ keyClick(Qt.Key_A, Qt.MetaModifier);
3299+ typeString("browser");
3300+ keyClick(Qt.Key_Enter);
3301+
3302+ var appRepeater = findChild(shell, "appRepeater");
3303+ tryCompare(appRepeater.itemAt(0), "activeFocus", true);
3304+ }
3305+
32923306 function test_maximizedWindowAndMenuInPanel() {
32933307 loadShell("desktop");
32943308 shell.usageScenario = "desktop";