Merge lp:~mardy/unity-2d/spread-a11y-geometry into lp:unity-2d

Proposed by Alberto Mardegan
Status: Merged
Merged at revision: 798
Proposed branch: lp:~mardy/unity-2d/spread-a11y-geometry
Merge into: lp:unity-2d
Diff against target: 692 lines (+256/-152)
9 files modified
libunity-2d-private/Unity2d/GnomeBackground.qml (+4/-2)
libunity-2d-private/src/screeninfo.cpp (+7/-0)
libunity-2d-private/src/screeninfo.h (+3/-0)
places/app/dashdeclarativeview.cpp (+2/-17)
places/app/dashdeclarativeview.h (+0/-7)
spread/Windows.qml (+20/-8)
spread/Workspace.qml (+133/-83)
spread/Workspaces.qml (+86/-34)
spread/app/spreadview.cpp (+1/-1)
To merge this branch: bzr merge lp:~mardy/unity-2d/spread-a11y-geometry
Reviewer Review Type Date Requested Status
Michał Sawicz functional Needs Fixing
Lohith D Shivamurthy Pending
Florian Boucault functional Pending
Review via email: mp+80358@code.launchpad.net

This proposal supersedes a proposal from 2011-10-21.

Description of the change

[spread] Allow keyboard navigation between workspaces

Turn the Workspace repeater into a GridView, which takes care of giving the
keyboard focus to the proper child element.

This branch is based on lp:~mardy/unity-2d/geometry, and doesn't exhibit the issue of having the desktop background jumping to the left when the exit animation has been completed.

To post a comment you must log in.
Revision history for this message
Florian Boucault (fboucault) wrote : Posted in a previous version of this proposal

Quite nice functionally. Though I did spot one issue: when a workspace is zoomed and you hover an unzoomed workspace, the zoomed workspace is instantly unzoomed and the one hovered becomes focus.

review: Needs Fixing (functional)
Revision history for this message
Florian Boucault (fboucault) wrote : Posted in a previous version of this proposal

You did not actually implement accessibility in the workspace switcher, which is completely fine. The bug report might be confusing in that respect. Bottom line: do we have a separate bug report for adding a11y?

Revision history for this message
Florian Boucault (fboucault) wrote : Posted in a previous version of this proposal

I see the issue I raised earlier was raised by Michaŀ in https://code.launchpad.net/~mardy/unity-2d/spread-a11y/+merge/78593
That was your answer:
"The first issue with the mouse hover could be avoided, but I chose it this way because I think it's more intuitive than requiring to click outside -- and indeed, if you zoomed into a workspace and then move the mouse out of it, you probably want to dismiss it (and if not, it's easy enough to bring it back to zoomed state). Let me know if I should change this."

I'll consult with design now.

Revision history for this message
Florian Boucault (fboucault) wrote : Posted in a previous version of this proposal

btw, which one is the one that is going to be merged? this MR or that one: https://code.launchpad.net/~mardy/unity-2d/spread-a11y/+merge/78593

Revision history for this message
Florian Boucault (fboucault) wrote : Posted in a previous version of this proposal

> I see the issue I raised earlier was raised by Michaŀ in
> https://code.launchpad.net/~mardy/unity-2d/spread-a11y/+merge/78593
> That was your answer:
> "The first issue with the mouse hover could be avoided, but I chose it this
> way because I think it's more intuitive than requiring to click outside -- and
> indeed, if you zoomed into a workspace and then move the mouse out of it, you
> probably want to dismiss it (and if not, it's easy enough to bring it back to
> zoomed state). Let me know if I should change this."
>
> I'll consult with design now.

Design, in the person of John Lea, spotted at least one issue with that automatic zoom on hover: when the user reaches for the launcher the zoomed workspace is automatically unzoomed, which is confusing.

Revision history for this message
Alberto Mardegan (mardy) wrote : Posted in a previous version of this proposal

> btw, which one is the one that is going to be merged? this MR or that one:
> https://code.launchpad.net/~mardy/unity-2d/spread-a11y/+merge/78593

