Compare commits
24 Commits
citadel
...
overview-r
Author | SHA1 | Date | |
---|---|---|---|
|
9efa271888 | ||
|
9ed3ce9006 | ||
|
b400fc2837 | ||
|
a66af6fbac | ||
|
1bbc138ed2 | ||
|
868d4756e4 | ||
|
dfa3be59dc | ||
|
62677336a5 | ||
|
264a82cbfc | ||
|
f8cfd9f903 | ||
|
13f8cd3bcf | ||
|
e1f336374b | ||
|
0ba1387d19 | ||
|
8832ce3a2b | ||
|
91d7a022a9 | ||
|
95d15725fc | ||
|
bb2b7d83af | ||
|
0abac6f67d | ||
|
e00398e2ac | ||
|
0f19492545 | ||
|
9d46a6ceea | ||
|
6432de95cc | ||
|
738fc375c0 | ||
|
4e9a530a64 |
@ -25,6 +25,7 @@ dist_theme_DATA = \
|
|||||||
theme/close-window.svg \
|
theme/close-window.svg \
|
||||||
theme/close.svg \
|
theme/close.svg \
|
||||||
theme/corner-ripple.png \
|
theme/corner-ripple.png \
|
||||||
|
theme/dash-placeholder.svg \
|
||||||
theme/dialog-error.svg \
|
theme/dialog-error.svg \
|
||||||
theme/gnome-shell.css \
|
theme/gnome-shell.css \
|
||||||
theme/mosaic-view-active.svg \
|
theme/mosaic-view-active.svg \
|
||||||
@ -32,6 +33,7 @@ dist_theme_DATA = \
|
|||||||
theme/move-window-on-new.svg \
|
theme/move-window-on-new.svg \
|
||||||
theme/process-working.png \
|
theme/process-working.png \
|
||||||
theme/remove-workspace.svg \
|
theme/remove-workspace.svg \
|
||||||
|
theme/running-indicator.svg \
|
||||||
theme/scroll-button-down-hover.png \
|
theme/scroll-button-down-hover.png \
|
||||||
theme/scroll-button-down.png \
|
theme/scroll-button-down.png \
|
||||||
theme/scroll-button-up-hover.png \
|
theme/scroll-button-up-hover.png \
|
||||||
|
@ -41,18 +41,6 @@
|
|||||||
<default>[]</default>
|
<default>[]</default>
|
||||||
<_summary>History for command (Alt-F2) dialog</_summary>
|
<_summary>History for command (Alt-F2) dialog</_summary>
|
||||||
</key>
|
</key>
|
||||||
<key name="workspaces-view" type="s">
|
|
||||||
<default>'single'</default>
|
|
||||||
<_summary>Overview workspace view mode</_summary>
|
|
||||||
<_description>
|
|
||||||
The selected workspace view mode in the overview.
|
|
||||||
Supported values are "single" and "grid".
|
|
||||||
</_description>
|
|
||||||
<choices>
|
|
||||||
<choice value="single"/>
|
|
||||||
<choice value="grid"/>
|
|
||||||
</choices>
|
|
||||||
</key>
|
|
||||||
<child name="clock" schema="org.gnome.shell.clock"/>
|
<child name="clock" schema="org.gnome.shell.clock"/>
|
||||||
<child name="calendar" schema="org.gnome.shell.calendar"/>
|
<child name="calendar" schema="org.gnome.shell.calendar"/>
|
||||||
<child name="recorder" schema="org.gnome.shell.recorder"/>
|
<child name="recorder" schema="org.gnome.shell.recorder"/>
|
||||||
|
84
data/theme/dash-placeholder.svg
Normal file
84
data/theme/dash-placeholder.svg
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
width="76"
|
||||||
|
height="27"
|
||||||
|
id="svg11252"
|
||||||
|
version="1.1">
|
||||||
|
<defs
|
||||||
|
id="defs11254">
|
||||||
|
<radialGradient
|
||||||
|
xlink:href="#linearGradient39563-4-2"
|
||||||
|
id="radialGradient68155-2-3"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(1,0,0,0.3486842,0,317.8421)"
|
||||||
|
cx="49"
|
||||||
|
cy="488"
|
||||||
|
fx="49"
|
||||||
|
fy="488"
|
||||||
|
r="38" />
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient39563-4-2">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#ffffff;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop39565-1-4" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#ffffff;stop-opacity:0;"
|
||||||
|
offset="1"
|
||||||
|
id="stop39567-7-9" />
|
||||||
|
</linearGradient>
|
||||||
|
<radialGradient
|
||||||
|
xlink:href="#linearGradient39573-6-1"
|
||||||
|
id="radialGradient68157-0-8"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
cx="50.5"
|
||||||
|
cy="487.5"
|
||||||
|
fx="50.5"
|
||||||
|
fy="487.5"
|
||||||
|
r="10.5" />
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient39573-6-1">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#ffffff;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop39575-5-6" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#ffffff;stop-opacity:0;"
|
||||||
|
offset="1"
|
||||||
|
id="stop39577-1-2" />
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<g
|
||||||
|
id="layer1"
|
||||||
|
transform="translate(-337,-518.86218)">
|
||||||
|
<g
|
||||||
|
id="g99967"
|
||||||
|
style="display:inline"
|
||||||
|
transform="translate(326,44.862171)">
|
||||||
|
<rect
|
||||||
|
style="opacity:0.49375;color:#000000;fill:url(#radialGradient68155-2-3);fill-opacity:1;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||||
|
id="rect99969"
|
||||||
|
width="76"
|
||||||
|
height="2"
|
||||||
|
x="11"
|
||||||
|
y="487"
|
||||||
|
rx="0"
|
||||||
|
ry="0" />
|
||||||
|
<path
|
||||||
|
style="opacity:0.43125;color:#000000;fill:url(#radialGradient68157-0-8);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||||
|
id="path99971"
|
||||||
|
d="M 61,487.5 C 61,493.29899 56.29899,498 50.5,498 44.70101,498 40,493.29899 40,487.5 40,481.70101 44.70101,477 50.5,477 c 5.79899,0 10.5,4.70101 10.5,10.5 z"
|
||||||
|
transform="matrix(1.2857143,0,0,1.2857143,-14.428572,-139.28571)" />
|
||||||
|
<path
|
||||||
|
transform="matrix(0.43589747,0,0,0.43589747,28.487179,275)"
|
||||||
|
d="M 61,487.5 C 61,493.29899 56.29899,498 50.5,498 44.70101,498 40,493.29899 40,487.5 40,481.70101 44.70101,477 50.5,477 c 5.79899,0 10.5,4.70101 10.5,10.5 z"
|
||||||
|
id="path99973"
|
||||||
|
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.9 KiB |
@ -257,25 +257,9 @@ StTooltip StLabel {
|
|||||||
|
|
||||||
/* Overview */
|
/* Overview */
|
||||||
|
|
||||||
.overview {
|
#overview {
|
||||||
background-color: #111;
|
spacing: 12px;
|
||||||
}
|
background-color: rgba(0,0,0,0.6);
|
||||||
|
|
||||||
.info-bar {
|
|
||||||
color: #fff;
|
|
||||||
font-size: 14px;
|
|
||||||
spacing: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.info-bar-link-button {
|
|
||||||
background-color: #2d2d2d;
|
|
||||||
padding: 2px 14px;
|
|
||||||
border-radius: 10px;
|
|
||||||
border: 1px solid #181818;
|
|
||||||
}
|
|
||||||
|
|
||||||
.info-bar-link-button:hover {
|
|
||||||
border: 1px solid #666666;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.new-workspace-area {
|
.new-workspace-area {
|
||||||
@ -323,18 +307,17 @@ StTooltip StLabel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.workspaces-bar {
|
.workspaces-bar {
|
||||||
height: 48px;
|
spacing: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.workspaces-bar {
|
.workspace-indicator-panel {
|
||||||
spacing: 5px;
|
spacing: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.workspace-indicator {
|
.workspace-indicator {
|
||||||
width: 24px;
|
width: 24px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
background: rgba(155,155,155,0.8);
|
background: rgba(255,255,255,0.2);
|
||||||
border-spacing: 16px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.workspace-indicator.active {
|
.workspace-indicator.active {
|
||||||
@ -359,44 +342,33 @@ StTooltip StLabel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.single-view-controls {
|
.single-view-controls {
|
||||||
padding: 0px 15px;
|
padding: 8px 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.workspace-controls {
|
.workspace-controls {
|
||||||
width: 24px;
|
width: 48px;
|
||||||
height: 16px;
|
font-size: 32px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #ffffff;
|
||||||
|
border: 2px solid rgba(128, 128, 128, 0.4);
|
||||||
|
border-right: 0px;
|
||||||
|
border-radius: 9px 0px 0px 9px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.workspace-controls.add {
|
.add-workspace {
|
||||||
background-image: url("add-workspace.svg");
|
background-color: rgba(128, 128, 128, 0.4);
|
||||||
}
|
}
|
||||||
|
|
||||||
.workspace-controls.remove {
|
.add-workspace:hover {
|
||||||
background-image: url("remove-workspace.svg");
|
background-color: rgba(128, 128, 128, 0.6);
|
||||||
}
|
}
|
||||||
|
|
||||||
.workspace-controls.switch-single {
|
.remove-workspace {
|
||||||
background-image: url("single-view.svg");
|
height: 48px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.workspace-controls.switch-mosaic {
|
.remove-workspace:hover {
|
||||||
background-image: url("mosaic-view.svg");
|
background-color: rgba(128, 128, 128, 0.2);
|
||||||
}
|
|
||||||
|
|
||||||
.workspace-controls.switch-single:checked {
|
|
||||||
background-image: url("single-view-active.svg");
|
|
||||||
}
|
|
||||||
|
|
||||||
.workspace-controls.switch-mosaic:checked {
|
|
||||||
background-image: url("mosaic-view-active.svg");
|
|
||||||
}
|
|
||||||
|
|
||||||
#SwitchScroll {
|
|
||||||
height: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#SwitchScroll #hhandle {
|
|
||||||
border-radius: 7px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dash */
|
/* Dash */
|
||||||
@ -404,115 +376,111 @@ StTooltip StLabel {
|
|||||||
#dash {
|
#dash {
|
||||||
color: #5f5f5f;
|
color: #5f5f5f;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
padding: 0px 14px;
|
padding: 6px 0px;
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
border: 2px solid rgba(128, 128, 128, 0.4);
|
||||||
|
border-left: 0px;
|
||||||
|
border-radius: 0px 9px 9px 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#dashSections {
|
.dash-placeholder {
|
||||||
spacing: 12px;
|
background-image: url("dash-placeholder.svg");
|
||||||
|
height: 27px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#viewSelector {
|
||||||
|
spacing: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#searchArea {
|
||||||
|
padding: 0px 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#searchEntry {
|
#searchEntry {
|
||||||
padding: 4px;
|
padding: 4px 8px;
|
||||||
border-radius: 4px;
|
border-radius: 12px;
|
||||||
color: #a8a8a8;
|
color: rgb(128, 128, 128);
|
||||||
border: 1px solid #565656;
|
border: 2px solid rgba(128, 128, 128, 0.4);
|
||||||
background-color: #404040;
|
background-gradient-start: rgba(0, 0, 0, 0.2);
|
||||||
caret-color: #fff;
|
background-gradient-end: rgba(128, 128, 128, 0.2);
|
||||||
|
background-gradient-direction: vertical;
|
||||||
|
caret-color: rgb(128, 128, 128);
|
||||||
caret-size: 1px;
|
caret-size: 1px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
|
width: 250px;
|
||||||
transition-duration: 300;
|
transition-duration: 300;
|
||||||
}
|
}
|
||||||
|
|
||||||
#searchEntry:focus {
|
#searchEntry:focus {
|
||||||
color: #545454;
|
border: 2px solid #ffffff;
|
||||||
border: 1px solid #3a3a3a;
|
background-gradient-start: rgba(0, 0, 0, 0.2);
|
||||||
background-color: #e8e8e8;
|
background-gradient-end: #ffffff;
|
||||||
caret-color: #545454;
|
background-gradient-direction: vertical;
|
||||||
|
color: rgb(64, 64, 64);
|
||||||
|
font-weight: bold;
|
||||||
-st-shadow: 0px 0px 6px 2px rgba(255,255,255,0.9);
|
-st-shadow: 0px 0px 6px 2px rgba(255,255,255,0.9);
|
||||||
transition-duration: 0;
|
transition-duration: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#searchEntry:hover {
|
#searchEntry:hover {
|
||||||
color: #a8a8a8;
|
border: 2px solid #e8e8e8;
|
||||||
border: 1px solid #4d4d4d;
|
|
||||||
background-color: #e8e8e8;
|
|
||||||
caret-color: #545454;
|
caret-color: #545454;
|
||||||
transition-duration: 500;
|
transition-duration: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dash-section {
|
.view-tab-title {
|
||||||
|
color: #888a85;
|
||||||
|
font-weight: bold;
|
||||||
|
padding: 0px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.view-tab-title:selected {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.view-tab-boxpointer {
|
||||||
|
-arrow-border-radius: 9px;
|
||||||
|
-arrow-background-color: rgba(0,0,0,0.5);
|
||||||
|
-arrow-border-width: 2px;
|
||||||
|
-arrow-border-color: rgba(255,255,255,0.5);
|
||||||
|
-arrow-base: 30px;
|
||||||
|
-arrow-rise: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#searchResults {
|
||||||
|
padding: 20px 10px 10px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#searchResultsContent {
|
||||||
|
padding: 0 10px;
|
||||||
spacing: 8px;
|
spacing: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.section-header {
|
.search-statustext,
|
||||||
}
|
.search-section-header {
|
||||||
|
padding: 4px 12px;
|
||||||
.section-header-inner {
|
|
||||||
spacing: 4px;
|
spacing: 4px;
|
||||||
|
color: #6f6f6f;
|
||||||
}
|
}
|
||||||
|
|
||||||
.section-text-content {
|
.search-section {
|
||||||
padding: 4px 0px;
|
background-color: rgba(128, 128, 128, .1);
|
||||||
}
|
border: 1px solid rgba(50, 50, 50, .4);
|
||||||
|
|
||||||
.dash-section-content {
|
|
||||||
color: #ffffff;
|
|
||||||
spacing: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.more-link {
|
|
||||||
}
|
|
||||||
|
|
||||||
.more-link-expander {
|
|
||||||
background-image: url("section-more.svg");
|
|
||||||
width: 9px;
|
|
||||||
height: 9px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.more-link-expander.open {
|
|
||||||
background-image: url("section-more-open.svg");
|
|
||||||
width: 9px;
|
|
||||||
height: 9px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dash-pane {
|
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
background-color: #111111;
|
}
|
||||||
border: 2px solid #868686;
|
|
||||||
|
.search-section-results {
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
padding: 30px 10px 10px 20px;
|
border-radius: 10px;
|
||||||
|
border: 1px solid rgba(50, 50, 50, .4);
|
||||||
|
padding: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#dashAppSearchResults {
|
.search-section-list-results {
|
||||||
padding: 8px 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dash-search-statustext,
|
|
||||||
.dash-search-section-header {
|
|
||||||
padding: 4px 0px;
|
|
||||||
spacing: 4px;
|
spacing: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dash-search-section-results {
|
.results-container {
|
||||||
color: #ffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dash-search-section-list-results {
|
|
||||||
spacing: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dash-search-result-content {
|
|
||||||
padding: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dash-search-result-content:selected {
|
|
||||||
padding: 2px;
|
|
||||||
border: 1px solid #5c5c5c;
|
|
||||||
border-radius: 2px;
|
|
||||||
background-color: #1e1e1e;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dash-results-container {
|
|
||||||
spacing: 4px;
|
spacing: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -564,10 +532,7 @@ StTooltip StLabel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.all-app {
|
.all-app {
|
||||||
border-radius: 10px;
|
padding: 10px;
|
||||||
background-color: #111111;
|
|
||||||
border: 2px solid #868686;
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.app-section-divider-container {
|
.app-section-divider-container {
|
||||||
@ -580,46 +545,48 @@ StTooltip StLabel {
|
|||||||
background-image: url("separator-white.png");
|
background-image: url("separator-white.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
.all-app-controls-panel {
|
#dash > .app-well-app {
|
||||||
height: 30px;
|
padding: 6px 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.all-app-scroll-view {
|
.remove-favorite-icon {
|
||||||
padding-right: 10px;
|
color: #a0a0a0;
|
||||||
padding-left: 10px;
|
|
||||||
padding-bottom: 10px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.app-well-app {
|
.remove-favorite-icon:hover {
|
||||||
border: 1px solid #181818;
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-well-app > .overview-icon,
|
||||||
|
.remove-favorite > .overview-icon,
|
||||||
|
.search-result-content > .overview-icon {
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
width: 70px;
|
|
||||||
height: 70px;
|
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
|
color: white;
|
||||||
transition-duration: 100;
|
transition-duration: 100;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.app-well-app.running {
|
.app-well-app.running > .overview-icon {
|
||||||
background-gradient-direction: vertical;
|
text-shadow: black 0px 2px 2px;
|
||||||
background-gradient-start: #3d3d3d;
|
background-image: url("running-indicator.svg");
|
||||||
background-gradient-end: #181818;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.app-well-app.selected {
|
.app-well-app:selected > .overview-icon,
|
||||||
border: 1px solid #666666;
|
.search-result-content:selected > .overview-icon {
|
||||||
|
background: rgba(255,255,255,0.33);
|
||||||
}
|
}
|
||||||
|
|
||||||
.app-well-app:hover {
|
.app-well-app:hover > .overview-icon,
|
||||||
border: 1px solid #666666;
|
.remove-favorite:hover > .overview-icon,
|
||||||
background-gradient-direction: vertical;
|
.search-result-content:hover > .overview-icon {
|
||||||
background-gradient-start: rgba(61,61,61,0.8);
|
background: rgba(255,255,255,0.33);
|
||||||
background-gradient-end: rgba(24,24,24,0.2);
|
text-shadow: black 0px 2px 2px;
|
||||||
transition-duration: 100;
|
transition-duration: 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
.app-well-app:active {
|
.app-well-app:active > .overview-icon {
|
||||||
background-color: #1e1e1e;
|
background-color: #1e1e1e;
|
||||||
border: 1px solid #5f5f5f;
|
border: 1px solid #5f5f5f;
|
||||||
}
|
}
|
||||||
|
89
data/theme/running-indicator.svg
Normal file
89
data/theme/running-indicator.svg
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
width="74.01342"
|
||||||
|
height="74.006706"
|
||||||
|
id="svg7355"
|
||||||
|
version="1.1">
|
||||||
|
<defs
|
||||||
|
id="defs7357">
|
||||||
|
<radialGradient
|
||||||
|
xlink:href="#linearGradient36429"
|
||||||
|
id="radialGradient7461"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(1.0525552,0,0,1.0525552,-2.5162753,-9.0000838)"
|
||||||
|
cx="47.878681"
|
||||||
|
cy="171.25"
|
||||||
|
fx="47.878681"
|
||||||
|
fy="171.25"
|
||||||
|
r="37" />
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient36429">
|
||||||
|
<stop
|
||||||
|
id="stop36431"
|
||||||
|
offset="0"
|
||||||
|
style="stop-color:#ffffff;stop-opacity:1;" />
|
||||||
|
<stop
|
||||||
|
id="stop36433"
|
||||||
|
offset="1"
|
||||||
|
style="stop-color:#ffffff;stop-opacity:0;" />
|
||||||
|
</linearGradient>
|
||||||
|
<radialGradient
|
||||||
|
xlink:href="#linearGradient36471"
|
||||||
|
id="radialGradient7463"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(1.1891549,0,0,0.55513246,-9.281289,36.12653)"
|
||||||
|
cx="49.067139"
|
||||||
|
cy="242.50381"
|
||||||
|
fx="49.067139"
|
||||||
|
fy="242.50381"
|
||||||
|
r="37.00671" />
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient36471">
|
||||||
|
<stop
|
||||||
|
id="stop36473"
|
||||||
|
offset="0"
|
||||||
|
style="stop-color:#ffffff;stop-opacity:1;" />
|
||||||
|
<stop
|
||||||
|
id="stop36475"
|
||||||
|
offset="1"
|
||||||
|
style="stop-color:#ffffff;stop-opacity:0;" />
|
||||||
|
</linearGradient>
|
||||||
|
<radialGradient
|
||||||
|
r="37.00671"
|
||||||
|
fy="242.50381"
|
||||||
|
fx="49.067139"
|
||||||
|
cy="242.50381"
|
||||||
|
cx="49.067139"
|
||||||
|
gradientTransform="matrix(1.1891549,0,0,0.55513246,-9.281289,36.12653)"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
id="radialGradient7488"
|
||||||
|
xlink:href="#linearGradient36471" />
|
||||||
|
</defs>
|
||||||
|
<g
|
||||||
|
id="layer1"
|
||||||
|
transform="translate(-266.21629,-168.11809)">
|
||||||
|
<g
|
||||||
|
style="display:inline"
|
||||||
|
id="g30864"
|
||||||
|
transform="translate(255.223,70.118091)">
|
||||||
|
<rect
|
||||||
|
ry="3.5996203"
|
||||||
|
rx="3.5996203"
|
||||||
|
y="98"
|
||||||
|
x="11"
|
||||||
|
height="74"
|
||||||
|
width="74"
|
||||||
|
id="rect14000"
|
||||||
|
style="opacity:0.371875;fill:url(#radialGradient7461);fill-opacity:1;stroke:none" />
|
||||||
|
<path
|
||||||
|
id="rect34520"
|
||||||
|
d="m 84.506708,167.95508 c 6e-6,1.96759 -1.584022,3.55162 -3.551629,3.55163 l -65.910146,0 c -1.967608,-1e-5 -3.551648,-1.58402 -3.551643,-3.55164"
|
||||||
|
style="opacity:0.2;fill:none;stroke:url(#radialGradient7488);stroke-width:1;stroke-opacity:1" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.6 KiB |
@ -39,6 +39,7 @@ nobase_dist_js_DATA = \
|
|||||||
ui/runDialog.js \
|
ui/runDialog.js \
|
||||||
ui/scripting.js \
|
ui/scripting.js \
|
||||||
ui/search.js \
|
ui/search.js \
|
||||||
|
ui/searchDisplay.js \
|
||||||
ui/shellDBus.js \
|
ui/shellDBus.js \
|
||||||
ui/statusIconDispatcher.js \
|
ui/statusIconDispatcher.js \
|
||||||
ui/statusMenu.js \
|
ui/statusMenu.js \
|
||||||
@ -47,6 +48,7 @@ nobase_dist_js_DATA = \
|
|||||||
ui/status/volume.js \
|
ui/status/volume.js \
|
||||||
ui/telepathyClient.js \
|
ui/telepathyClient.js \
|
||||||
ui/tweener.js \
|
ui/tweener.js \
|
||||||
|
ui/viewSelector.js \
|
||||||
ui/windowAttentionHandler.js \
|
ui/windowAttentionHandler.js \
|
||||||
ui/windowManager.js \
|
ui/windowManager.js \
|
||||||
ui/workspace.js \
|
ui/workspace.js \
|
||||||
|
@ -272,7 +272,9 @@ const ChannelTextIface = {
|
|||||||
],
|
],
|
||||||
signals: [
|
signals: [
|
||||||
{ name: 'Received',
|
{ name: 'Received',
|
||||||
inSignature: 'uuuuus' }
|
inSignature: 'uuuuus' },
|
||||||
|
{ name: 'Sent',
|
||||||
|
inSignature: 'uus' }
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
let ChannelText = DBus.makeProxyClass(ChannelTextIface);
|
let ChannelText = DBus.makeProxyClass(ChannelTextIface);
|
||||||
|
@ -21,8 +21,6 @@ const Tweener = imports.ui.tweener;
|
|||||||
const Workspace = imports.ui.workspace;
|
const Workspace = imports.ui.workspace;
|
||||||
const Params = imports.misc.params;
|
const Params = imports.misc.params;
|
||||||
|
|
||||||
const WELL_MAX_COLUMNS = 16;
|
|
||||||
const WELL_MAX_SEARCH_ROWS = 1;
|
|
||||||
const MENU_POPUP_TIMEOUT = 600;
|
const MENU_POPUP_TIMEOUT = 600;
|
||||||
|
|
||||||
function AlphabeticalView() {
|
function AlphabeticalView() {
|
||||||
@ -148,22 +146,14 @@ AllAppDisplay.prototype = {
|
|||||||
Main.queueDeferredWork(this._workId);
|
Main.queueDeferredWork(this._workId);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let bin = new St.BoxLayout({ style_class: 'all-app-controls-panel',
|
this._scrollView = new St.ScrollView({ x_fill: true,
|
||||||
reactive: true });
|
y_fill: false,
|
||||||
this.actor = new St.BoxLayout({ style_class: 'all-app', vertical: true });
|
vshadows: true });
|
||||||
this.actor.hide();
|
this.actor = new St.Bin({ style_class: 'all-app',
|
||||||
|
y_align: St.Align.START,
|
||||||
let view = new St.ScrollView({ x_fill: true,
|
child: this._scrollView });
|
||||||
y_fill: false,
|
|
||||||
style_class: 'all-app-scroll-view',
|
|
||||||
vshadows: true });
|
|
||||||
this._scrollView = view;
|
|
||||||
this.actor.add(bin);
|
|
||||||
this.actor.add(view, { expand: true, y_fill: false, y_align: St.Align.START });
|
|
||||||
|
|
||||||
this._appView = new ViewByCategories();
|
this._appView = new ViewByCategories();
|
||||||
this._appView.connect('launching', Lang.bind(this, this.close));
|
|
||||||
this._appView.connect('drag-begin', Lang.bind(this, this.close));
|
|
||||||
this._scrollView.add_actor(this._appView.actor);
|
this._scrollView.add_actor(this._appView.actor);
|
||||||
|
|
||||||
this._scrollView.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
|
this._scrollView.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
|
||||||
@ -177,101 +167,10 @@ AllAppDisplay.prototype = {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this._appView.refresh(apps);
|
this._appView.refresh(apps);
|
||||||
},
|
|
||||||
|
|
||||||
toggle: function() {
|
|
||||||
if (this.actor.visible) {
|
|
||||||
Tweener.addTween(this.actor,
|
|
||||||
{ opacity: 0,
|
|
||||||
time: Overview.PANE_FADE_TIME,
|
|
||||||
transition: 'easeOutQuad',
|
|
||||||
onComplete: Lang.bind(this,
|
|
||||||
function() {
|
|
||||||
this.actor.hide();
|
|
||||||
this.emit('open-state-changed',
|
|
||||||
this.actor.visible);
|
|
||||||
})
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.actor.show();
|
|
||||||
this.emit('open-state-changed', this.actor.visible);
|
|
||||||
this.actor.opacity = 0;
|
|
||||||
Tweener.addTween(this.actor,
|
|
||||||
{ opacity: 255,
|
|
||||||
time: Overview.PANE_FADE_TIME,
|
|
||||||
transition: 'easeOutQuad'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
close: function() {
|
|
||||||
if (!this.actor.visible)
|
|
||||||
return;
|
|
||||||
this.toggle();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Signals.addSignalMethods(AllAppDisplay.prototype);
|
Signals.addSignalMethods(AllAppDisplay.prototype);
|
||||||
|
|
||||||
function AppSearchResultDisplay(provider) {
|
|
||||||
this._init(provider);
|
|
||||||
}
|
|
||||||
|
|
||||||
AppSearchResultDisplay.prototype = {
|
|
||||||
__proto__: Search.SearchResultDisplay.prototype,
|
|
||||||
|
|
||||||
_init: function (provider) {
|
|
||||||
Search.SearchResultDisplay.prototype._init.call(this, provider);
|
|
||||||
this._grid = new IconGrid.IconGrid({ rowLimit: WELL_MAX_SEARCH_ROWS });
|
|
||||||
this.actor = new St.Bin({ name: 'dashAppSearchResults',
|
|
||||||
x_align: St.Align.START });
|
|
||||||
this.actor.set_child(this._grid.actor);
|
|
||||||
},
|
|
||||||
|
|
||||||
renderResults: function(results, terms) {
|
|
||||||
let appSys = Shell.AppSystem.get_default();
|
|
||||||
let maxItems = WELL_MAX_SEARCH_ROWS * WELL_MAX_COLUMNS;
|
|
||||||
for (let i = 0; i < results.length && i < maxItems; i++) {
|
|
||||||
let result = results[i];
|
|
||||||
let app = appSys.get_app(result);
|
|
||||||
let display = new AppWellIcon(app);
|
|
||||||
this._grid.addItem(display.actor);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
clear: function () {
|
|
||||||
this._grid.removeAll();
|
|
||||||
this.selectionIndex = -1;
|
|
||||||
},
|
|
||||||
|
|
||||||
getVisibleResultCount: function() {
|
|
||||||
return this._grid.visibleItemsCount();
|
|
||||||
},
|
|
||||||
|
|
||||||
selectIndex: function (index) {
|
|
||||||
let nVisible = this.getVisibleResultCount();
|
|
||||||
if (this.selectionIndex >= 0) {
|
|
||||||
let prevActor = this._grid.getItemAtIndex(this.selectionIndex);
|
|
||||||
prevActor._delegate.setSelected(false);
|
|
||||||
}
|
|
||||||
this.selectionIndex = -1;
|
|
||||||
if (index >= nVisible)
|
|
||||||
return false;
|
|
||||||
else if (index < 0)
|
|
||||||
return false;
|
|
||||||
let targetActor = this._grid.getItemAtIndex(index);
|
|
||||||
targetActor._delegate.setSelected(true);
|
|
||||||
this.selectionIndex = index;
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
activateSelected: function() {
|
|
||||||
if (this.selectionIndex < 0)
|
|
||||||
return;
|
|
||||||
let targetActor = this._grid.getItemAtIndex(this.selectionIndex);
|
|
||||||
this.provider.activateResult(targetActor._delegate.app.get_id());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function BaseAppSearchProvider() {
|
function BaseAppSearchProvider() {
|
||||||
this._init();
|
this._init();
|
||||||
@ -324,12 +223,10 @@ AppSearchProvider.prototype = {
|
|||||||
return this._appSys.subsearch(false, previousResults, terms);
|
return this._appSys.subsearch(false, previousResults, terms);
|
||||||
},
|
},
|
||||||
|
|
||||||
createResultContainerActor: function () {
|
|
||||||
return new AppSearchResultDisplay(this);
|
|
||||||
},
|
|
||||||
|
|
||||||
createResultActor: function (resultMeta, terms) {
|
createResultActor: function (resultMeta, terms) {
|
||||||
return new AppIcon(resultMeta.id);
|
let app = this._appSys.get_app(resultMeta['id']);
|
||||||
|
let icon = new AppWellIcon(app);
|
||||||
|
return icon.actor;
|
||||||
},
|
},
|
||||||
|
|
||||||
expandSearch: function(terms) {
|
expandSearch: function(terms) {
|
||||||
@ -375,7 +272,9 @@ AppIcon.prototype = {
|
|||||||
|
|
||||||
let label = this.app.get_name();
|
let label = this.app.get_name();
|
||||||
|
|
||||||
IconGrid.BaseIcon.prototype._init.call(this, label);
|
IconGrid.BaseIcon.prototype._init.call(this,
|
||||||
|
label,
|
||||||
|
{ setSizeManually: true });
|
||||||
},
|
},
|
||||||
|
|
||||||
createIcon: function(iconSize) {
|
createIcon: function(iconSize) {
|
||||||
@ -396,8 +295,8 @@ AppWellIcon.prototype = {
|
|||||||
y_fill: true });
|
y_fill: true });
|
||||||
this.actor._delegate = this;
|
this.actor._delegate = this;
|
||||||
|
|
||||||
this._icon = new AppIcon(app);
|
this.icon = new AppIcon(app);
|
||||||
this.actor.set_child(this._icon.actor);
|
this.actor.set_child(this.icon.actor);
|
||||||
|
|
||||||
this.actor.connect('clicked', Lang.bind(this, this._onClicked));
|
this.actor.connect('clicked', Lang.bind(this, this._onClicked));
|
||||||
|
|
||||||
@ -526,14 +425,6 @@ AppWellIcon.prototype = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
setSelected: function (isSelected) {
|
|
||||||
this._selected = isSelected;
|
|
||||||
if (this._selected)
|
|
||||||
this.actor.add_style_class_name('selected');
|
|
||||||
else
|
|
||||||
this.actor.remove_style_class_name('selected');
|
|
||||||
},
|
|
||||||
|
|
||||||
_onMenuPoppedUp: function() {
|
_onMenuPoppedUp: function() {
|
||||||
if (this._getRunning()) {
|
if (this._getRunning()) {
|
||||||
Main.overview.getWorkspacesForWindow(null).setApplicationWindowSelection(this.app.get_id());
|
Main.overview.getWorkspacesForWindow(null).setApplicationWindowSelection(this.app.get_id());
|
||||||
@ -581,13 +472,13 @@ AppWellIcon.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
getDragActor: function() {
|
getDragActor: function() {
|
||||||
return this.app.create_icon_texture(this._icon.iconSize);
|
return this.app.create_icon_texture(this.icon.iconSize);
|
||||||
},
|
},
|
||||||
|
|
||||||
// Returns the original actor that should align with the actor
|
// Returns the original actor that should align with the actor
|
||||||
// we show as the item is being dragged.
|
// we show as the item is being dragged.
|
||||||
getDragActorSource: function() {
|
getDragActorSource: function() {
|
||||||
return this._icon.icon;
|
return this.icon.icon;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Signals.addSignalMethods(AppWellIcon.prototype);
|
Signals.addSignalMethods(AppWellIcon.prototype);
|
||||||
@ -756,135 +647,3 @@ AppIconMenu.prototype = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
Signals.addSignalMethods(AppIconMenu.prototype);
|
Signals.addSignalMethods(AppIconMenu.prototype);
|
||||||
|
|
||||||
function AppWell() {
|
|
||||||
this._init();
|
|
||||||
}
|
|
||||||
|
|
||||||
AppWell.prototype = {
|
|
||||||
_init : function() {
|
|
||||||
this._placeholderText = null;
|
|
||||||
this._menus = [];
|
|
||||||
this._menuDisplays = [];
|
|
||||||
|
|
||||||
this._favorites = [];
|
|
||||||
|
|
||||||
this._grid = new IconGrid.IconGrid();
|
|
||||||
this.actor = this._grid.actor;
|
|
||||||
this.actor._delegate = this;
|
|
||||||
|
|
||||||
this._workId = Main.initializeDeferredWork(this.actor, Lang.bind(this, this._redisplay));
|
|
||||||
|
|
||||||
this._tracker = Shell.WindowTracker.get_default();
|
|
||||||
this._appSystem = Shell.AppSystem.get_default();
|
|
||||||
|
|
||||||
this._appSystem.connect('installed-changed', Lang.bind(this, this._queueRedisplay));
|
|
||||||
AppFavorites.getAppFavorites().connect('changed', Lang.bind(this, this._queueRedisplay));
|
|
||||||
this._tracker.connect('app-state-changed', Lang.bind(this, this._queueRedisplay));
|
|
||||||
},
|
|
||||||
|
|
||||||
_appIdListToHash: function(apps) {
|
|
||||||
let ids = {};
|
|
||||||
for (let i = 0; i < apps.length; i++)
|
|
||||||
ids[apps[i].get_id()] = apps[i];
|
|
||||||
return ids;
|
|
||||||
},
|
|
||||||
|
|
||||||
_queueRedisplay: function () {
|
|
||||||
Main.queueDeferredWork(this._workId);
|
|
||||||
},
|
|
||||||
|
|
||||||
_redisplay: function () {
|
|
||||||
this._grid.removeAll();
|
|
||||||
|
|
||||||
let favorites = AppFavorites.getAppFavorites().getFavoriteMap();
|
|
||||||
|
|
||||||
/* hardcode here pending some design about how exactly desktop contexts behave */
|
|
||||||
let contextId = '';
|
|
||||||
|
|
||||||
let running = this._tracker.get_running_apps(contextId);
|
|
||||||
let runningIds = this._appIdListToHash(running);
|
|
||||||
|
|
||||||
let nFavorites = 0;
|
|
||||||
for (let id in favorites) {
|
|
||||||
let app = favorites[id];
|
|
||||||
let display = new AppWellIcon(app);
|
|
||||||
this._grid.addItem(display.actor);
|
|
||||||
nFavorites++;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < running.length; i++) {
|
|
||||||
let app = running[i];
|
|
||||||
if (app.get_id() in favorites)
|
|
||||||
continue;
|
|
||||||
let display = new AppWellIcon(app);
|
|
||||||
this._grid.addItem(display.actor);
|
|
||||||
}
|
|
||||||
if (this._placeholderText) {
|
|
||||||
this._placeholderText.destroy();
|
|
||||||
this._placeholderText = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (running.length == 0 && nFavorites == 0) {
|
|
||||||
this._placeholderText = new St.Label({ text: _("Drag here to add favorites") });
|
|
||||||
this.actor.add_actor(this._placeholderText);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
handleDragOver : function(source, actor, x, y, time) {
|
|
||||||
let app = null;
|
|
||||||
if (source instanceof AppWellIcon)
|
|
||||||
app = this._appSystem.get_app(source.getId());
|
|
||||||
else if (source instanceof Workspace.WindowClone)
|
|
||||||
app = this._tracker.get_window_app(source.metaWindow);
|
|
||||||
|
|
||||||
// Don't allow favoriting of transient apps
|
|
||||||
if (app == null || app.is_transient())
|
|
||||||
return DND.DragMotionResult.NO_DROP;
|
|
||||||
|
|
||||||
let id = app.get_id();
|
|
||||||
|
|
||||||
let favorites = AppFavorites.getAppFavorites().getFavoriteMap();
|
|
||||||
|
|
||||||
let srcIsFavorite = (id in favorites);
|
|
||||||
|
|
||||||
if (srcIsFavorite)
|
|
||||||
return DND.DragMotionResult.NO_DROP;
|
|
||||||
|
|
||||||
return DND.DragMotionResult.COPY_DROP;
|
|
||||||
},
|
|
||||||
|
|
||||||
// Draggable target interface
|
|
||||||
acceptDrop : function(source, actor, x, y, time) {
|
|
||||||
let app = null;
|
|
||||||
if (source instanceof AppWellIcon) {
|
|
||||||
app = this._appSystem.get_app(source.getId());
|
|
||||||
} else if (source instanceof Workspace.WindowClone) {
|
|
||||||
app = this._tracker.get_window_app(source.metaWindow);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't allow favoriting of transient apps
|
|
||||||
if (app == null || app.is_transient()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
let id = app.get_id();
|
|
||||||
|
|
||||||
let favorites = AppFavorites.getAppFavorites().getFavoriteMap();
|
|
||||||
|
|
||||||
let srcIsFavorite = (id in favorites);
|
|
||||||
|
|
||||||
if (srcIsFavorite) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
Mainloop.idle_add(Lang.bind(this, function () {
|
|
||||||
AppFavorites.getAppFavorites().addFavorite(id);
|
|
||||||
return false;
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Signals.addSignalMethods(AppWell.prototype);
|
|
||||||
|
@ -63,7 +63,7 @@ AppFavorites.prototype = {
|
|||||||
return appId in this._favorites;
|
return appId in this._favorites;
|
||||||
},
|
},
|
||||||
|
|
||||||
_addFavorite: function(appId) {
|
_addFavorite: function(appId, pos) {
|
||||||
if (appId in this._favorites)
|
if (appId in this._favorites)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -73,23 +73,35 @@ AppFavorites.prototype = {
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
let ids = this._getIds();
|
let ids = this._getIds();
|
||||||
ids.push(appId);
|
if (pos == -1)
|
||||||
|
ids.push(appId);
|
||||||
|
else
|
||||||
|
ids.splice(pos, 0, appId);
|
||||||
global.settings.set_strv(this.FAVORITE_APPS_KEY, ids);
|
global.settings.set_strv(this.FAVORITE_APPS_KEY, ids);
|
||||||
this._favorites[appId] = app;
|
this._favorites[appId] = app;
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
addFavorite: function(appId) {
|
addFavoriteAtPos: function(appId, pos) {
|
||||||
if (!this._addFavorite(appId))
|
if (!this._addFavorite(appId, pos))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
let app = Shell.AppSystem.get_default().get_app(appId);
|
let app = Shell.AppSystem.get_default().get_app(appId);
|
||||||
|
|
||||||
Main.overview.infoBar.setMessage(_("%s has been added to your favorites.").format(app.get_name()), Lang.bind(this, function () {
|
Main.overview.shellInfo.setMessage(_("%s has been added to your favorites.").format(app.get_name()), Lang.bind(this, function () {
|
||||||
this._removeFavorite(appId);
|
this._removeFavorite(appId);
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
addFavorite: function(appId) {
|
||||||
|
this.addFavoriteAtPos(appId, -1);
|
||||||
|
},
|
||||||
|
|
||||||
|
moveFavoriteToPos: function(appId, pos) {
|
||||||
|
this._removeFavorite(appId);
|
||||||
|
this._addFavorite(appId, pos);
|
||||||
|
},
|
||||||
|
|
||||||
_removeFavorite: function(appId) {
|
_removeFavorite: function(appId) {
|
||||||
if (!appId in this._favorites)
|
if (!appId in this._favorites)
|
||||||
return false;
|
return false;
|
||||||
@ -100,13 +112,16 @@ AppFavorites.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
removeFavorite: function(appId) {
|
removeFavorite: function(appId) {
|
||||||
|
let ids = this._getIds();
|
||||||
|
let pos = ids.indexOf(appId);
|
||||||
|
|
||||||
let app = this._favorites[appId];
|
let app = this._favorites[appId];
|
||||||
if (!this._removeFavorite(appId))
|
if (!this._removeFavorite(appId))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Main.overview.infoBar.setMessage(_("%s has been removed from your favorites.").format(app.get_name()),
|
Main.overview.shellInfo.setMessage(_("%s has been removed from your favorites.").format(app.get_name()),
|
||||||
Lang.bind(this, function () {
|
Lang.bind(this, function () {
|
||||||
this._addFavorite(appId);
|
this._addFavorite(appId, pos);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
1148
js/ui/dash.js
1148
js/ui/dash.js
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,7 @@
|
|||||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
const Clutter = imports.gi.Clutter;
|
const Clutter = imports.gi.Clutter;
|
||||||
|
const Meta = imports.gi.Meta;
|
||||||
const Mainloop = imports.mainloop;
|
const Mainloop = imports.mainloop;
|
||||||
const Signals = imports.signals;
|
const Signals = imports.signals;
|
||||||
const Lang = imports.lang;
|
const Lang = imports.lang;
|
||||||
@ -8,104 +9,60 @@ const St = imports.gi.St;
|
|||||||
const Gettext = imports.gettext.domain('gnome-shell');
|
const Gettext = imports.gettext.domain('gnome-shell');
|
||||||
const _ = Gettext.gettext;
|
const _ = Gettext.gettext;
|
||||||
|
|
||||||
|
const AppDisplay = imports.ui.appDisplay;
|
||||||
|
const Dash = imports.ui.dash;
|
||||||
|
const DocDisplay = imports.ui.docDisplay;
|
||||||
const GenericDisplay = imports.ui.genericDisplay;
|
const GenericDisplay = imports.ui.genericDisplay;
|
||||||
const Lightbox = imports.ui.lightbox;
|
const Lightbox = imports.ui.lightbox;
|
||||||
const Main = imports.ui.main;
|
const Main = imports.ui.main;
|
||||||
|
const MessageTray = imports.ui.messageTray;
|
||||||
const Panel = imports.ui.panel;
|
const Panel = imports.ui.panel;
|
||||||
const Dash = imports.ui.dash;
|
const PlaceDisplay = imports.ui.placeDisplay;
|
||||||
const Tweener = imports.ui.tweener;
|
const Tweener = imports.ui.tweener;
|
||||||
|
const ViewSelector = imports.ui.viewSelector;
|
||||||
const WorkspacesView = imports.ui.workspacesView;
|
const WorkspacesView = imports.ui.workspacesView;
|
||||||
|
|
||||||
// Time for initial animation going into Overview mode
|
// Time for initial animation going into Overview mode
|
||||||
const ANIMATION_TIME = 0.25;
|
const ANIMATION_TIME = 0.25;
|
||||||
|
|
||||||
// Time for pane menus to fade in/out
|
// We split the screen vertically between the dash and the view selector.
|
||||||
const PANE_FADE_TIME = 0.1;
|
const DASH_SPLIT_FRACTION = 0.1;
|
||||||
|
|
||||||
// We divide the screen into a grid of rows and columns, which we use
|
const SHELL_INFO_HIDE_TIMEOUT = 10;
|
||||||
// to help us position the Overview components, such as the side panel
|
|
||||||
// that lists applications and documents, the workspaces display, and
|
|
||||||
// the button for adding additional workspaces.
|
|
||||||
// In the regular mode, the side panel takes up one column on the left,
|
|
||||||
// and the workspaces display takes up the remaining columns.
|
|
||||||
// In the expanded side panel display mode, the side panel takes up two
|
|
||||||
// columns, and the workspaces display slides all the way to the right,
|
|
||||||
// being visible only in the last quarter of the right-most column.
|
|
||||||
// In the future, this mode will have more components, such as a display
|
|
||||||
// of documents which were recently opened with a given application, which
|
|
||||||
// will take up the remaining sections of the display.
|
|
||||||
|
|
||||||
const WIDE_SCREEN_CUT_OFF_RATIO = 1.4;
|
function Source() {
|
||||||
// A common netbook resolution is 1024x600, which trips the widescreen
|
|
||||||
// ratio. However that leaves way too few pixels for the dash. So
|
|
||||||
// just treat this as a regular screen.
|
|
||||||
const WIDE_SCREEN_MINIMUM_HEIGHT = 768;
|
|
||||||
|
|
||||||
const COLUMNS_REGULAR_SCREEN = 4;
|
|
||||||
const ROWS_REGULAR_SCREEN = 8;
|
|
||||||
const COLUMNS_WIDE_SCREEN = 5;
|
|
||||||
const ROWS_WIDE_SCREEN = 10;
|
|
||||||
|
|
||||||
const DEFAULT_PADDING = 4;
|
|
||||||
|
|
||||||
// Padding around workspace grid / Spacing between Dash and Workspaces
|
|
||||||
const WORKSPACE_GRID_PADDING = 12;
|
|
||||||
|
|
||||||
const COLUMNS_FOR_WORKSPACES_REGULAR_SCREEN = 3;
|
|
||||||
const ROWS_FOR_WORKSPACES_REGULAR_SCREEN = 6;
|
|
||||||
|
|
||||||
const COLUMNS_FOR_WORKSPACES_WIDE_SCREEN = 4;
|
|
||||||
const ROWS_FOR_WORKSPACES_WIDE_SCREEN = 8;
|
|
||||||
|
|
||||||
// A multi-state; PENDING is used during animations
|
|
||||||
const STATE_ACTIVE = true;
|
|
||||||
const STATE_PENDING_INACTIVE = false;
|
|
||||||
const STATE_INACTIVE = false;
|
|
||||||
|
|
||||||
const SHADOW_COLOR = new Clutter.Color();
|
|
||||||
SHADOW_COLOR.from_pixel(0x00000033);
|
|
||||||
const TRANSPARENT_COLOR = new Clutter.Color();
|
|
||||||
TRANSPARENT_COLOR.from_pixel(0x00000000);
|
|
||||||
|
|
||||||
const SHADOW_WIDTH = 6;
|
|
||||||
|
|
||||||
const NUMBER_OF_SECTIONS_IN_SEARCH = 2;
|
|
||||||
|
|
||||||
const INFO_BAR_HIDE_TIMEOUT = 10;
|
|
||||||
|
|
||||||
let wideScreen = false;
|
|
||||||
let displayGridColumnWidth = null;
|
|
||||||
let displayGridRowHeight = null;
|
|
||||||
|
|
||||||
function InfoBar() {
|
|
||||||
this._init();
|
this._init();
|
||||||
}
|
}
|
||||||
|
|
||||||
InfoBar.prototype = {
|
Source.prototype = {
|
||||||
|
__proto__: MessageTray.Source.prototype,
|
||||||
|
|
||||||
_init: function() {
|
_init: function() {
|
||||||
this.actor = new St.Bin({ style_class: 'info-bar-panel',
|
MessageTray.Source.prototype._init.call(this,
|
||||||
x_fill: true,
|
"System Information");
|
||||||
y_fill: false });
|
this._setSummaryIcon(this.createNotificationIcon());
|
||||||
this._label = new St.Label();
|
},
|
||||||
this._undo = new St.Button({ style_class: 'info-bar-link-button' });
|
|
||||||
|
|
||||||
let bin = new St.Bin({ x_fill: false,
|
createNotificationIcon: function() {
|
||||||
y_fill: false,
|
return new St.Icon({ icon_name: 'info',
|
||||||
x_align: St.Align.MIDDLE,
|
icon_type: St.IconType.FULLCOLOR,
|
||||||
y_align: St.Align.MIDDLE });
|
icon_size: this.ICON_SIZE });
|
||||||
this.actor.set_child(bin);
|
},
|
||||||
|
|
||||||
let box = new St.BoxLayout({ style_class: 'info-bar' });
|
_notificationClicked: function() {
|
||||||
bin.set_child(box);
|
this.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function ShellInfo() {
|
||||||
|
this._init();
|
||||||
|
}
|
||||||
|
|
||||||
|
ShellInfo.prototype = {
|
||||||
|
_init: function() {
|
||||||
|
this._source = null;
|
||||||
this._timeoutId = 0;
|
this._timeoutId = 0;
|
||||||
|
|
||||||
box.add(this._label, {'y-fill' : false, 'y-align' : St.Align.MIDDLE});
|
|
||||||
box.add(this._undo);
|
|
||||||
|
|
||||||
this.actor.set_opacity(0);
|
|
||||||
|
|
||||||
this._undoCallback = null;
|
this._undoCallback = null;
|
||||||
this._undo.connect('clicked', Lang.bind(this, this._onUndoClicked));
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_onUndoClicked: function() {
|
_onUndoClicked: function() {
|
||||||
@ -114,27 +71,16 @@ InfoBar.prototype = {
|
|||||||
|
|
||||||
if (this._undoCallback)
|
if (this._undoCallback)
|
||||||
this._undoCallback();
|
this._undoCallback();
|
||||||
this.actor.set_opacity(0);
|
|
||||||
this._undoCallback = null;
|
this._undoCallback = null;
|
||||||
},
|
|
||||||
|
|
||||||
_hideDone: function() {
|
if (this._source)
|
||||||
this._undoCallback = null;
|
this._source.destroy();
|
||||||
},
|
|
||||||
|
|
||||||
_hide: function() {
|
|
||||||
Tweener.addTween(this.actor,
|
|
||||||
{ opacity: 0,
|
|
||||||
transition: 'easeOutQuad',
|
|
||||||
time: ANIMATION_TIME,
|
|
||||||
onComplete: this._hideDone,
|
|
||||||
onCompleteScope: this
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_onTimeout: function() {
|
_onTimeout: function() {
|
||||||
this._timeoutId = 0;
|
this._timeoutId = 0;
|
||||||
this._hide();
|
if (this._source)
|
||||||
|
this._source.destroy();
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -142,28 +88,33 @@ InfoBar.prototype = {
|
|||||||
if (this._timeoutId)
|
if (this._timeoutId)
|
||||||
Mainloop.source_remove(this._timeoutId);
|
Mainloop.source_remove(this._timeoutId);
|
||||||
|
|
||||||
this._timeout = false;
|
this._timeoutId = Mainloop.timeout_add_seconds(SHELL_INFO_HIDE_TIMEOUT,
|
||||||
|
Lang.bind(this, this._onTimeout));
|
||||||
|
|
||||||
this._label.text = text;
|
if (this._source == null) {
|
||||||
|
this._source = new Source();
|
||||||
|
this._source.connect('destroy', Lang.bind(this,
|
||||||
|
function() {
|
||||||
|
this._source = null;
|
||||||
|
}));
|
||||||
|
Main.messageTray.add(this._source);
|
||||||
|
}
|
||||||
|
|
||||||
Tweener.addTween(this.actor,
|
let notification = this._source.notification;
|
||||||
{ opacity: 255,
|
if (notification == null)
|
||||||
transition: 'easeOutQuad',
|
notification = new MessageTray.Notification(this._source, text, null);
|
||||||
time: ANIMATION_TIME
|
|
||||||
});
|
|
||||||
|
|
||||||
this._timeoutId = Mainloop.timeout_add_seconds(INFO_BAR_HIDE_TIMEOUT, Lang.bind(this, this._onTimeout));
|
|
||||||
|
|
||||||
if (undoLabel)
|
|
||||||
this._undo.label = undoLabel;
|
|
||||||
else
|
else
|
||||||
this._undo.label = _("Undo");
|
notification.update(text, null, { clear: true });
|
||||||
|
|
||||||
this._undoCallback = undoCallback;
|
this._undoCallback = undoCallback;
|
||||||
if (undoCallback)
|
if (undoCallback) {
|
||||||
this._undo.show();
|
notification.addButton('system-undo',
|
||||||
else
|
undoLabel ? undoLabel : _("Undo"));
|
||||||
this._undo.hide();
|
notification.connect('action-invoked',
|
||||||
|
Lang.bind(this, this._onUndoClicked));
|
||||||
|
}
|
||||||
|
|
||||||
|
this._source.notify(notification);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -173,30 +124,37 @@ function Overview() {
|
|||||||
|
|
||||||
Overview.prototype = {
|
Overview.prototype = {
|
||||||
_init : function() {
|
_init : function() {
|
||||||
this._group = new St.Group({ style_class: 'overview' });
|
this._desktopFade = new St.Bin();
|
||||||
|
global.overlay_group.add_actor(this._desktopFade);
|
||||||
|
|
||||||
|
// The actual global.background_actor is inside global.window_group,
|
||||||
|
// which is hidden when displaying the overview, so we display a clone.
|
||||||
|
this._background = new Clutter.Clone({ source: global.background_actor });
|
||||||
|
this._background.hide();
|
||||||
|
global.overlay_group.add_actor(this._background);
|
||||||
|
|
||||||
|
this._spacing = 0;
|
||||||
|
|
||||||
|
this._group = new St.Group({ name: 'overview' });
|
||||||
this._group._delegate = this;
|
this._group._delegate = this;
|
||||||
this._group.connect('destroy', Lang.bind(this,
|
this._group.connect('style-changed',
|
||||||
function() {
|
Lang.bind(this, function() {
|
||||||
if (this._lightbox) {
|
let node = this._group.get_theme_node();
|
||||||
this._lightbox.destroy();
|
let spacing = node.get_length('spacing');
|
||||||
this._lightbox = null;
|
if (spacing != this._spacing) {
|
||||||
|
this._spacing = spacing;
|
||||||
|
this.relayout();
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
this.infoBar = new InfoBar();
|
this.shellInfo = new ShellInfo();
|
||||||
this._group.add_actor(this.infoBar.actor);
|
|
||||||
|
|
||||||
this._workspacesManager = null;
|
this._workspacesDisplay = null;
|
||||||
this._lightbox = null;
|
|
||||||
|
|
||||||
this.visible = false;
|
this.visible = false;
|
||||||
this.animationInProgress = false;
|
this.animationInProgress = false;
|
||||||
this._hideInProgress = false;
|
this._hideInProgress = false;
|
||||||
|
|
||||||
this._recalculateGridSizes();
|
|
||||||
|
|
||||||
this._activeDisplayPane = null;
|
|
||||||
|
|
||||||
// During transitions, we raise this to the top to avoid having the overview
|
// During transitions, we raise this to the top to avoid having the overview
|
||||||
// area be reactive; it causes too many issues such as double clicks on
|
// area be reactive; it causes too many issues such as double clicks on
|
||||||
// Dash elements, or mouseover handlers in the workspaces.
|
// Dash elements, or mouseover handlers in the workspaces.
|
||||||
@ -205,196 +163,87 @@ Overview.prototype = {
|
|||||||
this._group.add_actor(this._coverPane);
|
this._group.add_actor(this._coverPane);
|
||||||
this._coverPane.connect('event', Lang.bind(this, function (actor, event) { return true; }));
|
this._coverPane.connect('event', Lang.bind(this, function (actor, event) { return true; }));
|
||||||
|
|
||||||
// Similar to the cover pane but used for dialogs ("panes"); see the comments
|
|
||||||
// in addPane below.
|
|
||||||
this._transparentBackground = new Clutter.Rectangle({ opacity: 0,
|
|
||||||
reactive: true });
|
|
||||||
this._group.add_actor(this._transparentBackground);
|
|
||||||
|
|
||||||
// Background color for the Overview
|
|
||||||
this._backOver = new St.Label();
|
|
||||||
this._group.add_actor(this._backOver);
|
|
||||||
|
|
||||||
this._group.hide();
|
this._group.hide();
|
||||||
global.overlay_group.add_actor(this._group);
|
global.overlay_group.add_actor(this._group);
|
||||||
|
|
||||||
|
this.viewSelector = new ViewSelector.ViewSelector();
|
||||||
|
this._group.add_actor(this.viewSelector.actor);
|
||||||
|
|
||||||
|
this._workspacesDisplay = new WorkspacesView.WorkspacesDisplay();
|
||||||
|
this.viewSelector.addViewTab("Windows", this._workspacesDisplay.actor);
|
||||||
|
|
||||||
|
let appView = new AppDisplay.AllAppDisplay();
|
||||||
|
this.viewSelector.addViewTab("Applications", appView.actor);
|
||||||
|
|
||||||
|
// Default search providers
|
||||||
|
this.viewSelector.addSearchProvider(new AppDisplay.AppSearchProvider());
|
||||||
|
this.viewSelector.addSearchProvider(new AppDisplay.PrefsSearchProvider());
|
||||||
|
this.viewSelector.addSearchProvider(new PlaceDisplay.PlaceSearchProvider());
|
||||||
|
this.viewSelector.addSearchProvider(new DocDisplay.DocSearchProvider());
|
||||||
|
this.viewSelector.addSearchProvider(new WorkspacesView.WindowSearchProvider());
|
||||||
|
|
||||||
// TODO - recalculate everything when desktop size changes
|
// TODO - recalculate everything when desktop size changes
|
||||||
this._dash = new Dash.Dash();
|
this._dash = new Dash.Dash();
|
||||||
this._group.add_actor(this._dash.actor);
|
this._group.add_actor(this._dash.actor);
|
||||||
|
this._dash.actor.add_constraint(this.viewSelector.constrainY);
|
||||||
// Container to hold popup pane chrome.
|
this._dash.actor.add_constraint(this.viewSelector.constrainHeight);
|
||||||
this._paneContainer = new St.BoxLayout({ style_class: 'overview-pane' });
|
|
||||||
// Note here we explicitly don't set the paneContainer to be reactive yet; that's done
|
|
||||||
// inside the notify::visible handler on panes.
|
|
||||||
this._paneContainer.connect('button-release-event', Lang.bind(this, function(background) {
|
|
||||||
this._activeDisplayPane.close();
|
|
||||||
return true;
|
|
||||||
}));
|
|
||||||
this._group.add_actor(this._paneContainer);
|
|
||||||
|
|
||||||
this._transparentBackground.lower_bottom();
|
|
||||||
this._paneContainer.hide();
|
|
||||||
|
|
||||||
this._coverPane.lower_bottom();
|
this._coverPane.lower_bottom();
|
||||||
|
|
||||||
this.workspaces = null;
|
this.workspaces = null;
|
||||||
},
|
},
|
||||||
|
|
||||||
_onViewChanged: function() {
|
_getDesktopClone: function() {
|
||||||
if (!this.visible)
|
let windows = global.get_window_actors().filter(function(w) {
|
||||||
return;
|
return w.meta_window.get_window_type() == Meta.WindowType.DESKTOP;
|
||||||
|
});
|
||||||
|
if (windows.length == 0)
|
||||||
|
return null;
|
||||||
|
|
||||||
this.workspaces = this._workspacesManager.workspacesView;
|
let clone = new Clutter.Clone({ source: windows[0].get_texture() });
|
||||||
|
clone.source.connect('destroy', Lang.bind(this, function() {
|
||||||
// Show new workspacesView
|
clone.destroy();
|
||||||
this._group.add_actor(this.workspaces.actor);
|
}));
|
||||||
this._workspacesBar.raise(this.workspaces.actor);
|
return clone;
|
||||||
this._dash.actor.raise(this.workspaces.actor);
|
|
||||||
},
|
|
||||||
|
|
||||||
_recalculateGridSizes: function () {
|
|
||||||
let primary = global.get_primary_monitor();
|
|
||||||
wideScreen = (primary.width/primary.height > WIDE_SCREEN_CUT_OFF_RATIO) &&
|
|
||||||
(primary.height >= WIDE_SCREEN_MINIMUM_HEIGHT);
|
|
||||||
|
|
||||||
// We divide the screen into an imaginary grid which helps us determine the layout of
|
|
||||||
// different visual components.
|
|
||||||
if (wideScreen) {
|
|
||||||
displayGridColumnWidth = Math.floor(primary.width / COLUMNS_WIDE_SCREEN);
|
|
||||||
displayGridRowHeight = Math.floor(primary.height / ROWS_WIDE_SCREEN);
|
|
||||||
} else {
|
|
||||||
displayGridColumnWidth = Math.floor(primary.width / COLUMNS_REGULAR_SCREEN);
|
|
||||||
displayGridRowHeight = Math.floor(primary.height / ROWS_REGULAR_SCREEN);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
relayout: function () {
|
relayout: function () {
|
||||||
let primary = global.get_primary_monitor();
|
let primary = global.get_primary_monitor();
|
||||||
let rtl = (St.Widget.get_default_direction () == St.TextDirection.RTL);
|
let rtl = (St.Widget.get_default_direction () == St.TextDirection.RTL);
|
||||||
|
|
||||||
this._recalculateGridSizes();
|
let contentY = Panel.PANEL_HEIGHT;
|
||||||
|
let contentHeight = primary.height - contentY - Main.messageTray.actor.height;
|
||||||
|
|
||||||
this._group.set_position(primary.x, primary.y);
|
this._group.set_position(primary.x, primary.y);
|
||||||
this._group.set_size(primary.width, primary.height);
|
this._group.set_size(primary.width, primary.height);
|
||||||
|
|
||||||
let contentY = Panel.PANEL_HEIGHT;
|
|
||||||
let contentHeight = primary.height - contentY;
|
|
||||||
|
|
||||||
this._coverPane.set_position(0, contentY);
|
this._coverPane.set_position(0, contentY);
|
||||||
this._coverPane.set_size(primary.width, contentHeight);
|
this._coverPane.set_size(primary.width, contentHeight);
|
||||||
|
|
||||||
let workspaceColumnsUsed = wideScreen ? COLUMNS_FOR_WORKSPACES_WIDE_SCREEN : COLUMNS_FOR_WORKSPACES_REGULAR_SCREEN;
|
let viewWidth = (1.0 - DASH_SPLIT_FRACTION) * primary.width - this._spacing;
|
||||||
let workspaceRowsUsed = wideScreen ? ROWS_FOR_WORKSPACES_WIDE_SCREEN : ROWS_FOR_WORKSPACES_REGULAR_SCREEN;
|
let viewHeight = contentHeight - 2 * this._spacing;
|
||||||
|
let viewY = contentY + this._spacing;
|
||||||
this._workspacesWidth = displayGridColumnWidth * workspaceColumnsUsed
|
let viewX = rtl ? 0
|
||||||
- WORKSPACE_GRID_PADDING * 2;
|
: Math.floor(DASH_SPLIT_FRACTION * primary.width) + this._spacing;
|
||||||
// We scale the vertical padding by (primary.height / primary.width)
|
|
||||||
// so that the workspace preserves its aspect ratio.
|
|
||||||
this._workspacesHeight = Math.floor(displayGridRowHeight * workspaceRowsUsed
|
|
||||||
- WORKSPACE_GRID_PADDING * (primary.height / primary.width) * 2);
|
|
||||||
|
|
||||||
|
// Set the dash's x position - y is handled by a constraint
|
||||||
|
let dashX;
|
||||||
if (rtl) {
|
if (rtl) {
|
||||||
this._workspacesX = WORKSPACE_GRID_PADDING;
|
this._dash.actor.set_anchor_point_from_gravity(Clutter.Gravity.NORTH_EAST);
|
||||||
|
dashX = primary.width;
|
||||||
} else {
|
} else {
|
||||||
this._workspacesX = displayGridColumnWidth + WORKSPACE_GRID_PADDING;
|
dashX = 0;
|
||||||
}
|
}
|
||||||
this._workspacesY = Math.floor(displayGridRowHeight + WORKSPACE_GRID_PADDING * (primary.height / primary.width));
|
this._dash.actor.set_x(dashX);
|
||||||
|
|
||||||
if (rtl) {
|
this.viewSelector.actor.set_position(viewX, viewY);
|
||||||
this._dash.actor.set_position(primary.width - displayGridColumnWidth, contentY);
|
this.viewSelector.actor.set_size(viewWidth, viewHeight);
|
||||||
} else {
|
|
||||||
this._dash.actor.set_position(0, contentY);
|
|
||||||
}
|
|
||||||
|
|
||||||
this._dash.actor.set_size(displayGridColumnWidth, contentHeight);
|
|
||||||
this._dash.searchArea.height = this._workspacesY - contentY;
|
|
||||||
this._dash.sectionArea.height = this._workspacesHeight;
|
|
||||||
this._dash.searchResults.actor.height = this._workspacesHeight;
|
|
||||||
|
|
||||||
this.infoBar.actor.set_position(displayGridColumnWidth, Panel.PANEL_HEIGHT);
|
|
||||||
this.infoBar.actor.set_size(primary.width - displayGridColumnWidth, this._workspacesY - Panel.PANEL_HEIGHT);
|
|
||||||
this.infoBar.actor.raise_top();
|
|
||||||
|
|
||||||
// place the 'Add Workspace' button in the bottom row of the grid
|
|
||||||
this._workspacesBarX = this._workspacesX;
|
|
||||||
this._workspacesBarWidth = this._workspacesWidth;
|
|
||||||
this._workspacesBarY = primary.height - displayGridRowHeight;
|
|
||||||
|
|
||||||
// The parent (this._group) is positioned at the top left of the primary monitor
|
|
||||||
// while this._backOver occupies the entire screen.
|
|
||||||
this._backOver.set_position(- primary.x, - primary.y);
|
|
||||||
this._backOver.set_size(global.screen_width, global.screen_height);
|
|
||||||
|
|
||||||
this._paneContainer.set_position(this._dash.actor.x + this._dash.actor.width + DEFAULT_PADDING,
|
|
||||||
this._workspacesY);
|
|
||||||
// Dynamic width
|
|
||||||
this._paneContainer.height = this._workspacesHeight;
|
|
||||||
if (rtl) {
|
|
||||||
this._paneContainer.connect('notify::width', Lang.bind(this, function (paneContainer) {
|
|
||||||
paneContainer.x = this._dash.actor.x - (DEFAULT_PADDING + paneContainer.width);
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
this._transparentBackground.set_position(primary.x, primary.y);
|
|
||||||
this._transparentBackground.set_size(primary.width, primary.height);
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
addPane: function (pane, align) {
|
|
||||||
pane.actor.height = .9 * this._workspacesHeight;
|
|
||||||
this._paneContainer.add(pane.actor, { expand: true,
|
|
||||||
y_fill: false,
|
|
||||||
y_align: align });
|
|
||||||
// When a pane is displayed, we raise the transparent background to the top
|
|
||||||
// and connect to button-release-event on it, then raise the pane above that.
|
|
||||||
// The idea here is that clicking anywhere outside the pane should close it.
|
|
||||||
// When the active pane is closed, undo the effect.
|
|
||||||
let backgroundEventId = null;
|
|
||||||
pane.connect('open-state-changed', Lang.bind(this, function (pane, isOpen) {
|
|
||||||
if (isOpen) {
|
|
||||||
this._activeDisplayPane = pane;
|
|
||||||
this._transparentBackground.raise_top();
|
|
||||||
this._paneContainer.raise_top();
|
|
||||||
this._paneContainer.show();
|
|
||||||
this._paneReady = false;
|
|
||||||
if (backgroundEventId != null)
|
|
||||||
this._transparentBackground.disconnect(backgroundEventId);
|
|
||||||
backgroundEventId = this._transparentBackground.connect('captured-event', Lang.bind(this, function (actor, event) {
|
|
||||||
if (event.get_source() != this._transparentBackground)
|
|
||||||
return false;
|
|
||||||
if (event.type() == Clutter.EventType.BUTTON_PRESS)
|
|
||||||
this._paneReady = true;
|
|
||||||
if (event.type() == Clutter.EventType.BUTTON_RELEASE
|
|
||||||
&& this._paneReady)
|
|
||||||
this._activeDisplayPane.close();
|
|
||||||
return true;
|
|
||||||
}));
|
|
||||||
if (!this._lightbox)
|
|
||||||
this._lightbox = new Lightbox.Lightbox(this._group,
|
|
||||||
{ fadeTime: PANE_FADE_TIME });
|
|
||||||
this._lightbox.show();
|
|
||||||
this._lightbox.highlight(this._paneContainer);
|
|
||||||
} else if (pane == this._activeDisplayPane) {
|
|
||||||
this._activeDisplayPane = null;
|
|
||||||
if (backgroundEventId != null) {
|
|
||||||
this._transparentBackground.disconnect(backgroundEventId);
|
|
||||||
backgroundEventId = null;
|
|
||||||
}
|
|
||||||
this._transparentBackground.lower_bottom();
|
|
||||||
this._paneContainer.hide();
|
|
||||||
this._lightbox.hide();
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
},
|
},
|
||||||
|
|
||||||
//// Public methods ////
|
//// Public methods ////
|
||||||
|
|
||||||
beginItemDrag: function(source) {
|
beginItemDrag: function(source) {
|
||||||
// Close any active panes if @source is a GenericDisplayItem.
|
|
||||||
// This allows the user to place the item on any workspace.
|
|
||||||
if (source instanceof GenericDisplay.GenericDisplayItem)
|
|
||||||
if (this._activeDisplayPane != null)
|
|
||||||
this._activeDisplayPane.close();
|
|
||||||
this.emit('item-drag-begin');
|
this.emit('item-drag-begin');
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -402,6 +251,14 @@ Overview.prototype = {
|
|||||||
this.emit('item-drag-end');
|
this.emit('item-drag-end');
|
||||||
},
|
},
|
||||||
|
|
||||||
|
beginWindowDrag: function(source) {
|
||||||
|
this.emit('window-drag-begin');
|
||||||
|
},
|
||||||
|
|
||||||
|
endWindowDrag: function(source) {
|
||||||
|
this.emit('window-drag-end');
|
||||||
|
},
|
||||||
|
|
||||||
// Returns the scale the Overview has when we just start zooming out
|
// Returns the scale the Overview has when we just start zooming out
|
||||||
// to overview mode. That is, when just the active workspace is showing.
|
// to overview mode. That is, when just the active workspace is showing.
|
||||||
getZoomedInScale : function() {
|
getZoomedInScale : function() {
|
||||||
@ -419,49 +276,23 @@ Overview.prototype = {
|
|||||||
|
|
||||||
// Returns the current scale of the Overview.
|
// Returns the current scale of the Overview.
|
||||||
getScale : function() {
|
getScale : function() {
|
||||||
return this._group.scaleX;
|
return this.workspaces.actor.scaleX;
|
||||||
},
|
},
|
||||||
|
|
||||||
// Returns the current position of the Overview.
|
// Returns the current position of the Overview.
|
||||||
getPosition : function() {
|
getPosition : function() {
|
||||||
return [this._group.x, this._group.y];
|
return [this.workspaces.actor.x, this.workspaces.actor.y];
|
||||||
},
|
},
|
||||||
|
|
||||||
show : function() {
|
show : function() {
|
||||||
if (this.visible)
|
if (this.visible)
|
||||||
return;
|
return;
|
||||||
if (!Main.pushModal(this._dash.actor))
|
if (!Main.pushModal(this.viewSelector.actor))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.visible = true;
|
this.visible = true;
|
||||||
this.animationInProgress = true;
|
this.animationInProgress = true;
|
||||||
|
|
||||||
this._dash.show();
|
|
||||||
|
|
||||||
/* TODO: make this stuff dynamic */
|
|
||||||
this._workspacesManager =
|
|
||||||
new WorkspacesView.WorkspacesManager(this._workspacesWidth,
|
|
||||||
this._workspacesHeight,
|
|
||||||
this._workspacesX,
|
|
||||||
this._workspacesY);
|
|
||||||
this._workspacesManager.connect('view-changed',
|
|
||||||
Lang.bind(this, this._onViewChanged));
|
|
||||||
this.workspaces = this._workspacesManager.workspacesView;
|
|
||||||
this._group.add_actor(this.workspaces.actor);
|
|
||||||
|
|
||||||
// The workspaces actor is as big as the screen, so we have to raise the dash above it
|
|
||||||
// for drag and drop to work. In the future we should fix the workspaces to not
|
|
||||||
// be as big as the screen.
|
|
||||||
this._dash.actor.raise(this.workspaces.actor);
|
|
||||||
|
|
||||||
this._workspacesBar = this._workspacesManager.controlsBar.actor;
|
|
||||||
this._workspacesBar.set_position(this._workspacesBarX,
|
|
||||||
this._workspacesBarY);
|
|
||||||
this._workspacesBar.width = this._workspacesBarWidth;
|
|
||||||
|
|
||||||
this._group.add_actor(this._workspacesBar);
|
|
||||||
this._workspacesBar.raise(this.workspaces.actor);
|
|
||||||
|
|
||||||
// All the the actors in the window group are completely obscured,
|
// All the the actors in the window group are completely obscured,
|
||||||
// hiding the group holding them while the Overview is displayed greatly
|
// hiding the group holding them while the Overview is displayed greatly
|
||||||
// increases performance of the Overview especially when there are many
|
// increases performance of the Overview especially when there are many
|
||||||
@ -471,17 +302,38 @@ Overview.prototype = {
|
|||||||
// clones of them, this would obviously no longer be necessary.
|
// clones of them, this would obviously no longer be necessary.
|
||||||
global.window_group.hide();
|
global.window_group.hide();
|
||||||
this._group.show();
|
this._group.show();
|
||||||
|
this._background.show();
|
||||||
|
|
||||||
// Create a zoom out effect. First scale the Overview group up and
|
this.viewSelector.show();
|
||||||
|
this._workspacesDisplay.show();
|
||||||
|
this._dash.show();
|
||||||
|
|
||||||
|
this.workspaces = this._workspacesDisplay.workspacesView;
|
||||||
|
global.overlay_group.add_actor(this.workspaces.actor);
|
||||||
|
|
||||||
|
if (!this._desktopFade.child)
|
||||||
|
this._desktopFade.child = this._getDesktopClone();
|
||||||
|
|
||||||
|
if (!this.workspaces.getActiveWorkspace().hasMaximizedWindows()) {
|
||||||
|
this._desktopFade.opacity = 255;
|
||||||
|
this._desktopFade.show();
|
||||||
|
Tweener.addTween(this._desktopFade,
|
||||||
|
{ opacity: 0,
|
||||||
|
time: ANIMATION_TIME,
|
||||||
|
transition: 'easeOutQuad'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a zoom out effect. First scale the workspaces view up and
|
||||||
// position it so that the active workspace fills up the whole screen,
|
// position it so that the active workspace fills up the whole screen,
|
||||||
// then transform the group to its normal dimensions and position.
|
// then transform it to its normal dimensions and position.
|
||||||
// The opposite transition is used in hide().
|
// The opposite transition is used in hide().
|
||||||
this._group.scaleX = this._group.scaleY = this.getZoomedInScale();
|
this.workspaces.actor.scaleX = this.workspaces.actor.scaleY = this.getZoomedInScale();
|
||||||
[this._group.x, this._group.y] = this.getZoomedInPosition();
|
[this.workspaces.actor.x, this.workspaces.actor.y] = this.getZoomedInPosition();
|
||||||
let primary = global.get_primary_monitor();
|
let primary = global.get_primary_monitor();
|
||||||
Tweener.addTween(this._group,
|
Tweener.addTween(this.workspaces.actor,
|
||||||
{ x: primary.x,
|
{ x: primary.x - this._group.x,
|
||||||
y: primary.y,
|
y: primary.y - this._group.y,
|
||||||
scaleX: 1,
|
scaleX: 1,
|
||||||
scaleY: 1,
|
scaleY: 1,
|
||||||
transition: 'easeOutQuad',
|
transition: 'easeOutQuad',
|
||||||
@ -490,9 +342,9 @@ Overview.prototype = {
|
|||||||
onCompleteScope: this
|
onCompleteScope: this
|
||||||
});
|
});
|
||||||
|
|
||||||
// Make Dash fade in so that it doesn't appear too big.
|
// Make the other elements fade in.
|
||||||
this._dash.actor.opacity = 0;
|
this._group.opacity = 0;
|
||||||
Tweener.addTween(this._dash.actor,
|
Tweener.addTween(this._group,
|
||||||
{ opacity: 255,
|
{ opacity: 255,
|
||||||
transition: 'easeOutQuad',
|
transition: 'easeOutQuad',
|
||||||
time: ANIMATION_TIME
|
time: ANIMATION_TIME
|
||||||
@ -508,16 +360,24 @@ Overview.prototype = {
|
|||||||
|
|
||||||
this.animationInProgress = true;
|
this.animationInProgress = true;
|
||||||
this._hideInProgress = true;
|
this._hideInProgress = true;
|
||||||
if (this._activeDisplayPane != null)
|
|
||||||
this._activeDisplayPane.close();
|
if (!this.workspaces.getActiveWorkspace().hasMaximizedWindows()) {
|
||||||
|
this._desktopFade.opacity = 0;
|
||||||
|
this._desktopFade.show();
|
||||||
|
Tweener.addTween(this._desktopFade,
|
||||||
|
{ opacity: 255,
|
||||||
|
time: ANIMATION_TIME,
|
||||||
|
transition: 'easeOutQuad' });
|
||||||
|
}
|
||||||
|
|
||||||
this.workspaces.hide();
|
this.workspaces.hide();
|
||||||
|
|
||||||
// Create a zoom in effect by transforming the Overview group so that
|
// Create a zoom in effect by transforming the workspaces view so that
|
||||||
// the active workspace fills up the whole screen. The opposite
|
// the active workspace fills up the whole screen. The opposite
|
||||||
// transition is used in show().
|
// transition is used in show().
|
||||||
let scale = this.getZoomedInScale();
|
let scale = this.getZoomedInScale();
|
||||||
let [posX, posY] = this.getZoomedInPosition();
|
let [posX, posY] = this.getZoomedInPosition();
|
||||||
Tweener.addTween(this._group,
|
Tweener.addTween(this.workspaces.actor,
|
||||||
{ x: posX,
|
{ x: posX,
|
||||||
y: posY,
|
y: posY,
|
||||||
scaleX: scale,
|
scaleX: scale,
|
||||||
@ -528,8 +388,8 @@ Overview.prototype = {
|
|||||||
onCompleteScope: this
|
onCompleteScope: this
|
||||||
});
|
});
|
||||||
|
|
||||||
// Make Dash fade out so that it doesn't appear to big.
|
// Make other elements fade out.
|
||||||
Tweener.addTween(this._dash.actor,
|
Tweener.addTween(this._group,
|
||||||
{ opacity: 0,
|
{ opacity: 0,
|
||||||
transition: 'easeOutQuad',
|
transition: 'easeOutQuad',
|
||||||
time: ANIMATION_TIME
|
time: ANIMATION_TIME
|
||||||
@ -565,6 +425,7 @@ Overview.prototype = {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
this.animationInProgress = false;
|
this.animationInProgress = false;
|
||||||
|
this._desktopFade.hide();
|
||||||
this._coverPane.lower_bottom();
|
this._coverPane.lower_bottom();
|
||||||
|
|
||||||
this.emit('shown');
|
this.emit('shown');
|
||||||
@ -576,12 +437,12 @@ Overview.prototype = {
|
|||||||
this.workspaces.destroy();
|
this.workspaces.destroy();
|
||||||
this.workspaces = null;
|
this.workspaces = null;
|
||||||
|
|
||||||
this._workspacesBar.destroy();
|
this._workspacesDisplay.hide();
|
||||||
this._workspacesBar = null;
|
this.viewSelector.hide();
|
||||||
|
|
||||||
this._workspacesManager = null;
|
|
||||||
|
|
||||||
this._dash.hide();
|
this._dash.hide();
|
||||||
|
|
||||||
|
this._desktopFade.hide();
|
||||||
|
this._background.hide();
|
||||||
this._group.hide();
|
this._group.hide();
|
||||||
|
|
||||||
this.visible = false;
|
this.visible = false;
|
||||||
@ -590,7 +451,7 @@ Overview.prototype = {
|
|||||||
|
|
||||||
this._coverPane.lower_bottom();
|
this._coverPane.lower_bottom();
|
||||||
|
|
||||||
Main.popModal(this._dash.actor);
|
Main.popModal(this.viewSelector.actor);
|
||||||
this.emit('hidden');
|
this.emit('hidden');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -109,7 +109,7 @@ PlaceDeviceInfo.prototype = {
|
|||||||
this._mount.unmount_finish(res);
|
this._mount.unmount_finish(res);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
let message = _("Failed to unmount '%s'").format(o.get_name());
|
let message = _("Failed to unmount '%s'").format(o.get_name());
|
||||||
Main.overview.infoBar.setMessage(message,
|
Main.overview.shellInfo.setMessage(message,
|
||||||
Lang.bind(this, this.remove),
|
Lang.bind(this, this.remove),
|
||||||
_("Retry"));
|
_("Retry"));
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
const Signals = imports.signals;
|
const Signals = imports.signals;
|
||||||
|
|
||||||
const RESULT_ICON_SIZE = 24;
|
const RESULT_ICON_SIZE = 48;
|
||||||
|
|
||||||
// Not currently referenced by the search API, but
|
// Not currently referenced by the search API, but
|
||||||
// this enumeration can be useful for provider
|
// this enumeration can be useful for provider
|
||||||
@ -182,7 +182,7 @@ SearchProvider.prototype = {
|
|||||||
* implementation will show the icon next to the name.
|
* implementation will show the icon next to the name.
|
||||||
*
|
*
|
||||||
* The actor should be an instance of St.Widget, with the style class
|
* The actor should be an instance of St.Widget, with the style class
|
||||||
* 'dash-search-result-content'.
|
* 'search-result-content'.
|
||||||
*/
|
*/
|
||||||
createResultActor: function(resultMeta, terms) {
|
createResultActor: function(resultMeta, terms) {
|
||||||
return null;
|
return null;
|
||||||
|
332
js/ui/searchDisplay.js
Normal file
332
js/ui/searchDisplay.js
Normal file
@ -0,0 +1,332 @@
|
|||||||
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
|
const Clutter = imports.gi.Clutter;
|
||||||
|
const Lang = imports.lang;
|
||||||
|
const Gettext = imports.gettext.domain('gnome-shell');
|
||||||
|
const _ = Gettext.gettext;
|
||||||
|
const Gtk = imports.gi.Gtk;
|
||||||
|
const St = imports.gi.St;
|
||||||
|
|
||||||
|
const DND = imports.ui.dnd;
|
||||||
|
const IconGrid = imports.ui.iconGrid;
|
||||||
|
const Main = imports.ui.main;
|
||||||
|
const Search = imports.ui.search;
|
||||||
|
|
||||||
|
const MAX_SEARCH_RESULTS_ROWS = 2;
|
||||||
|
|
||||||
|
|
||||||
|
function SearchResult(provider, metaInfo, terms) {
|
||||||
|
this._init(provider, metaInfo, terms);
|
||||||
|
}
|
||||||
|
|
||||||
|
SearchResult.prototype = {
|
||||||
|
_init: function(provider, metaInfo, terms) {
|
||||||
|
this.provider = provider;
|
||||||
|
this.metaInfo = metaInfo;
|
||||||
|
this.actor = new St.Clickable({ style_class: 'search-result',
|
||||||
|
reactive: true,
|
||||||
|
x_align: St.Align.START,
|
||||||
|
y_fill: true });
|
||||||
|
this.actor._delegate = this;
|
||||||
|
|
||||||
|
let content = provider.createResultActor(metaInfo, terms);
|
||||||
|
if (content == null) {
|
||||||
|
content = new St.Bin({ style_class: 'search-result-content',
|
||||||
|
reactive: true,
|
||||||
|
track_hover: true });
|
||||||
|
let icon = new IconGrid.BaseIcon(this.metaInfo['name'],
|
||||||
|
{ createIcon: Lang.bind(this, function(size) {
|
||||||
|
return this.metaInfo['icon'];
|
||||||
|
})});
|
||||||
|
content.set_child(icon.actor);
|
||||||
|
}
|
||||||
|
this._content = content;
|
||||||
|
this.actor.set_child(content);
|
||||||
|
|
||||||
|
this.actor.connect('clicked', Lang.bind(this, this._onResultClicked));
|
||||||
|
|
||||||
|
let draggable = DND.makeDraggable(this.actor);
|
||||||
|
draggable.connect('drag-begin',
|
||||||
|
Lang.bind(this, function() {
|
||||||
|
Main.overview.beginItemDrag(this);
|
||||||
|
}));
|
||||||
|
draggable.connect('drag-end',
|
||||||
|
Lang.bind(this, function() {
|
||||||
|
Main.overview.endItemDrag(this);
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
|
||||||
|
setSelected: function(selected) {
|
||||||
|
if (selected)
|
||||||
|
this._content.add_style_pseudo_class('selected');
|
||||||
|
else
|
||||||
|
this._content.remove_style_pseudo_class('selected');
|
||||||
|
},
|
||||||
|
|
||||||
|
activate: function() {
|
||||||
|
this.provider.activateResult(this.metaInfo.id);
|
||||||
|
Main.overview.toggle();
|
||||||
|
},
|
||||||
|
|
||||||
|
_onResultClicked: function(actor, event) {
|
||||||
|
this.activate();
|
||||||
|
},
|
||||||
|
|
||||||
|
getDragActorSource: function() {
|
||||||
|
return this.metaInfo['icon'];
|
||||||
|
},
|
||||||
|
|
||||||
|
getDragActor: function(stageX, stageY) {
|
||||||
|
return new Clutter.Clone({ source: this.metaInfo['icon'] });
|
||||||
|
},
|
||||||
|
|
||||||
|
shellWorkspaceLaunch: function() {
|
||||||
|
if (this.provider.dragActivateResult)
|
||||||
|
this.provider.dragActivateResult(this.metaInfo.id);
|
||||||
|
else
|
||||||
|
this.provider.activateResult(this.metaInfo.id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
function GridSearchResults(provider) {
|
||||||
|
this._init(provider);
|
||||||
|
}
|
||||||
|
|
||||||
|
GridSearchResults.prototype = {
|
||||||
|
__proto__: Search.SearchResultDisplay.prototype,
|
||||||
|
|
||||||
|
_init: function(provider) {
|
||||||
|
Search.SearchResultDisplay.prototype._init.call(this, provider);
|
||||||
|
this._grid = new IconGrid.IconGrid({ rowLimit: MAX_SEARCH_RESULTS_ROWS,
|
||||||
|
xAlign: St.Align.START });
|
||||||
|
this.actor = new St.Bin({ x_align: St.Align.START });
|
||||||
|
this.actor.set_child(this._grid.actor);
|
||||||
|
this.selectionIndex = -1;
|
||||||
|
},
|
||||||
|
|
||||||
|
getVisibleResultCount: function() {
|
||||||
|
return this._grid.visibleItemsCount();
|
||||||
|
},
|
||||||
|
|
||||||
|
renderResults: function(results, terms) {
|
||||||
|
for (let i = 0; i < results.length; i++) {
|
||||||
|
let result = results[i];
|
||||||
|
let meta = this.provider.getResultMeta(result);
|
||||||
|
let display = new SearchResult(this.provider, meta, terms);
|
||||||
|
this._grid.addItem(display.actor);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
clear: function () {
|
||||||
|
this._grid.removeAll();
|
||||||
|
this.selectionIndex = -1;
|
||||||
|
},
|
||||||
|
|
||||||
|
selectIndex: function (index) {
|
||||||
|
let nVisible = this.getVisibleResultCount();
|
||||||
|
if (this.selectionIndex >= 0) {
|
||||||
|
let prevActor = this._grid.getItemAtIndex(this.selectionIndex);
|
||||||
|
prevActor._delegate.setSelected(false);
|
||||||
|
}
|
||||||
|
this.selectionIndex = -1;
|
||||||
|
if (index >= nVisible)
|
||||||
|
return false;
|
||||||
|
else if (index < 0)
|
||||||
|
return false;
|
||||||
|
let targetActor = this._grid.getItemAtIndex(index);
|
||||||
|
targetActor._delegate.setSelected(true);
|
||||||
|
this.selectionIndex = index;
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
activateSelected: function() {
|
||||||
|
if (this.selectionIndex < 0)
|
||||||
|
return;
|
||||||
|
let targetActor = this._grid.getItemAtIndex(this.selectionIndex);
|
||||||
|
targetActor._delegate.activate();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
function SearchResults(searchSystem) {
|
||||||
|
this._init(searchSystem);
|
||||||
|
}
|
||||||
|
|
||||||
|
SearchResults.prototype = {
|
||||||
|
_init: function(searchSystem) {
|
||||||
|
this._searchSystem = searchSystem;
|
||||||
|
|
||||||
|
this.actor = new St.Bin({ name: 'searchResults',
|
||||||
|
y_align: St.Align.START,
|
||||||
|
x_align: St.Align.START,
|
||||||
|
x_fill: true });
|
||||||
|
this._content = new St.BoxLayout({ name: 'searchResultsContent',
|
||||||
|
vertical: true });
|
||||||
|
|
||||||
|
let scrollView = new St.ScrollView({ x_fill: true,
|
||||||
|
y_fill: false,
|
||||||
|
vshadows: true });
|
||||||
|
scrollView.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
|
||||||
|
scrollView.add_actor(this._content);
|
||||||
|
|
||||||
|
this.actor.set_child(scrollView);
|
||||||
|
|
||||||
|
this._statusText = new St.Label({ style_class: 'search-statustext' });
|
||||||
|
this._content.add(this._statusText);
|
||||||
|
this._selectedProvider = -1;
|
||||||
|
this._providers = this._searchSystem.getProviders();
|
||||||
|
this._providerMeta = [];
|
||||||
|
for (let i = 0; i < this._providers.length; i++)
|
||||||
|
this.createProviderMeta(this._providers[i]);
|
||||||
|
},
|
||||||
|
|
||||||
|
createProviderMeta: function(provider) {
|
||||||
|
let providerBox = new St.BoxLayout({ style_class: 'search-section',
|
||||||
|
vertical: true });
|
||||||
|
let titleButton = new St.Button({ style_class: 'search-section-header',
|
||||||
|
reactive: true,
|
||||||
|
x_fill: true,
|
||||||
|
y_fill: true });
|
||||||
|
titleButton.connect('clicked', Lang.bind(this, function () { this._onHeaderClicked(provider); }));
|
||||||
|
providerBox.add(titleButton);
|
||||||
|
let titleBox = new St.BoxLayout();
|
||||||
|
titleButton.set_child(titleBox);
|
||||||
|
let title = new St.Label({ text: provider.title });
|
||||||
|
let count = new St.Label();
|
||||||
|
titleBox.add(title, { expand: true });
|
||||||
|
titleBox.add(count);
|
||||||
|
|
||||||
|
let resultDisplayBin = new St.Bin({ style_class: 'search-section-results',
|
||||||
|
x_fill: true,
|
||||||
|
y_fill: true });
|
||||||
|
providerBox.add(resultDisplayBin, { expand: true });
|
||||||
|
let resultDisplay = provider.createResultContainerActor();
|
||||||
|
if (resultDisplay == null) {
|
||||||
|
resultDisplay = new GridSearchResults(provider);
|
||||||
|
}
|
||||||
|
resultDisplayBin.set_child(resultDisplay.actor);
|
||||||
|
|
||||||
|
this._providerMeta.push({ actor: providerBox,
|
||||||
|
resultDisplay: resultDisplay,
|
||||||
|
count: count });
|
||||||
|
this._content.add(providerBox);
|
||||||
|
},
|
||||||
|
|
||||||
|
_clearDisplay: function() {
|
||||||
|
this._selectedProvider = -1;
|
||||||
|
this._visibleResultsCount = 0;
|
||||||
|
for (let i = 0; i < this._providerMeta.length; i++) {
|
||||||
|
let meta = this._providerMeta[i];
|
||||||
|
meta.resultDisplay.clear();
|
||||||
|
meta.actor.hide();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
reset: function() {
|
||||||
|
this._searchSystem.reset();
|
||||||
|
this._statusText.hide();
|
||||||
|
this._clearDisplay();
|
||||||
|
},
|
||||||
|
|
||||||
|
startingSearch: function() {
|
||||||
|
this.reset();
|
||||||
|
this._statusText.set_text(_("Searching..."));
|
||||||
|
this._statusText.show();
|
||||||
|
},
|
||||||
|
|
||||||
|
_metaForProvider: function(provider) {
|
||||||
|
return this._providerMeta[this._providers.indexOf(provider)];
|
||||||
|
},
|
||||||
|
|
||||||
|
updateSearch: function (searchString) {
|
||||||
|
let results = this._searchSystem.updateSearch(searchString);
|
||||||
|
|
||||||
|
this._clearDisplay();
|
||||||
|
|
||||||
|
if (results.length == 0) {
|
||||||
|
this._statusText.set_text(_("No matching results."));
|
||||||
|
this._statusText.show();
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
this._statusText.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
let terms = this._searchSystem.getTerms();
|
||||||
|
|
||||||
|
for (let i = 0; i < results.length; i++) {
|
||||||
|
let [provider, providerResults] = results[i];
|
||||||
|
let meta = this._metaForProvider(provider);
|
||||||
|
meta.actor.show();
|
||||||
|
meta.resultDisplay.renderResults(providerResults, terms);
|
||||||
|
meta.count.set_text('' + providerResults.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.selectDown(false);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
_onHeaderClicked: function(provider) {
|
||||||
|
provider.expandSearch(this._searchSystem.getTerms());
|
||||||
|
},
|
||||||
|
|
||||||
|
_modifyActorSelection: function(resultDisplay, up) {
|
||||||
|
let success;
|
||||||
|
let index = resultDisplay.getSelectionIndex();
|
||||||
|
if (up && index == -1)
|
||||||
|
index = resultDisplay.getVisibleResultCount() - 1;
|
||||||
|
else if (up)
|
||||||
|
index = index - 1;
|
||||||
|
else
|
||||||
|
index = index + 1;
|
||||||
|
return resultDisplay.selectIndex(index);
|
||||||
|
},
|
||||||
|
|
||||||
|
selectUp: function(recursing) {
|
||||||
|
for (let i = this._selectedProvider; i >= 0; i--) {
|
||||||
|
let meta = this._providerMeta[i];
|
||||||
|
if (!meta.actor.visible)
|
||||||
|
continue;
|
||||||
|
let success = this._modifyActorSelection(meta.resultDisplay, true);
|
||||||
|
if (success) {
|
||||||
|
this._selectedProvider = i;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this._providerMeta.length > 0 && !recursing) {
|
||||||
|
this._selectedProvider = this._providerMeta.length - 1;
|
||||||
|
this.selectUp(true);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
selectDown: function(recursing) {
|
||||||
|
let current = this._selectedProvider;
|
||||||
|
if (current == -1)
|
||||||
|
current = 0;
|
||||||
|
for (let i = current; i < this._providerMeta.length; i++) {
|
||||||
|
let meta = this._providerMeta[i];
|
||||||
|
if (!meta.actor.visible)
|
||||||
|
continue;
|
||||||
|
let success = this._modifyActorSelection(meta.resultDisplay, false);
|
||||||
|
if (success) {
|
||||||
|
this._selectedProvider = i;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this._providerMeta.length > 0 && !recursing) {
|
||||||
|
this._selectedProvider = 0;
|
||||||
|
this.selectDown(true);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
activateSelected: function() {
|
||||||
|
let current = this._selectedProvider;
|
||||||
|
if (current < 0)
|
||||||
|
return;
|
||||||
|
let meta = this._providerMeta[current];
|
||||||
|
let resultDisplay = meta.resultDisplay;
|
||||||
|
resultDisplay.activateSelected();
|
||||||
|
Main.overview.hide();
|
||||||
|
}
|
||||||
|
};
|
@ -469,11 +469,15 @@ Source.prototype = {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._notification = undefined;
|
||||||
|
this._sentMessages = [];
|
||||||
|
|
||||||
// Since we only create sources when receiving a message, this
|
// Since we only create sources when receiving a message, this
|
||||||
// is a plausible default
|
// is a plausible default
|
||||||
this._presence = Telepathy.ConnectionPresenceType.AVAILABLE;
|
this._presence = Telepathy.ConnectionPresenceType.AVAILABLE;
|
||||||
|
|
||||||
this._channelText = new Telepathy.ChannelText(DBus.session, connName, channelPath);
|
this._channelText = new Telepathy.ChannelText(DBus.session, connName, channelPath);
|
||||||
|
this._sentId = this._channelText.connect('Sent', Lang.bind(this, this._messageSent));
|
||||||
this._receivedId = this._channelText.connect('Received', Lang.bind(this, this._messageReceived));
|
this._receivedId = this._channelText.connect('Received', Lang.bind(this, this._messageReceived));
|
||||||
|
|
||||||
this._channelText.ListPendingMessagesRemote(false, Lang.bind(this, this._gotPendingMessages));
|
this._channelText.ListPendingMessagesRemote(false, Lang.bind(this, this._gotPendingMessages));
|
||||||
@ -517,6 +521,7 @@ Source.prototype = {
|
|||||||
_channelClosed: function() {
|
_channelClosed: function() {
|
||||||
this._channel.disconnect(this._closedId);
|
this._channel.disconnect(this._closedId);
|
||||||
this._channelText.disconnect(this._receivedId);
|
this._channelText.disconnect(this._receivedId);
|
||||||
|
this._channelText.disconnect(this._sentId);
|
||||||
this.destroy();
|
this.destroy();
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -524,17 +529,30 @@ Source.prototype = {
|
|||||||
if (!Main.messageTray.contains(this))
|
if (!Main.messageTray.contains(this))
|
||||||
Main.messageTray.add(this);
|
Main.messageTray.add(this);
|
||||||
|
|
||||||
if (!this._notification)
|
if (!this._notification) {
|
||||||
this._notification = new Notification(this);
|
this._notification = new Notification(this);
|
||||||
|
for (let i = 0; i < this._sentMessages.length; i ++)
|
||||||
|
this._notification.appendMessage(this._sentMessages[i], false, true);
|
||||||
|
this._sentMessages = [];
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_messageReceived: function(channel, id, timestamp, sender,
|
_messageReceived: function(channel, id, timestamp, sender,
|
||||||
type, flags, text) {
|
type, flags, text) {
|
||||||
this._ensureNotification();
|
this._ensureNotification();
|
||||||
this._notification.appendMessage(text);
|
this._notification.appendMessage(text, false, false);
|
||||||
this.notify(this._notification);
|
this.notify(this._notification);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_messageSent: function(channel, timestamp, type, text) {
|
||||||
|
if (this._notification) {
|
||||||
|
this._notification.appendMessage(text, false, true);
|
||||||
|
this.notify(this._notification);
|
||||||
|
} else {
|
||||||
|
this._sentMessages.push(text);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
respond: function(text) {
|
respond: function(text) {
|
||||||
this._channelText.SendRemote(Telepathy.ChannelTextMessageType.NORMAL, text);
|
this._channelText.SendRemote(Telepathy.ChannelTextMessageType.NORMAL, text);
|
||||||
},
|
},
|
||||||
@ -565,7 +583,7 @@ Source.prototype = {
|
|||||||
msg += ' <i>(' + GLib.markup_escape_text(message, -1) + ')</i>';
|
msg += ' <i>(' + GLib.markup_escape_text(message, -1) + ')</i>';
|
||||||
|
|
||||||
this._ensureNotification();
|
this._ensureNotification();
|
||||||
this._notification.appendMessage(msg, true);
|
this._notification.appendMessage(msg, true, false);
|
||||||
if (notify)
|
if (notify)
|
||||||
this.notify(this._notification);
|
this.notify(this._notification);
|
||||||
}
|
}
|
||||||
@ -588,12 +606,12 @@ Notification.prototype = {
|
|||||||
this._history = [];
|
this._history = [];
|
||||||
},
|
},
|
||||||
|
|
||||||
appendMessage: function(text, asTitle) {
|
appendMessage: function(text, asTitle, sent) {
|
||||||
if (asTitle)
|
if (asTitle)
|
||||||
this.update(text, null, { customContent: true });
|
this.update(text, null, { customContent: true });
|
||||||
else
|
else
|
||||||
this.update(this.source.title, text, { customContent: true });
|
this.update(this.source.title, text, { customContent: true });
|
||||||
this._append(text, 'chat-received');
|
this._append(text, sent ? 'chat-sent' : 'chat-received');
|
||||||
},
|
},
|
||||||
|
|
||||||
_append: function(text, style) {
|
_append: function(text, style) {
|
||||||
@ -635,7 +653,6 @@ Notification.prototype = {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
this._responseEntry.set_text('');
|
this._responseEntry.set_text('');
|
||||||
this._append(text, 'chat-sent');
|
|
||||||
this.source.respond(text);
|
this.source.respond(text);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
628
js/ui/viewSelector.js
Normal file
628
js/ui/viewSelector.js
Normal file
@ -0,0 +1,628 @@
|
|||||||
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
|
const Clutter = imports.gi.Clutter;
|
||||||
|
const Mainloop = imports.mainloop;
|
||||||
|
const Meta = imports.gi.Meta;
|
||||||
|
const Signals = imports.signals;
|
||||||
|
const Lang = imports.lang;
|
||||||
|
const Shell = imports.gi.Shell;
|
||||||
|
const St = imports.gi.St;
|
||||||
|
const Gettext = imports.gettext.domain('gnome-shell');
|
||||||
|
const _ = Gettext.gettext;
|
||||||
|
|
||||||
|
const Main = imports.ui.main;
|
||||||
|
const Search = imports.ui.search;
|
||||||
|
const SearchDisplay = imports.ui.searchDisplay;
|
||||||
|
const Tweener = imports.ui.tweener;
|
||||||
|
|
||||||
|
|
||||||
|
function SearchEntry() {
|
||||||
|
this._init();
|
||||||
|
}
|
||||||
|
|
||||||
|
SearchEntry.prototype = {
|
||||||
|
_init : function() {
|
||||||
|
this.actor = new St.Entry({ name: 'searchEntry',
|
||||||
|
hint_text: _("Search your computer") });
|
||||||
|
this.entry = this.actor.clutter_text;
|
||||||
|
|
||||||
|
this.actor.clutter_text.connect('text-changed', Lang.bind(this,
|
||||||
|
function() {
|
||||||
|
if (this.isActive())
|
||||||
|
this.actor.set_secondary_icon_from_file(global.imagedir +
|
||||||
|
'close-black.svg');
|
||||||
|
else
|
||||||
|
this.actor.set_secondary_icon_from_file(null);
|
||||||
|
}));
|
||||||
|
this.actor.connect('secondary-icon-clicked', Lang.bind(this,
|
||||||
|
function() {
|
||||||
|
this.reset();
|
||||||
|
}));
|
||||||
|
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
|
||||||
|
|
||||||
|
global.stage.connect('notify::key-focus', Lang.bind(this, this._updateCursorVisibility));
|
||||||
|
|
||||||
|
this.pane = null;
|
||||||
|
|
||||||
|
this._capturedEventId = 0;
|
||||||
|
},
|
||||||
|
|
||||||
|
_updateCursorVisibility: function() {
|
||||||
|
let focus = global.stage.get_key_focus();
|
||||||
|
if (focus == global.stage || focus == this.entry)
|
||||||
|
this.entry.set_cursor_visible(true);
|
||||||
|
else
|
||||||
|
this.entry.set_cursor_visible(false);
|
||||||
|
},
|
||||||
|
|
||||||
|
show: function() {
|
||||||
|
if (this._capturedEventId == 0)
|
||||||
|
this._capturedEventId = global.stage.connect('captured-event',
|
||||||
|
Lang.bind(this, this._onCapturedEvent));
|
||||||
|
this.entry.set_cursor_visible(true);
|
||||||
|
this.entry.set_selection(0, 0);
|
||||||
|
},
|
||||||
|
|
||||||
|
hide: function() {
|
||||||
|
if (this._capturedEventId > 0) {
|
||||||
|
global.stage.disconnect(this._capturedEventId);
|
||||||
|
this._capturedEventId = 0;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
reset: function () {
|
||||||
|
let [x, y, mask] = global.get_pointer();
|
||||||
|
let actor = global.stage.get_actor_at_pos (Clutter.PickMode.REACTIVE,
|
||||||
|
x, y);
|
||||||
|
// this.actor is never hovered directly, only its clutter_text and icon
|
||||||
|
let hovered = this.actor == actor.get_parent();
|
||||||
|
|
||||||
|
this.actor.set_hover(hovered);
|
||||||
|
|
||||||
|
this.entry.text = '';
|
||||||
|
|
||||||
|
// Return focus to the stage
|
||||||
|
global.stage.set_key_focus(null);
|
||||||
|
|
||||||
|
this.entry.set_cursor_visible(true);
|
||||||
|
this.entry.set_selection(0, 0);
|
||||||
|
},
|
||||||
|
|
||||||
|
getText: function () {
|
||||||
|
return this.entry.get_text().replace(/^\s+/g, '').replace(/\s+$/g, '');
|
||||||
|
},
|
||||||
|
|
||||||
|
// some search term has been entered
|
||||||
|
isActive: function() {
|
||||||
|
return this.actor.get_text() != '';
|
||||||
|
},
|
||||||
|
|
||||||
|
// the entry does not show the hint
|
||||||
|
_isActivated: function() {
|
||||||
|
return this.entry.text == this.actor.get_text();
|
||||||
|
},
|
||||||
|
|
||||||
|
_onCapturedEvent: function(actor, event) {
|
||||||
|
let source = event.get_source();
|
||||||
|
let panelEvent = source && Main.panel.actor.contains(source);
|
||||||
|
|
||||||
|
switch (event.type()) {
|
||||||
|
case Clutter.EventType.BUTTON_PRESS:
|
||||||
|
// the user clicked outside after activating the entry, but
|
||||||
|
// with no search term entered - cancel the search
|
||||||
|
if (source != this.entry && this.entry.text == '') {
|
||||||
|
this.reset();
|
||||||
|
// allow only panel events to continue
|
||||||
|
return !panelEvent;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
case Clutter.EventType.KEY_PRESS:
|
||||||
|
// If neither the stage nor our entry have key focus, some
|
||||||
|
// "special" actor grabbed the focus (run dialog, looking
|
||||||
|
// glass); we don't want to interfere with that
|
||||||
|
let focus = global.stage.get_key_focus();
|
||||||
|
if (focus != global.stage && focus != this.entry)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
let sym = event.get_key_symbol();
|
||||||
|
|
||||||
|
// If we have an active search, Escape cancels it - if we
|
||||||
|
// haven't, the key is ignored
|
||||||
|
if (sym == Clutter.Escape)
|
||||||
|
if (this._isActivated()) {
|
||||||
|
this.reset();
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ignore non-printable keys
|
||||||
|
if (!Clutter.keysym_to_unicode(sym))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Search started - move the key focus to the entry and
|
||||||
|
// "repeat" the event
|
||||||
|
if (!this._isActivated()) {
|
||||||
|
global.stage.set_key_focus(this.entry);
|
||||||
|
this.entry.event(event, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
// Suppress all other events outside the panel while the entry
|
||||||
|
// is activated and no search has been entered - any click
|
||||||
|
// outside the entry will cancel the search
|
||||||
|
return (this.entry.text == '' && !panelEvent);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_onDestroy: function() {
|
||||||
|
if (this._capturedEventId > 0) {
|
||||||
|
global.stage.disconnect(this._capturedEventId);
|
||||||
|
this._capturedEventId = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Signals.addSignalMethods(SearchEntry.prototype);
|
||||||
|
|
||||||
|
|
||||||
|
function BaseTab(titleActor, pageActor) {
|
||||||
|
this._init(titleActor, pageActor);
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseTab.prototype = {
|
||||||
|
_init: function(titleActor, pageActor) {
|
||||||
|
this.title = titleActor;
|
||||||
|
this.page = new St.Bin({ child: pageActor,
|
||||||
|
x_align: St.Align.START,
|
||||||
|
y_align: St.Align.START,
|
||||||
|
x_fill: true,
|
||||||
|
y_fill: true,
|
||||||
|
style_class: 'view-tab-page' });
|
||||||
|
|
||||||
|
this.visible = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
show: function() {
|
||||||
|
this.visible = true;
|
||||||
|
this.page.opacity = 0;
|
||||||
|
this.page.show();
|
||||||
|
|
||||||
|
Tweener.addTween(this.page,
|
||||||
|
{ opacity: 255,
|
||||||
|
time: 0.1,
|
||||||
|
transition: 'easeOutQuad' });
|
||||||
|
},
|
||||||
|
|
||||||
|
hide: function() {
|
||||||
|
this.visible = false;
|
||||||
|
Tweener.addTween(this.page,
|
||||||
|
{ opacity: 0,
|
||||||
|
time: 0.1,
|
||||||
|
transition: 'easeOutQuad',
|
||||||
|
onComplete: Lang.bind(this,
|
||||||
|
function() {
|
||||||
|
this.page.hide();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
_activate: function() {
|
||||||
|
this.emit('activated');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Signals.addSignalMethods(BaseTab.prototype);
|
||||||
|
|
||||||
|
|
||||||
|
function ViewTab(label, pageActor) {
|
||||||
|
this._init(label, pageActor);
|
||||||
|
}
|
||||||
|
|
||||||
|
ViewTab.prototype = {
|
||||||
|
__proto__: BaseTab.prototype,
|
||||||
|
|
||||||
|
_init: function(label, pageActor) {
|
||||||
|
let titleActor = new St.Button({ label: label,
|
||||||
|
style_class: 'view-tab-title' });
|
||||||
|
titleActor.connect('clicked', Lang.bind(this, this._activate));
|
||||||
|
|
||||||
|
BaseTab.prototype._init.call(this, titleActor, pageActor);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
function SearchTab() {
|
||||||
|
this._init();
|
||||||
|
}
|
||||||
|
|
||||||
|
SearchTab.prototype = {
|
||||||
|
__proto__: BaseTab.prototype,
|
||||||
|
|
||||||
|
_init: function() {
|
||||||
|
this._searchActive = false;
|
||||||
|
this._searchPending = false;
|
||||||
|
this._keyPressId = 0;
|
||||||
|
this._searchTimeoutId = 0;
|
||||||
|
|
||||||
|
this._searchSystem = new Search.SearchSystem();
|
||||||
|
|
||||||
|
this._searchEntry = new SearchEntry();
|
||||||
|
this._searchResults = new SearchDisplay.SearchResults(this._searchSystem);
|
||||||
|
BaseTab.prototype._init.call(this,
|
||||||
|
this._searchEntry.actor,
|
||||||
|
this._searchResults.actor);
|
||||||
|
this._searchEntry.entry.connect('text-changed',
|
||||||
|
Lang.bind(this, this._onTextChanged));
|
||||||
|
this._searchEntry.entry.connect('activate', Lang.bind(this, function (se) {
|
||||||
|
if (this._searchTimeoutId > 0) {
|
||||||
|
Mainloop.source_remove(this._searchTimeoutId);
|
||||||
|
this._doSearch();
|
||||||
|
}
|
||||||
|
this._searchResults.activateSelected();
|
||||||
|
return true;
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
|
||||||
|
setFindAsYouType: function(enabled) {
|
||||||
|
if (enabled)
|
||||||
|
this._searchEntry.show();
|
||||||
|
else
|
||||||
|
this._searchEntry.hide();
|
||||||
|
},
|
||||||
|
|
||||||
|
show: function() {
|
||||||
|
BaseTab.prototype.show.call(this);
|
||||||
|
|
||||||
|
if (this._keyPressId == 0)
|
||||||
|
this._keyPressId = global.stage.connect('key-press-event',
|
||||||
|
Lang.bind(this, this._onKeyPress));
|
||||||
|
},
|
||||||
|
|
||||||
|
hide: function() {
|
||||||
|
BaseTab.prototype.hide.call(this);
|
||||||
|
|
||||||
|
if (this._keyPressId > 0) {
|
||||||
|
global.stage.disconnect(this._keyPressId);
|
||||||
|
this._keyPressId = 0;
|
||||||
|
}
|
||||||
|
this._searchEntry.reset();
|
||||||
|
},
|
||||||
|
|
||||||
|
addSearchProvider: function(provider) {
|
||||||
|
this._searchSystem.registerProvider(provider);
|
||||||
|
this._searchResults.createProviderMeta(provider);
|
||||||
|
},
|
||||||
|
|
||||||
|
_onTextChanged: function (se, prop) {
|
||||||
|
let searchPreviouslyActive = this._searchActive;
|
||||||
|
this._searchActive = this._searchEntry.isActive();
|
||||||
|
this._searchPending = this._searchActive && !searchPreviouslyActive;
|
||||||
|
if (this._searchPending) {
|
||||||
|
this._searchResults.startingSearch();
|
||||||
|
}
|
||||||
|
if (this._searchActive) {
|
||||||
|
this._activate();
|
||||||
|
} else {
|
||||||
|
this.emit('search-cancelled');
|
||||||
|
}
|
||||||
|
if (!this._searchActive) {
|
||||||
|
if (this._searchTimeoutId > 0) {
|
||||||
|
Mainloop.source_remove(this._searchTimeoutId);
|
||||||
|
this._searchTimeoutId = 0;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this._searchTimeoutId > 0)
|
||||||
|
return;
|
||||||
|
this._searchTimeoutId = Mainloop.timeout_add(150, Lang.bind(this, this._doSearch));
|
||||||
|
},
|
||||||
|
|
||||||
|
_onKeyPress: function(stage, event) {
|
||||||
|
// If neither the stage nor the search entry have key focus, some
|
||||||
|
// "special" actor grabbed the focus (run dialog, looking glass);
|
||||||
|
// we don't want to interfere with that
|
||||||
|
let focus = stage.get_key_focus();
|
||||||
|
if (focus != stage && focus != this._searchEntry.entry)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
let symbol = event.get_key_symbol();
|
||||||
|
if (symbol == Clutter.Up) {
|
||||||
|
if (!this._searchActive)
|
||||||
|
return true;
|
||||||
|
this._searchResults.selectUp(false);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} else if (symbol == Clutter.Down) {
|
||||||
|
if (!this._searchActive)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
this._searchResults.selectDown(false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
_doSearch: function () {
|
||||||
|
this._searchTimeoutId = 0;
|
||||||
|
let text = this._searchEntry.getText();
|
||||||
|
this._searchResults.updateSearch(text);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
function ViewSelector() {
|
||||||
|
this._init();
|
||||||
|
}
|
||||||
|
|
||||||
|
ViewSelector.prototype = {
|
||||||
|
_init : function() {
|
||||||
|
this.actor = new St.BoxLayout({ name: 'viewSelector',
|
||||||
|
vertical: true });
|
||||||
|
|
||||||
|
// The tab bar is located at the top of the view selector and
|
||||||
|
// holds both "normal" tab labels and the search entry. The former
|
||||||
|
// is left aligned, the latter right aligned - unless the text
|
||||||
|
// direction is RTL, in which case the order is reversed.
|
||||||
|
this._tabBar = new Shell.GenericContainer();
|
||||||
|
this._tabBar.connect('get-preferred-width',
|
||||||
|
Lang.bind(this, this._getPreferredTabBarWidth));
|
||||||
|
this._tabBar.connect('get-preferred-height',
|
||||||
|
Lang.bind(this, this._getPreferredTabBarHeight));
|
||||||
|
this._tabBar.connect('allocate',
|
||||||
|
Lang.bind(this, this._allocateTabBar));
|
||||||
|
this.actor.add(this._tabBar);
|
||||||
|
|
||||||
|
// Box to hold "normal" tab labels
|
||||||
|
this._tabBox = new St.BoxLayout({ name: 'viewSelectorTabBar' });
|
||||||
|
this._tabBar.add_actor(this._tabBox);
|
||||||
|
|
||||||
|
// The searchArea just holds the entry
|
||||||
|
this._searchArea = new St.Bin({ name: 'searchArea' });
|
||||||
|
this._tabBar.add_actor(this._searchArea);
|
||||||
|
|
||||||
|
// The page area holds the tab pages. Every page is given the
|
||||||
|
// area's full allocation, so that the pages would appear on top
|
||||||
|
// of each other if the inactive ones weren't hidden.
|
||||||
|
this._pageArea = new Shell.Stack();
|
||||||
|
this.actor.add(this._pageArea, { x_fill: true,
|
||||||
|
y_fill: true,
|
||||||
|
expand: true });
|
||||||
|
|
||||||
|
this._tabs = [];
|
||||||
|
this._activeTab = null;
|
||||||
|
|
||||||
|
this._searchTab = new SearchTab();
|
||||||
|
this._searchArea.set_child(this._searchTab.title);
|
||||||
|
this._addTab(this._searchTab);
|
||||||
|
|
||||||
|
this._searchTab.connect('search-cancelled', Lang.bind(this,
|
||||||
|
function() {
|
||||||
|
this._switchTab(this._activeTab);
|
||||||
|
}));
|
||||||
|
|
||||||
|
this._keyPressId = 0;
|
||||||
|
this._itemDragBeginId = 0;
|
||||||
|
this._overviewHidingId = 0;
|
||||||
|
|
||||||
|
// Public constraints which may be used to tie actors' height or
|
||||||
|
// vertical position to the current tab's content; as the content's
|
||||||
|
// height and position depend on the view selector's style properties
|
||||||
|
// (e.g. font size, padding, spacing, ...) it would be extremely hard
|
||||||
|
// and ugly to get these from the outside. While it would be possible
|
||||||
|
// to use position and height properties directly, outside code would
|
||||||
|
// need to ensure that the content is properly allocated before
|
||||||
|
// accessing the properties.
|
||||||
|
this.constrainY = new Clutter.BindConstraint({ source: this._pageArea,
|
||||||
|
coordinate: Clutter.BindCoordinate.Y });
|
||||||
|
this.constrainHeight = new Clutter.BindConstraint({ source: this._pageArea,
|
||||||
|
coordinate: Clutter.BindCoordinate.HEIGHT });
|
||||||
|
},
|
||||||
|
|
||||||
|
_addTab: function(tab) {
|
||||||
|
tab.page.hide();
|
||||||
|
this._pageArea.add_actor(tab.page);
|
||||||
|
tab.connect('activated', Lang.bind(this, function(tab) {
|
||||||
|
this._switchTab(tab);
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
|
||||||
|
addViewTab: function(title, pageActor) {
|
||||||
|
let viewTab = new ViewTab(title, pageActor);
|
||||||
|
this._tabs.push(viewTab);
|
||||||
|
this._tabBox.add(viewTab.title);
|
||||||
|
this._addTab(viewTab);
|
||||||
|
},
|
||||||
|
|
||||||
|
_switchTab: function(tab) {
|
||||||
|
if (this._activeTab && this._activeTab.visible) {
|
||||||
|
if (this._activeTab == tab)
|
||||||
|
return;
|
||||||
|
this._activeTab.title.remove_style_pseudo_class('selected');
|
||||||
|
this._activeTab.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tab != this._searchTab) {
|
||||||
|
tab.title.add_style_pseudo_class('selected');
|
||||||
|
this._activeTab = tab;
|
||||||
|
if (this._searchTab.visible) {
|
||||||
|
this._searchTab.hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tab.visible)
|
||||||
|
tab.show();
|
||||||
|
|
||||||
|
// Pull a Meg Ryan:
|
||||||
|
if (Main.overview && Main.overview.workspaces) {
|
||||||
|
if (tab != this._tabs[0]) {
|
||||||
|
Tweener.addTween(Main.overview.workspaces.actor,
|
||||||
|
{ opacity: 0,
|
||||||
|
time: 0.1,
|
||||||
|
transition: 'easeOutQuad',
|
||||||
|
onComplete: Lang.bind(this,
|
||||||
|
function() {
|
||||||
|
Main.overview.workspaces.actor.hide();
|
||||||
|
Main.overview.workspaces.actor.opacity = 255;
|
||||||
|
})
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
Main.overview.workspaces.actor.opacity = 0;
|
||||||
|
Main.overview.workspaces.actor.show();
|
||||||
|
Tweener.addTween(Main.overview.workspaces.actor,
|
||||||
|
{ opacity: 255,
|
||||||
|
time: 0.1,
|
||||||
|
transition: 'easeOutQuad' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_switchDefaultTab: function() {
|
||||||
|
if (this._tabs.length > 0)
|
||||||
|
this._switchTab(this._tabs[0]);
|
||||||
|
},
|
||||||
|
|
||||||
|
_nextTab: function() {
|
||||||
|
if (this._tabs.length == 0 ||
|
||||||
|
this._tabs[this._tabs.length - 1] == this._activeTab)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (let i = 0; i < this._tabs.length; i++)
|
||||||
|
if (this._tabs[i] == this._activeTab) {
|
||||||
|
this._switchTab(this._tabs[i + 1]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_prevTab: function() {
|
||||||
|
if (this._tabs.length == 0 || this._tabs[0] == this._activeTab)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (let i = 0; i < this._tabs.length; i++)
|
||||||
|
if (this._tabs[i] == this._activeTab) {
|
||||||
|
this._switchTab(this._tabs[i - 1]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_getPreferredTabBarWidth: function(box, forHeight, alloc) {
|
||||||
|
let children = box.get_children();
|
||||||
|
for (let i = 0; i < children.length; i++) {
|
||||||
|
let [childMin, childNat] = children[i].get_preferred_width(forHeight);
|
||||||
|
alloc.min_size += childMin;
|
||||||
|
alloc.natural_size += childNat;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_getPreferredTabBarHeight: function(box, forWidth, alloc) {
|
||||||
|
let children = box.get_children();
|
||||||
|
for (let i = 0; i < children.length; i++) {
|
||||||
|
let [childMin, childNatural] = children[i].get_preferred_height(forWidth);
|
||||||
|
if (childMin > alloc.min_size)
|
||||||
|
alloc.min_size = childMin;
|
||||||
|
if (childNatural > alloc.natural_size)
|
||||||
|
alloc.natural_size = childNatural;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_allocateTabBar: function(container, box, flags) {
|
||||||
|
let allocWidth = box.x2 - box.x1;
|
||||||
|
let allocHeight = box.y2 - box.y1;
|
||||||
|
|
||||||
|
let [searchMinWidth, searchNatWidth] = this._searchArea.get_preferred_width(-1);
|
||||||
|
let [barMinWidth, barNatWidth] = this._tabBox.get_preferred_width(-1);
|
||||||
|
let childBox = new Clutter.ActorBox();
|
||||||
|
childBox.y1 = 0;
|
||||||
|
childBox.y2 = allocHeight;
|
||||||
|
if (this.actor.get_direction() == St.TextDirection.RTL) {
|
||||||
|
childBox.x1 = allocWidth - barNatWidth;
|
||||||
|
childBox.x2 = allocWidth;
|
||||||
|
} else {
|
||||||
|
childBox.x1 = 0;
|
||||||
|
childBox.x2 = barNatWidth;
|
||||||
|
}
|
||||||
|
this._tabBox.allocate(childBox, flags);
|
||||||
|
|
||||||
|
if (this.actor.get_direction() == St.TextDirection.RTL) {
|
||||||
|
childBox.x1 = 0;
|
||||||
|
childBox.x2 = searchNatWidth;
|
||||||
|
} else {
|
||||||
|
childBox.x1 = allocWidth - searchNatWidth;
|
||||||
|
childBox.x2 = allocWidth;
|
||||||
|
}
|
||||||
|
this._searchArea.allocate(childBox, flags);
|
||||||
|
|
||||||
|
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this,
|
||||||
|
function() {
|
||||||
|
this.constrainY.offset = this.actor.y;
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
|
||||||
|
_onKeyPress: function(stage, event) {
|
||||||
|
// Only process events if the stage has key focus - search is handled
|
||||||
|
// by the search tab, and we do not want to interfere with "special"
|
||||||
|
// actors grabbing focus (run dialog, looking glass, notifications).
|
||||||
|
let focus = stage.get_key_focus();
|
||||||
|
if (focus != stage)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
let modifiers = Shell.get_event_state(event);
|
||||||
|
let symbol = event.get_key_symbol();
|
||||||
|
if (symbol == Clutter.Escape) {
|
||||||
|
Main.overview.hide();
|
||||||
|
return true;
|
||||||
|
} else if (modifiers & Clutter.ModifierType.CONTROL_MASK) {
|
||||||
|
if (symbol == Clutter.Page_Up) {
|
||||||
|
if (!this._searchActive)
|
||||||
|
this._prevTab();
|
||||||
|
return true;
|
||||||
|
} else if (symbol == Clutter.Page_Down) {
|
||||||
|
if (!this._searchActive)
|
||||||
|
this._nextTab();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
addSearchProvider: function(provider) {
|
||||||
|
this._searchTab.addSearchProvider(provider);
|
||||||
|
},
|
||||||
|
|
||||||
|
show: function() {
|
||||||
|
this._searchTab.setFindAsYouType(true);
|
||||||
|
|
||||||
|
if (this._itemDragBeginId == 0)
|
||||||
|
this._itemDragBeginId = Main.overview.connect('item-drag-begin',
|
||||||
|
Lang.bind(this, this._switchDefaultTab));
|
||||||
|
if (this._overviewHidingId == 0)
|
||||||
|
this._overviewHidingId = Main.overview.connect('hiding',
|
||||||
|
Lang.bind(this, this._switchDefaultTab));
|
||||||
|
if (this._keyPressId == 0)
|
||||||
|
this._keyPressId = global.stage.connect('key-press-event',
|
||||||
|
Lang.bind(this, this._onKeyPress));
|
||||||
|
|
||||||
|
this._switchDefaultTab();
|
||||||
|
},
|
||||||
|
|
||||||
|
hide: function() {
|
||||||
|
this._searchTab.setFindAsYouType(false);
|
||||||
|
|
||||||
|
if (this._keyPressId > 0) {
|
||||||
|
global.stage.disconnect(this._keyPressId);
|
||||||
|
this._keyPressId = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._itemDragBeginId > 0) {
|
||||||
|
Main.overview.disconnect(this._itemDragBeginId);
|
||||||
|
this._itemDragBeginId = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._overviewHidingId > 0) {
|
||||||
|
Main.overview.disconnect(this._overviewHidingId);
|
||||||
|
this._overviewHidingId = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Signals.addSignalMethods(ViewSelector.prototype);
|
@ -20,9 +20,6 @@ const FOCUS_ANIMATION_TIME = 0.15;
|
|||||||
|
|
||||||
const WINDOW_DND_SIZE = 256;
|
const WINDOW_DND_SIZE = 256;
|
||||||
|
|
||||||
const FRAME_COLOR = new Clutter.Color();
|
|
||||||
FRAME_COLOR.from_pixel(0xffffffff);
|
|
||||||
|
|
||||||
const SCROLL_SCALE_AMOUNT = 100 / 5;
|
const SCROLL_SCALE_AMOUNT = 100 / 5;
|
||||||
|
|
||||||
const LIGHTBOX_FADE_TIME = 0.1;
|
const LIGHTBOX_FADE_TIME = 0.1;
|
||||||
@ -54,11 +51,6 @@ function _clamp(value, min, max) {
|
|||||||
return Math.max(min, Math.min(max, value));
|
return Math.max(min, Math.min(max, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Spacing between workspaces. At the moment, the same spacing is used
|
|
||||||
// in both zoomed-in and zoomed-out views; this is slightly
|
|
||||||
// metaphor-breaking, but the alternatives are also weird.
|
|
||||||
const GRID_SPACING = 15;
|
|
||||||
const FRAME_SIZE = GRID_SPACING / 3;
|
|
||||||
|
|
||||||
function ScaledPoint(x, y, scaleX, scaleY) {
|
function ScaledPoint(x, y, scaleX, scaleY) {
|
||||||
[this.x, this.y, this.scaleX, this.scaleY] = arguments;
|
[this.x, this.y, this.scaleX, this.scaleY] = arguments;
|
||||||
@ -289,76 +281,9 @@ WindowClone.prototype = {
|
|||||||
this.emit('drag-end');
|
this.emit('drag-end');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Signals.addSignalMethods(WindowClone.prototype);
|
Signals.addSignalMethods(WindowClone.prototype);
|
||||||
|
|
||||||
|
|
||||||
function DesktopClone(window) {
|
|
||||||
this._init(window);
|
|
||||||
}
|
|
||||||
|
|
||||||
DesktopClone.prototype = {
|
|
||||||
_init : function(window) {
|
|
||||||
this.actor = new Clutter.Group({ reactive: true });
|
|
||||||
|
|
||||||
let background = new Clutter.Clone({ source: global.background_actor });
|
|
||||||
this.actor.add_actor(background);
|
|
||||||
|
|
||||||
if (window) {
|
|
||||||
this._desktop = new Clutter.Clone({ source: window.get_texture() });
|
|
||||||
this.actor.add_actor(this._desktop);
|
|
||||||
this._desktop.hide();
|
|
||||||
} else {
|
|
||||||
this._desktop = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.actor.connect('button-release-event',
|
|
||||||
Lang.bind(this, this._onButtonRelease));
|
|
||||||
},
|
|
||||||
|
|
||||||
zoomFromOverview: function(fadeInIcons) {
|
|
||||||
if (this._desktop == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (fadeInIcons) {
|
|
||||||
this._desktop.opacity = 0;
|
|
||||||
this._desktop.show();
|
|
||||||
Tweener.addTween(this._desktop,
|
|
||||||
{ opacity: 255,
|
|
||||||
time: Overview.ANIMATION_TIME,
|
|
||||||
transition: 'easeOutQuad' });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
zoomToOverview: function(fadeOutIcons) {
|
|
||||||
if (this._desktop == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (fadeOutIcons) {
|
|
||||||
this._desktop.opacity = 255;
|
|
||||||
this._desktop.show();
|
|
||||||
Tweener.addTween(this._desktop,
|
|
||||||
{ opacity: 0,
|
|
||||||
time: Overview.ANIMATION_TIME,
|
|
||||||
transition: 'easeOutQuad',
|
|
||||||
onComplete: Lang.bind(this,
|
|
||||||
function() {
|
|
||||||
this._desktop.hide();
|
|
||||||
})
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this._desktop.hide();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_onButtonRelease : function (actor, event) {
|
|
||||||
this.emit('selected', event.get_time());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Signals.addSignalMethods(DesktopClone.prototype);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @windowClone: Corresponding window clone
|
* @windowClone: Corresponding window clone
|
||||||
* @parentActor: The actor which will be the parent of all overlay items
|
* @parentActor: The actor which will be the parent of all overlay items
|
||||||
@ -561,7 +486,6 @@ WindowOverlay.prototype = {
|
|||||||
this._parentActor.queue_relayout();
|
this._parentActor.queue_relayout();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Signals.addSignalMethods(WindowOverlay.prototype);
|
Signals.addSignalMethods(WindowOverlay.prototype);
|
||||||
|
|
||||||
const WindowPositionFlags = {
|
const WindowPositionFlags = {
|
||||||
@ -585,10 +509,20 @@ Workspace.prototype = {
|
|||||||
// Without this the drop area will be overlapped.
|
// Without this the drop area will be overlapped.
|
||||||
this._windowOverlaysGroup.set_size(0, 0);
|
this._windowOverlaysGroup.set_size(0, 0);
|
||||||
|
|
||||||
this.actor = new Clutter.Group();
|
this.actor = new Clutter.Group({ reactive: true });
|
||||||
this.actor._delegate = this;
|
this.actor._delegate = this;
|
||||||
|
|
||||||
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
|
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
|
||||||
|
this.actor.connect('button-release-event', Lang.bind(this,
|
||||||
|
function(actor, event) {
|
||||||
|
// Only switch to the workspace when there's no application
|
||||||
|
// windows open. The problem is that it's too easy to miss
|
||||||
|
// an app window and get the wrong one focused.
|
||||||
|
if (this._windows.length == 0) {
|
||||||
|
this.metaWorkspace.activate(event.get_time());
|
||||||
|
Main.overview.hide();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
// Items in _windowOverlaysGroup should not be scaled, so we don't
|
// Items in _windowOverlaysGroup should not be scaled, so we don't
|
||||||
// add them to this.actor, but to its parent whenever it changes
|
// add them to this.actor, but to its parent whenever it changes
|
||||||
@ -604,35 +538,10 @@ Workspace.prototype = {
|
|||||||
|
|
||||||
let windows = global.get_window_actors().filter(this._isMyWindow, this);
|
let windows = global.get_window_actors().filter(this._isMyWindow, this);
|
||||||
|
|
||||||
// Find the desktop window
|
|
||||||
for (let i = 0; i < windows.length; i++) {
|
|
||||||
if (windows[i].meta_window.get_window_type() == Meta.WindowType.DESKTOP) {
|
|
||||||
this._desktop = new DesktopClone(windows[i]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// If there wasn't one, fake it
|
|
||||||
if (!this._desktop)
|
|
||||||
this._desktop = new DesktopClone();
|
|
||||||
|
|
||||||
this._desktop.connect('selected',
|
|
||||||
Lang.bind(this,
|
|
||||||
function(clone, time) {
|
|
||||||
// Only switch to the workspace when there's no application windows
|
|
||||||
// open (we always have one window for the desktop). The problem
|
|
||||||
// is that it's too easy to miss an app window and get the wrong
|
|
||||||
// one focused.
|
|
||||||
if (this._windows.length == 1) {
|
|
||||||
this.metaWorkspace.activate(time);
|
|
||||||
Main.overview.hide();
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
this.actor.add_actor(this._desktop.actor);
|
|
||||||
|
|
||||||
// Create clones for remaining windows that should be
|
// Create clones for remaining windows that should be
|
||||||
// visible in the Overview
|
// visible in the Overview
|
||||||
this._windows = [this._desktop];
|
this._windows = [];
|
||||||
this._windowOverlays = [ null ];
|
this._windowOverlays = [];
|
||||||
for (let i = 0; i < windows.length; i++) {
|
for (let i = 0; i < windows.length; i++) {
|
||||||
if (this._isOverviewWindow(windows[i])) {
|
if (this._isOverviewWindow(windows[i])) {
|
||||||
this._addWindowClone(windows[i]);
|
this._addWindowClone(windows[i]);
|
||||||
@ -651,8 +560,6 @@ Workspace.prototype = {
|
|||||||
|
|
||||||
this._visible = false;
|
this._visible = false;
|
||||||
|
|
||||||
this._frame = null;
|
|
||||||
|
|
||||||
this.leavingOverview = false;
|
this.leavingOverview = false;
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -714,9 +621,6 @@ Workspace.prototype = {
|
|||||||
this._lightbox.show();
|
this._lightbox.show();
|
||||||
else
|
else
|
||||||
this._lightbox.hide();
|
this._lightbox.hide();
|
||||||
|
|
||||||
if (this._frame)
|
|
||||||
this._frame.set_opacity(showLightbox ? 150 : 255);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -737,32 +641,6 @@ Workspace.prototype = {
|
|||||||
this._lightbox.highlight(actor);
|
this._lightbox.highlight(actor);
|
||||||
},
|
},
|
||||||
|
|
||||||
// Mark the workspace selected/not-selected
|
|
||||||
setSelected : function(selected) {
|
|
||||||
// Don't draw a frame if we only have one workspace
|
|
||||||
if (selected && global.screen.n_workspaces > 1) {
|
|
||||||
if (this._frame)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// FIXME: do something cooler-looking using clutter-cairo
|
|
||||||
this._frame = new Clutter.Rectangle({ color: FRAME_COLOR });
|
|
||||||
this.actor.add_actor(this._frame);
|
|
||||||
this._frame.set_position(this._desktop.actor.x - FRAME_SIZE / this.actor.scale_x,
|
|
||||||
this._desktop.actor.y - FRAME_SIZE / this.actor.scale_y);
|
|
||||||
this._frame.set_size(this._desktop.actor.width + 2 * FRAME_SIZE / this.actor.scale_x,
|
|
||||||
this._desktop.actor.height + 2 * FRAME_SIZE / this.actor.scale_y);
|
|
||||||
this._frame.lower_bottom();
|
|
||||||
|
|
||||||
this._framePosHandler = this.actor.connect('notify::scale-x', Lang.bind(this, this._updateFramePosition));
|
|
||||||
} else {
|
|
||||||
if (!this._frame)
|
|
||||||
return;
|
|
||||||
this.actor.disconnect(this._framePosHandler);
|
|
||||||
this._frame.destroy();
|
|
||||||
this._frame = null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* setReactive:
|
* setReactive:
|
||||||
* @reactive: %true iff the workspace should be reactive
|
* @reactive: %true iff the workspace should be reactive
|
||||||
@ -770,14 +648,7 @@ Workspace.prototype = {
|
|||||||
* Set the workspace (desktop) reactive
|
* Set the workspace (desktop) reactive
|
||||||
**/
|
**/
|
||||||
setReactive: function(reactive) {
|
setReactive: function(reactive) {
|
||||||
this._desktop.actor.reactive = reactive;
|
this.actor.reactive = reactive;
|
||||||
},
|
|
||||||
|
|
||||||
_updateFramePosition : function() {
|
|
||||||
this._frame.set_position(this._desktop.actor.x - FRAME_SIZE / this.actor.scale_x,
|
|
||||||
this._desktop.actor.y - FRAME_SIZE / this.actor.scale_y);
|
|
||||||
this._frame.set_size(this._desktop.actor.width + 2 * FRAME_SIZE / this.actor.scale_x,
|
|
||||||
this._desktop.actor.height + 2 * FRAME_SIZE / this.actor.scale_y);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_isCloneVisible: function(clone) {
|
_isCloneVisible: function(clone) {
|
||||||
@ -788,7 +659,7 @@ Workspace.prototype = {
|
|||||||
* _getVisibleClones:
|
* _getVisibleClones:
|
||||||
*
|
*
|
||||||
* Returns a list WindowClone objects where the clone isn't filtered
|
* Returns a list WindowClone objects where the clone isn't filtered
|
||||||
* out by any application filter. The clone for the desktop is excluded.
|
* out by any application filter.
|
||||||
* The returned array will always be newly allocated; it is not in any
|
* The returned array will always be newly allocated; it is not in any
|
||||||
* defined order, and thus it's convenient to call .sort() with your
|
* defined order, and thus it's convenient to call .sort() with your
|
||||||
* choice of sorting function.
|
* choice of sorting function.
|
||||||
@ -796,7 +667,7 @@ Workspace.prototype = {
|
|||||||
_getVisibleClones: function() {
|
_getVisibleClones: function() {
|
||||||
let visible = [];
|
let visible = [];
|
||||||
|
|
||||||
for (let i = 1; i < this._windows.length; i++) {
|
for (let i = 0; i < this._windows.length; i++) {
|
||||||
let clone = this._windows[i];
|
let clone = this._windows[i];
|
||||||
|
|
||||||
if (!this._isCloneVisible(clone))
|
if (!this._isCloneVisible(clone))
|
||||||
@ -808,7 +679,7 @@ Workspace.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
_resetCloneVisibility: function () {
|
_resetCloneVisibility: function () {
|
||||||
for (let i = 1; i < this._windows.length; i++) {
|
for (let i = 0; i < this._windows.length; i++) {
|
||||||
let clone = this._windows[i];
|
let clone = this._windows[i];
|
||||||
let overlay = this._windowOverlays[i];
|
let overlay = this._windowOverlays[i];
|
||||||
|
|
||||||
@ -1007,9 +878,9 @@ Workspace.prototype = {
|
|||||||
let buttonOuterHeight, captionHeight;
|
let buttonOuterHeight, captionHeight;
|
||||||
let buttonOuterWidth = 0;
|
let buttonOuterWidth = 0;
|
||||||
|
|
||||||
if (this._windowOverlays[1]) {
|
if (this._windowOverlays[0]) {
|
||||||
[buttonOuterHeight, captionHeight] = this._windowOverlays[1].chromeHeights();
|
[buttonOuterHeight, captionHeight] = this._windowOverlays[0].chromeHeights();
|
||||||
buttonOuterWidth = this._windowOverlays[1].chromeWidth() / this.scale;
|
buttonOuterWidth = this._windowOverlays[0].chromeWidth() / this.scale;
|
||||||
} else
|
} else
|
||||||
[buttonOuterHeight, captionHeight] = [0, 0];
|
[buttonOuterHeight, captionHeight] = [0, 0];
|
||||||
buttonOuterHeight /= this.scale;
|
buttonOuterHeight /= this.scale;
|
||||||
@ -1157,8 +1028,8 @@ Workspace.prototype = {
|
|||||||
// be after the workspace animation finishes.
|
// be after the workspace animation finishes.
|
||||||
let [cloneX, cloneY] = clone.actor.get_position();
|
let [cloneX, cloneY] = clone.actor.get_position();
|
||||||
let [cloneWidth, cloneHeight] = clone.actor.get_size();
|
let [cloneWidth, cloneHeight] = clone.actor.get_size();
|
||||||
cloneX = this.gridX + this.scale * cloneX;
|
cloneX = this.x + this.scale * cloneX;
|
||||||
cloneY = this.gridY + this.scale * cloneY;
|
cloneY = this.y + this.scale * cloneY;
|
||||||
cloneWidth = this.scale * clone.actor.scale_x * cloneWidth;
|
cloneWidth = this.scale * clone.actor.scale_x * cloneWidth;
|
||||||
cloneHeight = this.scale * clone.actor.scale_y * cloneHeight;
|
cloneHeight = this.scale * clone.actor.scale_y * cloneHeight;
|
||||||
|
|
||||||
@ -1172,7 +1043,7 @@ Workspace.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
_fadeInAllOverlays: function() {
|
_fadeInAllOverlays: function() {
|
||||||
for (let i = 1; i < this._windows.length; i++) {
|
for (let i = 0; i < this._windows.length; i++) {
|
||||||
let clone = this._windows[i];
|
let clone = this._windows[i];
|
||||||
let overlay = this._windowOverlays[i];
|
let overlay = this._windowOverlays[i];
|
||||||
if (this._showOnlyWindows != null && !(clone.metaWindow in this._showOnlyWindows))
|
if (this._showOnlyWindows != null && !(clone.metaWindow in this._showOnlyWindows))
|
||||||
@ -1182,7 +1053,7 @@ Workspace.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
_hideAllOverlays: function() {
|
_hideAllOverlays: function() {
|
||||||
for (let i = 1; i< this._windows.length; i++) {
|
for (let i = 0; i < this._windows.length; i++) {
|
||||||
let overlay = this._windowOverlays[i];
|
let overlay = this._windowOverlays[i];
|
||||||
overlay.hide();
|
overlay.hide();
|
||||||
}
|
}
|
||||||
@ -1197,8 +1068,8 @@ Workspace.prototype = {
|
|||||||
let wsHeight = this.actor.height * this.scale;
|
let wsHeight = this.actor.height * this.scale;
|
||||||
|
|
||||||
let pointerHasMoved = (this._cursorX != x && this._cursorY != y);
|
let pointerHasMoved = (this._cursorX != x && this._cursorY != y);
|
||||||
let inWorkspace = (this.gridX < x && x < this.gridX + wsWidth &&
|
let inWorkspace = (this.x < x && x < this.x + wsWidth &&
|
||||||
this.gridY < y && y < this.gridY + wsHeight);
|
this.y < y && y < this.y + wsHeight);
|
||||||
|
|
||||||
if (pointerHasMoved && inWorkspace) {
|
if (pointerHasMoved && inWorkspace) {
|
||||||
// store current cursor position
|
// store current cursor position
|
||||||
@ -1309,8 +1180,8 @@ Workspace.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// check for maximized windows on the workspace
|
// check for maximized windows on the workspace
|
||||||
_haveMaximizedWindows: function() {
|
hasMaximizedWindows: function() {
|
||||||
for (let i = 1; i < this._windows.length; i++) {
|
for (let i = 0; i < this._windows.length; i++) {
|
||||||
let metaWindow = this._windows[i].metaWindow;
|
let metaWindow = this._windows[i].metaWindow;
|
||||||
if (metaWindow.showing_on_its_workspace() &&
|
if (metaWindow.showing_on_its_workspace() &&
|
||||||
metaWindow.maximized_horizontally &&
|
metaWindow.maximized_horizontally &&
|
||||||
@ -1322,7 +1193,7 @@ Workspace.prototype = {
|
|||||||
|
|
||||||
// Animate the full-screen to Overview transition.
|
// Animate the full-screen to Overview transition.
|
||||||
zoomToOverview : function() {
|
zoomToOverview : function() {
|
||||||
this.actor.set_position(this.gridX, this.gridY);
|
this.actor.set_position(this.x, this.y);
|
||||||
this.actor.set_scale(this.scale, this.scale);
|
this.actor.set_scale(this.scale, this.scale);
|
||||||
|
|
||||||
// Position and scale the windows.
|
// Position and scale the windows.
|
||||||
@ -1331,12 +1202,6 @@ Workspace.prototype = {
|
|||||||
else
|
else
|
||||||
this.positionWindows(WindowPositionFlags.ZOOM);
|
this.positionWindows(WindowPositionFlags.ZOOM);
|
||||||
|
|
||||||
let active = global.screen.get_active_workspace();
|
|
||||||
let fadeInIcons = (Main.overview.animationInProgress &&
|
|
||||||
active == this.metaWorkspace &&
|
|
||||||
!this._haveMaximizedWindows());
|
|
||||||
this._desktop.zoomToOverview(fadeInIcons);
|
|
||||||
|
|
||||||
this._visible = true;
|
this._visible = true;
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1354,7 +1219,7 @@ Workspace.prototype = {
|
|||||||
this._doneLeavingOverview));
|
this._doneLeavingOverview));
|
||||||
|
|
||||||
// Position and scale the windows.
|
// Position and scale the windows.
|
||||||
for (let i = 1; i < this._windows.length; i++) {
|
for (let i = 0; i < this._windows.length; i++) {
|
||||||
let clone = this._windows[i];
|
let clone = this._windows[i];
|
||||||
|
|
||||||
clone.zoomFromOverview();
|
clone.zoomFromOverview();
|
||||||
@ -1383,77 +1248,9 @@ Workspace.prototype = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let active = global.screen.get_active_workspace();
|
|
||||||
let fadeOutIcons = (active == this.metaWorkspace &&
|
|
||||||
!this._haveMaximizedWindows());
|
|
||||||
this._desktop.zoomFromOverview(fadeOutIcons);
|
|
||||||
|
|
||||||
this._visible = false;
|
this._visible = false;
|
||||||
},
|
},
|
||||||
|
|
||||||
// Animates grid shrinking/expanding when a row or column
|
|
||||||
// of workspaces is added or removed
|
|
||||||
resizeToGrid : function (oldScale) {
|
|
||||||
this._hideAllOverlays();
|
|
||||||
Tweener.addTween(this.actor,
|
|
||||||
{ x: this.gridX,
|
|
||||||
y: this.gridY,
|
|
||||||
scale_x: this.scale,
|
|
||||||
scale_y: this.scale,
|
|
||||||
time: Overview.ANIMATION_TIME,
|
|
||||||
transition: 'easeOutQuad',
|
|
||||||
onComplete: Lang.bind(this, this._fadeInAllOverlays)
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
// Animates the addition of a new (empty) workspace
|
|
||||||
slideIn : function(oldScale) {
|
|
||||||
if (this.gridCol > this.gridRow) {
|
|
||||||
this.actor.set_position(global.screen_width, this.gridY);
|
|
||||||
this.actor.set_scale(oldScale, oldScale);
|
|
||||||
} else {
|
|
||||||
this.actor.set_position(this.gridX, global.screen_height);
|
|
||||||
this.actor.set_scale(this.scale, this.scale);
|
|
||||||
}
|
|
||||||
Tweener.addTween(this.actor,
|
|
||||||
{ x: this.gridX,
|
|
||||||
y: this.gridY,
|
|
||||||
scale_x: this.scale,
|
|
||||||
scale_y: this.scale,
|
|
||||||
time: Overview.ANIMATION_TIME,
|
|
||||||
transition: 'easeOutQuad'
|
|
||||||
});
|
|
||||||
|
|
||||||
this._visible = true;
|
|
||||||
},
|
|
||||||
|
|
||||||
// Animates the removal of a workspace
|
|
||||||
slideOut : function(onComplete) {
|
|
||||||
let destX = this.actor.x, destY = this.actor.y;
|
|
||||||
|
|
||||||
this._hideAllOverlays();
|
|
||||||
|
|
||||||
if (this.gridCol > this.gridRow)
|
|
||||||
destX = global.screen_width;
|
|
||||||
else
|
|
||||||
destY = global.screen_height;
|
|
||||||
Tweener.addTween(this.actor,
|
|
||||||
{ x: destX,
|
|
||||||
y: destY,
|
|
||||||
scale_x: this.scale,
|
|
||||||
scale_y: this.scale,
|
|
||||||
time: Overview.ANIMATION_TIME,
|
|
||||||
transition: 'easeOutQuad',
|
|
||||||
onComplete: onComplete
|
|
||||||
});
|
|
||||||
|
|
||||||
this._visible = false;
|
|
||||||
|
|
||||||
// Don't let the user try to select this workspace as it's
|
|
||||||
// making its exit.
|
|
||||||
this._desktop.reactive = false;
|
|
||||||
},
|
|
||||||
|
|
||||||
destroy : function() {
|
destroy : function() {
|
||||||
this.actor.destroy();
|
this.actor.destroy();
|
||||||
},
|
},
|
||||||
@ -1475,7 +1272,7 @@ Workspace.prototype = {
|
|||||||
// their parent (this.actor), but we might have a zoomed window
|
// their parent (this.actor), but we might have a zoomed window
|
||||||
// which has been reparented to the stage - _windows[0] holds
|
// which has been reparented to the stage - _windows[0] holds
|
||||||
// the desktop window, which is never reparented
|
// the desktop window, which is never reparented
|
||||||
for (let w = 1; w < this._windows.length; w++)
|
for (let w = 0; w < this._windows.length; w++)
|
||||||
this._windows[w].destroy();
|
this._windows[w].destroy();
|
||||||
this._windows = [];
|
this._windows = [];
|
||||||
},
|
},
|
||||||
@ -1506,12 +1303,12 @@ Workspace.prototype = {
|
|||||||
Lang.bind(this, this._onCloneSelected));
|
Lang.bind(this, this._onCloneSelected));
|
||||||
clone.connect('drag-begin',
|
clone.connect('drag-begin',
|
||||||
Lang.bind(this, function(clone) {
|
Lang.bind(this, function(clone) {
|
||||||
this.emit('window-drag-begin', clone.actor);
|
Main.overview.beginWindowDrag();
|
||||||
overlay.hide();
|
overlay.hide();
|
||||||
}));
|
}));
|
||||||
clone.connect('drag-end',
|
clone.connect('drag-end',
|
||||||
Lang.bind(this, function(clone) {
|
Lang.bind(this, function(clone) {
|
||||||
this.emit('window-drag-end', clone.actor);
|
Main.overview.endWindowDrag();
|
||||||
overlay.show();
|
overlay.show();
|
||||||
}));
|
}));
|
||||||
clone.connect('zoom-start',
|
clone.connect('zoom-start',
|
||||||
@ -1534,7 +1331,7 @@ Workspace.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
_onShowOverlayClose: function (windowOverlay) {
|
_onShowOverlayClose: function (windowOverlay) {
|
||||||
for (let i = 1; i < this._windowOverlays.length; i++) {
|
for (let i = 0; i < this._windowOverlays.length; i++) {
|
||||||
let overlay = this._windowOverlays[i];
|
let overlay = this._windowOverlays[i];
|
||||||
if (overlay == windowOverlay)
|
if (overlay == windowOverlay)
|
||||||
continue;
|
continue;
|
||||||
@ -1643,11 +1440,11 @@ function _workspaceRelativeModifier(workspace) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return [ { name: 'x',
|
return [ { name: 'x',
|
||||||
parameters: { workspacePos: workspace.gridX,
|
parameters: { workspacePos: workspace.x,
|
||||||
overviewPos: overviewPosX,
|
overviewPos: overviewPosX,
|
||||||
overviewScale: overviewScale } },
|
overviewScale: overviewScale } },
|
||||||
{ name: 'y',
|
{ name: 'y',
|
||||||
parameters: { workspacePos: workspace.gridY,
|
parameters: { workspacePos: workspace.y,
|
||||||
overviewPos: overviewPosY,
|
overviewPos: overviewPosY,
|
||||||
overviewScale: overviewScale } }
|
overviewScale: overviewScale } }
|
||||||
];
|
];
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -15,6 +15,7 @@ js/ui/popupMenu.js
|
|||||||
js/ui/runDialog.js
|
js/ui/runDialog.js
|
||||||
js/ui/statusMenu.js
|
js/ui/statusMenu.js
|
||||||
js/ui/status/accessibility.js
|
js/ui/status/accessibility.js
|
||||||
|
js/ui/viewSelector.js
|
||||||
js/ui/windowAttentionHandler.js
|
js/ui/windowAttentionHandler.js
|
||||||
js/ui/workspacesView.js
|
js/ui/workspacesView.js
|
||||||
src/gvc/gvc-mixer-control.c
|
src/gvc/gvc-mixer-control.c
|
||||||
|
Loading…
Reference in New Issue
Block a user