~sil2100/unity-2d/precise-security

« back to all changes in this revision

Viewing changes to spread/Workspaces.qml

  • Committer: Aurelien Gateau
  • Date: 2010-11-10 08:57:29 UTC
  • mto: This revision was merged to the branch mainline in revision 284.
  • Revision ID: aurelien.gateau@canonical.com-20101110085729-fl1ye7impkqhm0w6
Added a section about const correct-ness

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * This file is part of unity-2d
3
 
 *
4
 
 * Copyright 2010-2011 Canonical Ltd.
5
 
 *
6
 
 * This program is free software; you can redistribute it and/or modify
7
 
 * it under the terms of the GNU General Public License as published by
8
 
 * the Free Software Foundation; version 3.
9
 
 *
10
 
 * This program is distributed in the hope that it will be useful,
11
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
 * GNU General Public License for more details.
14
 
 *
15
 
 * You should have received a copy of the GNU General Public License
16
 
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
 
 */
18
 
 
19
 
import QtQuick 1.0
20
 
import Unity2d 1.0
21
 
import "utils.js" as Utils
22
 
 
23
 
Rectangle {
24
 
    id: switcher
25
 
 
26
 
    color: "black"
27
 
 
28
 
    property int columns: desktop.workspaces.columns
29
 
    property int rows: desktop.workspaces.rows
30
 
 
31
 
    property int margin: 35
32
 
    property int spacing: 4
33
 
 
34
 
    /* Effective area available for laying out the workspaces after considering
35
 
       inter-workspace spaces */
36
 
    property int availableWidth: switcher.width - (columns * spacing)
37
 
    property int availableHeight: switcher.height - (rows * spacing)
38
 
 
39
 
    property int maxCellWidth: Math.floor(availableWidth / columns)
40
 
    property int maxCellHeight: Math.floor(availableHeight / rows)
41
 
    /* Depending on the aspect ratio of the final workspaces layout, we will
42
 
       have either vertical or horizontal margins. That is, we will either:
43
 
       - use maxCellWidth as base cell width and compute the height based on the
44
 
         screen ratio, or
45
 
       - use maxCellHeight for the base cell height and compute the width based
46
 
         on the screen ratio.
47
 
       To figure out which way to go, compute the other size and see how things
48
 
       would fit inside the screen.  */
49
 
    property int computedCellHeight: maxCellWidth * switcher.height / switcher.width
50
 
    property int computedCellWidth: maxCellHeight * switcher.width / switcher.height
51
 
 
52
 
    property bool useWidth: (computedCellHeight + spacing) * rows <= switcher.height
53
 
 
54
 
    property int cellWidth: useWidth ? maxCellWidth : computedCellWidth
55
 
    property int cellHeight: useWidth ? computedCellHeight : maxCellHeight
56
 
    property real cellScale: cellWidth / switcher.width
57
 
 
58
 
    /* Scale of a workspace when the user zooms on it (fills most of the switcher, leaving a margin to see
59
 
       the corners of the other workspaces below it) */
60
 
    property bool isDesktopHorizontal: declarativeView.screen.panelsFreeGeometry.width > declarativeView.screen.panelsFreeGeometry.height
61
 
    property real zoomedScale: (isDesktopHorizontal) ? ((width - 2*margin) / switcher.width) :
62
 
                                                       ((height - 2*margin) / switcher.height)
63
 
 
64
 
    /* When this is set, it is used to filter the global list of windows to limit it to
65
 
       a single application. See the SortFilterProxyModel used in Spread.qml */
66
 
    property string applicationFilter
67
 
 
68
 
    /* The number of the currently zoomed workspace (-1 means no workspace)
69
 
       Use workspaceForNumber to find the actual Workspace component. */
70
 
    property int zoomedWorkspace: -1
71
 
 
72
 
    /* This is the master model containing all the windows recognized by bamf for the entire
73
 
       screen. Each workspace will individually filter them to select only those that
74
 
       belong to it. */
75
 
    property variant allWindows: WindowsList { }
76
 
 
77
 
    /* Group all Workspace elements into a single Item to help workspaceByNumber
78
 
       iterate over less items than it would need to if the Repeater was adding children
79
 
       to the switcher itself. */
80
 
    GridView {
81
 
        id: workspaces
82
 
        anchors.centerIn: parent
83
 
 
84
 
        width: cellWidth * columns
85
 
        height: cellHeight * rows
86
 
 
87
 
        model: desktop.workspaces.count
88
 
        cellWidth: parent.cellWidth + spacing
89
 
        cellHeight: parent.cellHeight + spacing
90
 
        keyNavigationWraps: true
91
 
        property string windowFocus
92
 
        Keys.onPressed: {
93
 
            if (event.key == Qt.Key_Left || event.key == Qt.Key_Up) {
94
 
                windowFocus = "last"
95
 
            } else if (event.key == Qt.Key_Right || event.key == Qt.Key_Down) {
96
 
                windowFocus = "first"
97
 
            }
98
 
        }
99
 
 
100
 
        highlight: Rectangle {
101
 
            color: "orange"
102
 
            x: workspaces.currentItem.x
103
 
            y: workspaces.currentItem.y
104
 
            z: -1
105
 
            width: workspaces.cellWidth
106
 
            height: workspaces.cellHeight
107
 
            visible: workspaces.currentItem.state == "unzoomed"
108
 
        }
109
 
        highlightFollowsCurrentItem: false
110
 
 
111
 
        delegate: Workspace {
112
 
            id: workspace
113
 
 
114
 
            property int workspaceNumber: index
115
 
 
116
 
            width: workspaces.cellWidth
117
 
            height: workspaces.cellHeight
118
 
 
119
 
            unzoomedScale:  switcher.cellScale
120
 
 
121
 
            /* Center the workspace in 'zoomed' state */
122
 
            zoomedX: switcher.width * (1 - zoomedScale) / 2
123
 
            zoomedY: switcher.height * (1 - zoomedScale) / 2
124
 
            zoomedScale: switcher.zoomedScale
125
 
 
126
 
            Connections {
127
 
                target: workspaces
128
 
                onCurrentIndexChanged: {
129
 
                    if (workspaces.windowFocus == "first") {
130
 
                        setFocusOnFirstWindow()
131
 
                    } else if (workspaces.windowFocus == "last") {
132
 
                        setFocusOnLastWindow()
133
 
                    }
134
 
                }
135
 
            }
136
 
            state: {
137
 
                if (initial) {
138
 
                    if (desktop.workspaces.current == workspaceNumber) {
139
 
                        return "screen"
140
 
                    } else {
141
 
                        return "unzoomed"
142
 
                    }
143
 
                } else {
144
 
                    if (zoomedWorkspace == workspaceNumber) {
145
 
                        return "zoomed"
146
 
                    } else {
147
 
                        return "unzoomed"
148
 
                    }
149
 
                }
150
 
            }
151
 
 
152
 
            onEntered: {
153
 
                if (zoomedWorkspace == -1) {
154
 
                    workspaces.currentIndex = index
155
 
                }
156
 
            }
157
 
 
158
 
            onClicked: {
159
 
                if (zoomedWorkspace == workspaceNumber) {
160
 
                    activateWorkspace(workspaceNumber)
161
 
                } else if (zoomedWorkspace == -1) {
162
 
                    if (windowCount <= 1) {
163
 
                        activateWorkspace(workspaceNumber)
164
 
                    } else {
165
 
                        workspaces.currentIndex = index
166
 
                        zoomedWorkspace = workspaceNumber
167
 
                    }
168
 
                } else {
169
 
                    workspaces.currentIndex = index
170
 
                    zoomedWorkspace = -1
171
 
                }
172
 
            }
173
 
        }
174
 
 
175
 
        onCurrentIndexChanged: {
176
 
            zoomedWorkspace = -1
177
 
        }
178
 
    }
179
 
 
180
 
    /* FIXME: bad naming. Ideas: screenModeActivated, initialState */
181
 
    property bool initial: true
182
 
 
183
 
    /* This connection receives all commands from the DBUS API */
184
 
    Connections {
185
 
        target: control
186
 
 
187
 
        onShowCurrentWorkspace: {
188
 
            /* Setup application pre-filtering and initially zoomed desktop, if any
189
 
               were specified as arguments */
190
 
            applicationFilter = applicationDesktopFile
191
 
            zoomedWorkspace = desktop.workspaces.current
192
 
            show()
193
 
        }
194
 
 
195
 
        onShowAllWorkspaces: {
196
 
            if (desktop.workspaces.count > 1) {
197
 
                applicationFilter = applicationDesktopFile
198
 
                zoomedWorkspace = -1
199
 
                show()
200
 
            } else {
201
 
                control.showCurrentWorkspace(applicationDesktopFile)
202
 
            }
203
 
        }
204
 
 
205
 
        onHide: cancelAndExit()
206
 
 
207
 
        onFilterByApplication: applicationFilter = applicationDesktopFile
208
 
    }
209
 
 
210
 
    function show() {
211
 
        allWindows.load()
212
 
 
213
 
        spreadView.show()
214
 
        spreadView.forceActivateWindow()
215
 
        workspaces.currentIndex = desktop.workspaces.current
216
 
        /* This is necessary otherwise we don't get keypresses until the user does a
217
 
           mouse over on a window */
218
 
        workspaces.forceActiveFocus()
219
 
        initial = false
220
 
    }
221
 
 
222
 
    /* This controls the exit from the switcher.
223
 
       Note that we can't just hide the workspaces switcher immediately when the user
224
 
       wants to activate a window or cancel the switching process. We first want any
225
 
       transitions to complete, so we need to start this timer, and when it's triggered
226
 
       it will actually do all that is necessary to hide the switcher and cleanup */
227
 
    Timer {
228
 
        id: exitTransitionTimer
229
 
        interval: Utils.transitionDuration
230
 
        onTriggered: {
231
 
            spreadView.hide()
232
 
 
233
 
            /* Nothing should be allowed to touch the windows anymore here, so it should
234
 
               be safe to unload them all to save memory.
235
 
               NOTE: i'm not exactly sure any memory will actually be saved since the biggest
236
 
               usage is the window screenshots, and Qt is caching them (see SpreadWindow.qml
237
 
               for the trick I use to force them to refresh and more info on this cache)
238
 
            */
239
 
            allWindows.unload()
240
 
            zoomedWorkspace = -1
241
 
        }
242
 
    }
243
 
 
244
 
 
245
 
    /* Handle both the ESC keypress and any click on the area outside of the
246
 
       switcher in the same way: maximize the currently active workspace to screen
247
 
       size and hide the switcher (effectively canceling the switching operation).
248
 
       If another workspace was zoomed unzoom it first. */
249
 
    Keys.onPressed: {
250
 
        switch (event.key) {
251
 
        case Qt.Key_Escape:
252
 
            cancelAndExit()
253
 
            event.accepted = true
254
 
            return
255
 
        case Qt.Key_S:
256
 
            if (event.modifiers & Qt.MetaModifier) {
257
 
                cancelAndExit()
258
 
                event.accepted = true
259
 
                return
260
 
            }
261
 
            break
262
 
        }
263
 
    }
264
 
 
265
 
    Connections {
266
 
        target: spreadView
267
 
        onOutsideClick: cancelAndExit()
268
 
    }
269
 
 
270
 
    function cancelAndExit() {
271
 
        initial = true
272
 
 
273
 
        /* Let the transition finish and then hide the switcher and perform cleanup */
274
 
        exitTransitionTimer.start()
275
 
    }
276
 
 
277
 
    function activateWindow(windowInfo) {
278
 
        desktop.workspaces.changeCurrent(zoomedWorkspace)
279
 
        windowInfo.activate()
280
 
        cancelAndExit()
281
 
    }
282
 
 
283
 
    function activateWorkspace(workspaceNumber) {
284
 
        desktop.workspaces.changeCurrent(workspaceNumber)
285
 
        cancelAndExit()
286
 
    }
287
 
}