This one. I'll cancel the old one.

I'll fix the unzooming on mouse movement; about the a11y, you are right, this is about keyboard navigation only. I'm not aware of any existing bug.

Revision history for this message
Alberto Mardegan (mardy) wrote : Posted in a previous version of this proposal

Updated the code. Now the zoomed view is not exited with just a mouse hover.

Revision history for this message
Michał Sawicz (saviq) wrote :

One more thing:
1. Invoke spread;
2. Zoom to a workspace with 2+ windows;
3. Click on another workspace;

Expected:
Current workspace unzooms, clicked workspace gets focus and highlight;

Current result:
Highlight shows up where current workspace should be, current workspace unzooms and remains focused;

review: Needs Fixing (functional)
Revision history for this message
Alberto Mardegan (mardy) wrote :

> One more thing:
> 1. Invoke spread;
> 2. Zoom to a workspace with 2+ windows;
> 3. Click on another workspace;

Fixed, MR updated.

Revision history for this message
Lohith D Shivamurthy (dyams) wrote :

There are issues I observed:

1) Invoke the Spread.
2) Now mouse hover over any other workspace in the spread.
3) The any other workspace is highlighted.
4) Now Press Spread shortcut, Super+S.

Expected:
The highlighted workspace(mouse hovered) should be brought to front.

Actual:
The previously zoomed workspace in brought to front again, ignored the current choice.

-----------------------------------------------------
Other issue is :

1) Have at least 2+ windows in two different workspaces
2) Invoke spread
3) Now click on a workspace which contains at least two windows
3) workspace comes front with window selection. (75% Zoomed)
4) Press Spread shortcut, Super+S key

Expected:
The spread should come back to its previous state again where all workspaces are shown in the Grid.

Actual:
Some other workspace is brought to front completely.

Revision history for this message
Alberto Mardegan (mardy) wrote :

Sorry, I have to step out of this, as I don't have time for fixing the issues raised.

Revision history for this message
Gerry Boland (gerboland) wrote :

Unit tests not passing just yet, so merge will fail. Wait for my fixes then merge.

Revision history for this message
Lohith D Shivamurthy (dyams) wrote :

There is merge conflict in places/dashdeclarativeview.cpp

mardy: would it be possible for you to resolve this? Please
It would be very helpful, if you could do so.

rebase your branch with current trunk. You have to edit only two lines.

Thank you.

Revision history for this message
Lohith D Shivamurthy (dyams) wrote :

This branch is moved to new location.
Please follow the new branch here
https://code.launchpad.net/~dyams/unity-2d/mardy-spread-a11y-geometry/+merge/83773

Thank you

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'libunity-2d-private/Unity2d/GnomeBackground.qml'
2--- libunity-2d-private/Unity2d/GnomeBackground.qml 2011-10-21 08:07:49 +0000
3+++ libunity-2d-private/Unity2d/GnomeBackground.qml 2011-11-02 20:30:31 +0000
4@@ -24,6 +24,8 @@
5 Item {
6 property string overlay_color
7 property real overlay_alpha
8+ property int offsetX: -1
9+ property int offsetY: -1
10
11 /* Avoid redraw at rendering */
12 CacheEffect {
13@@ -86,8 +88,8 @@
14 /* by default, place the background on top of the desktop background,
15 no matter where the DeclarativeView or the parent object are placed.
16 */
17- x: parent.mapFromItem(null, -declarativeView.globalPosition.x, 0).x
18- y: parent.mapFromItem(null, 0, -declarativeView.globalPosition.y).y
19+ x: offsetX != -1 ? offsetX : parent.mapFromItem(null, -declarativeView.globalPosition.x, 0).x
20+ y: offsetY != -1 ? offsetY : parent.mapFromItem(null, 0, -declarativeView.globalPosition.y).y
21
22 /* Possible modes are:
23 - "wallpaper"
24
25=== modified file 'libunity-2d-private/src/screeninfo.cpp'
26--- libunity-2d-private/src/screeninfo.cpp 2011-10-03 11:13:44 +0000
27+++ libunity-2d-private/src/screeninfo.cpp 2011-11-02 20:30:31 +0000
28@@ -71,6 +71,12 @@
29
30 QRect ScreenInfo::availableGeometry() const
31 {
32+ int screen = QX11Info::appScreen();
33+ return QApplication::desktop()->availableGeometry(screen);
34+}
35+
36+QRect ScreenInfo::panelsFreeGeometry() const
37+{
38 /* We cannot just return the system's availableGeometry(), because that
39 * doesn't consider the Launcher, if it's set to auto-hide. */
40 int screen = QX11Info::appScreen();
41@@ -105,6 +111,7 @@
42 {
43 if (screen == QX11Info::appScreen()) {
44 Q_EMIT availableGeometryChanged(availableGeometry());
45+ Q_EMIT panelsFreeGeometryChanged(panelsFreeGeometry());
46 }
47 }
48
49
50=== modified file 'libunity-2d-private/src/screeninfo.h'
51--- libunity-2d-private/src/screeninfo.h 2011-07-29 13:49:34 +0000
52+++ libunity-2d-private/src/screeninfo.h 2011-11-02 20:30:31 +0000
53@@ -21,6 +21,7 @@
54 Q_PROPERTY(unsigned int activeWindow READ activeWindow NOTIFY activeWindowChanged)
55 Q_PROPERTY(QRect geometry READ geometry NOTIFY geometryChanged)
56 Q_PROPERTY(QRect availableGeometry READ availableGeometry NOTIFY availableGeometryChanged)
57+ Q_PROPERTY(QRect panelsFreeGeometry READ panelsFreeGeometry NOTIFY panelsFreeGeometryChanged)
58 Q_PROPERTY(bool isCompositingManagerRunning READ isCompositingManagerRunning
59 NOTIFY isCompositingManagerRunningChanged)
60
61@@ -36,6 +37,7 @@
62 WorkspacesInfo *workspaces() { return &m_workspacesInfo; }
63 unsigned int activeWindow() const { return m_activeWindow; }
64 QRect availableGeometry() const;
65+ QRect panelsFreeGeometry() const;
66 QRect geometry() const;
67 bool isCompositingManagerRunning() const;
68
69@@ -43,6 +45,7 @@
70 void activeWindowChanged(unsigned int activeWindow);
71 void geometryChanged(QRect geometry);
72 void availableGeometryChanged(QRect availableGeometry);
73+ void panelsFreeGeometryChanged(QRect panelsFreeGeometry);
74 void workspacesChanged(WorkspacesInfo *workspaces);
75 void isCompositingManagerRunningChanged(bool);
76
77
78=== modified file 'places/app/dashdeclarativeview.cpp'
79--- places/app/dashdeclarativeview.cpp 2011-10-03 11:13:44 +0000
80+++ places/app/dashdeclarativeview.cpp 2011-11-02 20:30:31 +0000
81@@ -59,7 +59,6 @@
82 setTransparentBackground(QX11Info::isCompositingManagerRunning());
83
84 QDesktopWidget* desktop = QApplication::desktop();
85- connect(desktop, SIGNAL(resized(int)), SIGNAL(screenGeometryChanged()));
86 connect(desktop, SIGNAL(resized(int)), SIGNAL(updateDashModeDependingOnScreenGeometry()));
87 connect(desktop, SIGNAL(workAreaResized(int)), SLOT(onWorkAreaResized(int)));
88
89@@ -74,7 +73,6 @@
90 }
91
92 updateSize();
93- availableGeometryChanged();
94 }
95
96
97@@ -112,7 +110,7 @@
98 void
99 DashDeclarativeView::fitToAvailableSpace()
100 {
101- QRect rect = availableGeometry();
102+ QRect rect = m_screenInfo->panelsFreeGeometry();
103 move(rect.topLeft());
104 setFixedSize(rect.size());
105 }
106@@ -120,7 +118,7 @@
107 void
108 DashDeclarativeView::resizeToDesktopModeSize()
109 {
110- QRect rect = availableGeometry();
111+ QRect rect = m_screenInfo->panelsFreeGeometry();
112 int screenRight = rect.right();
113
114 rect.setWidth(qMin(DASH_DESKTOP_WIDTH, rect.width()));
115@@ -261,19 +259,6 @@
116 setActive(true);
117 }
118
119-const QRect
120-DashDeclarativeView::screenGeometry() const
121-{
122- QDesktopWidget* desktop = QApplication::desktop();
123- return desktop->screenGeometry(this);
124-}
125-
126-QRect
127-DashDeclarativeView::availableGeometry() const
128-{
129- return m_screenInfo->availableGeometry();
130-}
131-
132 void
133 DashDeclarativeView::keyPressEvent(QKeyEvent* event)
134 {
135
136=== modified file 'places/app/dashdeclarativeview.h'
137--- places/app/dashdeclarativeview.h 2011-10-03 11:13:44 +0000
138+++ places/app/dashdeclarativeview.h 2011-11-02 20:30:31 +0000
139@@ -32,8 +32,6 @@
140 Q_PROPERTY(bool expanded READ expanded WRITE setExpanded NOTIFY expandedChanged)
141 Q_PROPERTY(DashMode dashMode READ dashMode WRITE setDashMode NOTIFY dashModeChanged)
142 Q_PROPERTY(QString activeLens READ activeLens WRITE setActiveLens NOTIFY activeLensChanged)
143- Q_PROPERTY(QRect screenGeometry READ screenGeometry NOTIFY screenGeometryChanged)
144- Q_PROPERTY(QRect availableGeometry READ availableGeometry NOTIFY availableGeometryChanged)
145
146 public:
147 enum DashMode {
148@@ -46,8 +44,6 @@
149 bool active() const;
150 DashMode dashMode() const;
151 const QString& activeLens() const;
152- const QRect screenGeometry() const;
153- QRect availableGeometry() const;
154 bool expanded() const;
155
156 /* setters */
157@@ -67,9 +63,6 @@
158 void expandedChanged(bool);
159 void activeLensChanged(const QString&);
160
161- void screenGeometryChanged();
162- void availableGeometryChanged();
163-
164 protected:
165 void resizeEvent(QResizeEvent*);
166 virtual void showEvent(QShowEvent *event);
167
168=== modified file 'spread/Windows.qml'
169--- spread/Windows.qml 2011-08-09 13:33:24 +0000
170+++ spread/Windows.qml 2011-11-02 20:30:31 +0000
171@@ -32,22 +32,23 @@
172
173 The context property called control is the initiator of the entire spread process, and
174 is triggered by D-Bus calls on the C++ side.
175-
176- The ScreenInfo's property availableGeometry represents the available space on the screen (i.e.
177- screen minus launcher, panels, etc.).
178 */
179
180 GridView {
181 id: windows
182
183 signal clicked
184+ signal entered
185 signal windowActivated(variant window)
186
187+ keyNavigationWraps: state == "zoomed"
188+
189 MouseArea {
190 anchors.fill: parent
191 onClicked: windows.clicked()
192 /* Eating all mouse events so that they are not passed beneath the workspace */
193 hoverEnabled: true
194+ onEntered: windows.entered()
195 }
196
197 /* This proxy model takes care of removing all windows that are not on
198@@ -79,7 +80,12 @@
199 cellWidth: Math.floor(width / columns)
200 cellHeight: height / rows
201
202- model: filteredByApplication
203+ /* Set the model only when the component is ready; otherwise, the
204+ * initialization gets somehow messed up and the "columns" and "rows"
205+ * variables are set to those of the first workspace. */
206+ Component.onCompleted: {
207+ model = filteredByApplication
208+ }
209
210 delegate:
211 Item {
212@@ -93,6 +99,11 @@
213 itemHeight: window.size.height
214 parent: windows
215 }
216+ /* We are not using GridView.isCurrentItem because it mysteriously
217+ * returns "false" the first time the spread is activated. Couldn't
218+ * reproduce the same behaviour with simpler test cases.
219+ */
220+ focus: GridView.view.currentIndex == index
221
222 /* Workaround http://bugreports.qt.nokia.com/browse/QTBUG-15642 where onAdd is not called for the first item */
223 //GridView.onAdd:
224@@ -106,8 +117,10 @@
225 switch (event.key) {
226 case Qt.Key_Enter:
227 case Qt.Key_Return:
228+ {
229 windows.windowActivated(spreadWindow)
230 event.accepted = true
231+ }
232 }
233 }
234
235@@ -121,7 +134,8 @@
236
237 onEntered: {
238 windows.currentIndex = index
239- cell.forceActiveFocus()
240+ /* Make sure the workspace is notified as well */
241+ windows.entered()
242 }
243
244 onClicked: windows.windowActivated(spreadWindow)
245@@ -141,14 +155,12 @@
246 Behavior on height { enabled: spreadWindow.animateFollow; NumberAnimation { duration: Utils.transitionDuration; easing.type: Easing.InOutQuad } }
247
248 windowInfo: window
249- state: windows.state
250+ state: windows.state == "screen" ? "screen" : "spread"
251 states: [
252 State {
253 name: "screen"
254 PropertyChanges {
255 target: spreadWindow
256- /* Note that we subtract the availableGeometry x and y since window.location is
257- expressed in global screen coordinates. */
258 x: window.position.x - declarativeView.globalPosition.x
259 y: window.position.y - declarativeView.globalPosition.y
260 width: window.size.width
261
262=== modified file 'spread/Workspace.qml'
263--- spread/Workspace.qml 2011-08-10 00:10:39 +0000
264+++ spread/Workspace.qml 2011-11-02 20:30:31 +0000
265@@ -23,100 +23,150 @@
266 FocusScope {
267 id: workspace
268
269- transformOrigin: Item.TopLeft
270-
271 property real unzoomedScale
272- property int unzoomedX
273- property int unzoomedY
274 property real zoomedScale
275 property int zoomedX
276 property int zoomedY
277+ property alias windowCount: windows.count
278
279+ property int screenOriginX
280+ property int screenOriginY
281 signal clicked
282-
283- GnomeBackground {
284- anchors.fill: parent
285- overlay_color: "black"
286- overlay_alpha: 0
287-
288- clip: true
289- cached: false
290- }
291-
292- Windows {
293- state: workspace.state == "screen" ? "screen" : "spread"
294- anchors.fill: parent
295- focus: true
296- onClicked: workspace.clicked()
297- onWindowActivated: {
298- if (workspace.state != "zoomed") {
299- workspace.clicked()
300- } else {
301- /* Hack to make sure the window is on top of the others during the
302- outro animation */
303- window.z = 9999
304- switcher.activateWindow(window.windowInfo)
305- }
306- }
307- }
308-
309- states: [
310- State {
311- name: "unzoomed"
312- PropertyChanges {
313- target: workspace
314- scale: unzoomedScale
315- x: unzoomedX
316- y: unzoomedY
317- z: 0
318- }
319- },
320- State {
321- name: "zoomed"
322- PropertyChanges {
323- target: workspace
324- scale: zoomedScale
325- x: zoomedX
326- y: zoomedY
327- z: 2
328- }
329- },
330- State {
331- name: "screen"
332- PropertyChanges {
333- target: workspace
334- scale: 1.0
335- x: 0
336- y: 0
337- z: 2
338- }
339- }
340- ]
341-
342- transitions: [
343- Transition {
344- NumberAnimation {
345- target: workspace
346- properties: "x,y,scale"
347- duration: Utils.transitionDuration
348- easing.type: Easing.InOutQuad
349- }
350- },
351- Transition {
352- to: "unzoomed"
353- SequentialAnimation {
354- /* When going to default state put the workspace underneath the
355- workspace in zoomed state but not on the same plane as the
356- workspaces also in the default state until the end of the transition. */
357- PropertyAction { property: "z"; value: 1 }
358+ signal entered
359+
360+ onStateChanged: {
361+ screenOriginX = mapFromItem(switcher, 0, 0).x
362+ screenOriginY = mapFromItem(switcher, 0, 0).y
363+ }
364+
365+ Item {
366+ id: workspaceWindow
367+
368+ transformOrigin: Item.TopLeft
369+ width: switcher.width
370+ height: switcher.height
371+ state: parent.state
372+
373+ GnomeBackground {
374+ anchors.fill: parent
375+ overlay_color: "black"
376+ overlay_alpha: 0
377+
378+ clip: true
379+ cached: false
380+ offsetX: -screen.panelsFreeGeometry.x
381+ offsetY: -screen.panelsFreeGeometry.y
382+ }
383+
384+ Windows {
385+ id: windows
386+ state: workspace.state
387+ anchors.fill: parent
388+ focus: true
389+ onClicked: workspace.clicked()
390+ onEntered: workspace.entered()
391+ onWindowActivated: {
392+ if (workspace.state != "zoomed") {
393+ workspace.clicked()
394+ } else {
395+ /* Hack to make sure the window is on top of the others during the
396+ outro animation */
397+ window.z = 9999
398+ switcher.activateWindow(window.windowInfo)
399+ }
400+ }
401+ }
402+
403+ states: [
404+ State {
405+ name: "unzoomed"
406+ PropertyChanges {
407+ target: workspaceWindow
408+ scale: unzoomedScale
409+ x: switcher.spacing / 2
410+ y: switcher.spacing / 2
411+ }
412+ PropertyChanges {
413+ target: workspace
414+ z: 0
415+ }
416+ },
417+ State {
418+ name: "zoomed"
419+ PropertyChanges {
420+ target: workspaceWindow
421+ scale: zoomedScale
422+ x: zoomedX + workspace.screenOriginX
423+ y: zoomedY + workspace.screenOriginY
424+ }
425+ PropertyChanges {
426+ target: workspace
427+ z: 2
428+ }
429+ },
430+ State {
431+ name: "screen"
432+ PropertyChanges {
433+ target: workspaceWindow
434+ scale: 1.0
435+ x: workspace.screenOriginX
436+ y: workspace.screenOriginY
437+ }
438+ PropertyChanges {
439+ target: workspace
440+ z: 2
441+ }
442+ }
443+ ]
444+
445+ transitions: [
446+ Transition {
447+ /* Disable animations when coming from the base state */
448+ from: ""
449+ },
450+ Transition {
451 NumberAnimation {
452- target: workspace
453+ target: workspaceWindow
454 properties: "x,y,scale"
455 duration: Utils.transitionDuration
456 easing.type: Easing.InOutQuad
457 }
458- PropertyAction { property: "z" }
459+ },
460+ Transition {
461+ to: "unzoomed"
462+ SequentialAnimation {
463+ /* When going to default state put the workspace underneath the
464+ workspace in zoomed state but not on the same plane as the
465+ workspaces also in the default state until the end of the transition. */
466+ PropertyAction { target: workspace; property: "z"; value: 1 }
467+ NumberAnimation {
468+ target: workspaceWindow
469+ properties: "x,y,scale"
470+ duration: Utils.transitionDuration
471+ easing.type: Easing.InOutQuad
472+ }
473+ PropertyAction { target: workspace; property: "z" }
474+ }
475+ }
476+ ]
477+ }
478+
479+ Keys.onPressed: {
480+ switch (event.key) {
481+ case Qt.Key_Enter:
482+ case Qt.Key_Return:
483+ {
484+ clicked()
485+ event.accepted = true
486 }
487 }
488- ]
489+ }
490+
491+ function setFocusOnFirstWindow() {
492+ windows.currentIndex = 0
493+ }
494+
495+ function setFocusOnLastWindow() {
496+ windows.currentIndex = windows.count - 1
497+ }
498 }
499
500=== modified file 'spread/Workspaces.qml'
501--- spread/Workspaces.qml 2011-10-18 12:19:18 +0000
502+++ spread/Workspaces.qml 2011-11-02 20:30:31 +0000
503@@ -29,28 +29,35 @@
504 property int rows: screen.workspaces.rows
505
506 property int margin: 35
507- property int spacing: 5
508+ property int spacing: 4
509
510 /* Effective area available for laying out the workspaces after considering
511 inter-workspace spaces */
512- property int availableWidth: switcher.width - ((columns - 1) * spacing)
513- property int availableHeight: switcher.height - ((rows - 1) * spacing)
514-
515- /* Scale of each workspace when laid out in the switcher grid
516- Note that all scale calculations are done using the desktop's available
517- geometry as this is the "natural" (initial) size of every workspace.
518-
519- FIXME: this seems to be broken in the case of 10 workspaces and 4x4 layout.
520- it does only display a 3x3 grid for some reason.
521- */
522- property bool isLayoutHorizontal: (columns * screen.availableGeometry.width) >
523- (rows * screen.availableGeometry.height)
524- property real cellScale: (isLayoutHorizontal) ? (availableWidth / columns / switcher.width) :
525- (availableHeight / rows / switcher.height)
526+ property int availableWidth: switcher.width - (columns * spacing)
527+ property int availableHeight: switcher.height - (rows * spacing)
528+
529+ property int maxCellWidth: Math.floor(availableWidth / columns)
530+ property int maxCellHeight: Math.floor(availableHeight / rows)
531+ /* Depending on the aspect ratio of the final workspaces layout, we will
532+ have either vertical or horizontal margins. That is, we will either:
533+ - use maxCellWidth as base cell width and compute the height based on the
534+ screen ratio, or
535+ - use maxCellHeight for the base cell height and compute the width based
536+ on the screen ratio.
537+ To figure out which way to go, compute the other size and see how things
538+ would fit inside the screen. */
539+ property int computedCellHeight: maxCellWidth * switcher.height / switcher.width
540+ property int computedCellWidth: maxCellHeight * switcher.width / switcher.height
541+
542+ property bool useWidth: (computedCellHeight + spacing) * rows <= switcher.height
543+
544+ property int cellWidth: useWidth ? maxCellWidth : computedCellWidth
545+ property int cellHeight: useWidth ? computedCellHeight : maxCellHeight
546+ property real cellScale: cellWidth / switcher.width
547
548 /* Scale of a workspace when the user zooms on it (fills most of the switcher, leaving a margin to see
549 the corners of the other workspaces below it) */
550- property bool isDesktopHorizontal: screen.availableGeometry.width > screen.availableGeometry.height
551+ property bool isDesktopHorizontal: screen.panelsFreeGeometry.width > screen.panelsFreeGeometry.height
552 property real zoomedScale: (isDesktopHorizontal) ? ((width - 2*margin) / switcher.width) :
553 ((height - 2*margin) / switcher.height)
554
555@@ -71,34 +78,62 @@
556 /* Group all Workspace elements into a single Item to help workspaceByNumber
557 iterate over less items than it would need to if the Repeater was adding children
558 to the switcher itself. */
559- Repeater {
560+ GridView {
561 id: workspaces
562+ anchors.centerIn: parent
563+
564+ width: cellWidth * columns
565+ height: cellHeight * rows
566
567 model: screen.workspaces.count
568+ cellWidth: parent.cellWidth + spacing
569+ cellHeight: parent.cellHeight + spacing
570+ keyNavigationWraps: true
571+ property string windowFocus
572+ Keys.onPressed: {
573+ if (event.key == Qt.Key_Left || event.key == Qt.Key_Up) {
574+ windowFocus = "last"
575+ } else if (event.key == Qt.Key_Right || event.key == Qt.Key_Down) {
576+ windowFocus = "first"
577+ }
578+ }
579+
580+ highlight: Rectangle {
581+ color: "orange"
582+ x: workspaces.currentItem.x
583+ y: workspaces.currentItem.y
584+ z: -1
585+ width: workspaces.cellWidth
586+ height: workspaces.cellHeight
587+ visible: workspaces.currentItem.state == "unzoomed"
588+ }
589+ highlightFollowsCurrentItem: false
590+
591 delegate: Workspace {
592 id: workspace
593
594- /* FIXME: This is ok right now since we ignore screen.orientation and
595- screen.startingCorner, but we should respect them eventually */
596 property int workspaceNumber: index
597- property int row: Math.floor(index / columns)
598- property int column: index % columns
599-
600- width: switcher.width
601- height: switcher.height
602-
603- /* Organize the workspaces in a grid in 'unzoomed' state */
604- unzoomedX: column * (switcher.width * cellScale) + (column * switcher.spacing)
605- unzoomedY: row * (switcher.height * cellScale) + (row * switcher.spacing)
606+
607+ width: workspaces.cellWidth
608+ height: workspaces.cellHeight
609+
610 unzoomedScale: switcher.cellScale
611
612 /* Center the workspace in 'zoomed' state */
613- zoomedX: (switcher.width - width*zoomedScale) / 2
614- zoomedY: (switcher.height - height*zoomedScale) / 2
615+ zoomedX: switcher.width * (1 - zoomedScale) / 2
616+ zoomedY: switcher.height * (1 - zoomedScale) / 2
617 zoomedScale: switcher.zoomedScale
618
619- focus: zoomedWorkspace == workspaceNumber
620-
621+ Connections {
622+ target: workspaces
623+ onCurrentIndexChanged: {
624+ if (workspaces.windowFocus == "first") {
625+ setFocusOnFirstWindow()
626+ } else if (workspaces.windowFocus == "last") {
627+ setFocusOnLastWindow()
628+ }
629+ }
630+ }
631 state: {
632 if (initial) {
633 if (screen.workspaces.current == workspaceNumber) {
634@@ -115,16 +150,32 @@
635 }
636 }
637
638+ onEntered: {
639+ if (zoomedWorkspace == -1) {
640+ workspaces.currentIndex = index
641+ }
642+ }
643+
644 onClicked: {
645 if (zoomedWorkspace == workspaceNumber) {
646 activateWorkspace(workspaceNumber)
647 } else if (zoomedWorkspace == -1) {
648- zoomedWorkspace = workspaceNumber
649+ if (windowCount <= 1) {
650+ activateWorkspace(workspaceNumber)
651+ } else {
652+ workspaces.currentIndex = index
653+ zoomedWorkspace = workspaceNumber
654+ }
655 } else {
656+ workspaces.currentIndex = index
657 zoomedWorkspace = -1
658 }
659 }
660 }
661+
662+ onCurrentIndexChanged: {
663+ zoomedWorkspace = -1
664+ }
665 }
666
667 /* FIXME: bad naming. Ideas: screenModeActivated, initialState */
668@@ -166,9 +217,10 @@
669
670 spreadView.show()
671 spreadView.forceActivateWindow()
672+ workspaces.currentIndex = screen.workspaces.current
673 /* This is necessary otherwise we don't get keypresses until the user does a
674 mouse over on a window */
675- switcher.forceActiveFocus()
676+ workspaces.forceActiveFocus()
677 initial = false
678 }
679
680
681=== modified file 'spread/app/spreadview.cpp'
682--- spread/app/spreadview.cpp 2011-10-03 11:13:44 +0000
683+++ spread/app/spreadview.cpp 2011-11-02 20:30:31 +0000
684@@ -38,7 +38,7 @@
685
686 if(screen == current_screen)
687 {
688- QRect geometry = m_screenInfo->availableGeometry();
689+ QRect geometry = m_screenInfo->panelsFreeGeometry();
690 setGeometry(geometry);
691 setFixedSize(geometry.size());
692 }

Subscribers

People subscribed via source and target branches