New workspaces view
Matching the 20091114 mockup, the default workspace view is now a scrollable horizontal list, with a control to switch between this and the previous grid view. https://bugzilla.gnome.org/show_bug.cgi?id=593844
@ -21,16 +21,24 @@ dist_images_DATA = \
|
|||||||
|
|
||||||
themedir = $(pkgdatadir)/theme
|
themedir = $(pkgdatadir)/theme
|
||||||
dist_theme_DATA = \
|
dist_theme_DATA = \
|
||||||
theme/gnome-shell.css \
|
theme/add-workspace.svg \
|
||||||
theme/close.svg \
|
|
||||||
theme/close-window.svg \
|
theme/close-window.svg \
|
||||||
theme/scroll-button-down.png \
|
theme/close.svg \
|
||||||
|
theme/gnome-shell.css \
|
||||||
|
theme/mosaic-view-active.svg \
|
||||||
|
theme/mosaic-view.svg \
|
||||||
|
theme/remove-workspace.svg \
|
||||||
theme/scroll-button-down-hover.png \
|
theme/scroll-button-down-hover.png \
|
||||||
theme/scroll-button-up.png \
|
theme/scroll-button-down.png \
|
||||||
theme/scroll-button-up-hover.png \
|
theme/scroll-button-up-hover.png \
|
||||||
|
theme/scroll-button-up.png \
|
||||||
theme/scroll-vhandle.png \
|
theme/scroll-vhandle.png \
|
||||||
theme/section-back.svg \
|
theme/section-back.svg \
|
||||||
theme/section-more.svg
|
theme/section-more.svg \
|
||||||
|
theme/single-view-active.svg \
|
||||||
|
theme/single-view.svg \
|
||||||
|
theme/switch-scroll-hhandle.svg
|
||||||
|
|
||||||
|
|
||||||
schemadir = @GCONF_SCHEMA_FILE_DIR@
|
schemadir = @GCONF_SCHEMA_FILE_DIR@
|
||||||
schema_DATA = gnome-shell.schemas
|
schema_DATA = gnome-shell.schemas
|
||||||
|
98
data/theme/add-workspace.svg
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="23"
|
||||||
|
height="15"
|
||||||
|
id="svg6375"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.47pre4 r22446"
|
||||||
|
sodipodi:docname="New document 13">
|
||||||
|
<defs
|
||||||
|
id="defs6377">
|
||||||
|
<inkscape:perspective
|
||||||
|
sodipodi:type="inkscape:persp3d"
|
||||||
|
inkscape:vp_x="0 : 16 : 1"
|
||||||
|
inkscape:vp_y="0 : 1000 : 0"
|
||||||
|
inkscape:vp_z="32 : 16 : 1"
|
||||||
|
inkscape:persp3d-origin="16 : 10.666667 : 1"
|
||||||
|
id="perspective6383" />
|
||||||
|
<inkscape:perspective
|
||||||
|
id="perspective6366"
|
||||||
|
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||||
|
inkscape:vp_z="1 : 0.5 : 1"
|
||||||
|
inkscape:vp_y="0 : 1000 : 0"
|
||||||
|
inkscape:vp_x="0 : 0.5 : 1"
|
||||||
|
sodipodi:type="inkscape:persp3d" />
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="11.197802"
|
||||||
|
inkscape:cx="16"
|
||||||
|
inkscape:cy="16"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="true"
|
||||||
|
inkscape:grid-bbox="true"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:window-width="1680"
|
||||||
|
inkscape:window-height="997"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="26"
|
||||||
|
inkscape:window-maximized="1" />
|
||||||
|
<metadata
|
||||||
|
id="metadata6380">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
id="layer1"
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
transform="translate(0,-17)">
|
||||||
|
<g
|
||||||
|
style="display:inline"
|
||||||
|
id="g6243"
|
||||||
|
transform="translate(-986.28859,-658.2796)">
|
||||||
|
<rect
|
||||||
|
style="fill:#000000;fill-opacity:0.98770495;stroke:#666666;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
|
||||||
|
id="rect5318"
|
||||||
|
width="22"
|
||||||
|
height="14"
|
||||||
|
x="986.89801"
|
||||||
|
y="675.86743"
|
||||||
|
rx="0.49999979"
|
||||||
|
ry="0.5" />
|
||||||
|
<g
|
||||||
|
id="g5320"
|
||||||
|
transform="translate(402.77304,-12.882544)">
|
||||||
|
<path
|
||||||
|
id="path5322"
|
||||||
|
d="m 595.125,692.53048 0,6.43903"
|
||||||
|
style="fill:none;stroke:#666666;stroke-width:1.99999952;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
|
||||||
|
<path
|
||||||
|
id="path5324"
|
||||||
|
d="m 598.34451,695.75 -6.43902,0"
|
||||||
|
style="fill:none;stroke:#666666;stroke-width:1.99999952;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 3.2 KiB |
@ -137,6 +137,24 @@ StTooltip {
|
|||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.workspaces-bar {
|
||||||
|
height: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.workspace-indicator {
|
||||||
|
width: 24px;
|
||||||
|
height: 15px;
|
||||||
|
background: rgba(155,155,155,0.8);
|
||||||
|
border-spacing: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.workspace-indicator-active {
|
||||||
|
width: 24px;
|
||||||
|
height: 15px;
|
||||||
|
background: rgba(255,255,255,0.8);
|
||||||
|
border-spacing: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
.window-caption {
|
.window-caption {
|
||||||
background: rgba(0,0,0,0.8);
|
background: rgba(0,0,0,0.8);
|
||||||
border: 1px solid rgba(128,128,128,0.40);
|
border: 1px solid rgba(128,128,128,0.40);
|
||||||
@ -154,6 +172,67 @@ StTooltip {
|
|||||||
-shell-close-overlap: 16px;
|
-shell-close-overlap: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.single-view-add {
|
||||||
|
background-image: url("add-workspace.svg");
|
||||||
|
width: 24px;
|
||||||
|
height: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.single-view-remove {
|
||||||
|
background-image: url("remove-workspace.svg");
|
||||||
|
width: 24px;
|
||||||
|
height: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch-view-single {
|
||||||
|
background-image: url("single-view.svg");
|
||||||
|
width: 24px;
|
||||||
|
height: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch-view-mosaic {
|
||||||
|
background-image: url("mosaic-view.svg");
|
||||||
|
width: 24px;
|
||||||
|
height: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch-view-single:checked {
|
||||||
|
background-image: url("single-view-active.svg");
|
||||||
|
width: 24px;
|
||||||
|
height: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch-view-mosaic:checked {
|
||||||
|
background-image: url("mosaic-view-active.svg");
|
||||||
|
width: 24px;
|
||||||
|
height: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll-separator {
|
||||||
|
width: 9px;
|
||||||
|
height: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#SwitchScroll {
|
||||||
|
height: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#SwitchScroll StBin{
|
||||||
|
border: 1px solid rgba(128,128,128,0.40);
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#SwitchScroll StButton#hhandle {
|
||||||
|
border-image: url("switch-scroll-hhandle.svg") 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
#SwitchScroll StButton#backward-stepper,
|
||||||
|
#SwitchScroll StButton#forward-stepper
|
||||||
|
{
|
||||||
|
width: 0px;
|
||||||
|
border: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
/* Dash */
|
/* Dash */
|
||||||
|
|
||||||
#dash {
|
#dash {
|
||||||
|
113
data/theme/mosaic-view-active.svg
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="24"
|
||||||
|
height="16"
|
||||||
|
id="svg6503"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.47pre4 r22446"
|
||||||
|
sodipodi:docname="mosaic-view-active.svg">
|
||||||
|
<defs
|
||||||
|
id="defs6505">
|
||||||
|
<inkscape:perspective
|
||||||
|
sodipodi:type="inkscape:persp3d"
|
||||||
|
inkscape:vp_x="0 : 16 : 1"
|
||||||
|
inkscape:vp_y="0 : 1000 : 0"
|
||||||
|
inkscape:vp_z="32 : 16 : 1"
|
||||||
|
inkscape:persp3d-origin="16 : 10.666667 : 1"
|
||||||
|
id="perspective6511" />
|
||||||
|
<inkscape:perspective
|
||||||
|
id="perspective6494"
|
||||||
|
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||||
|
inkscape:vp_z="1 : 0.5 : 1"
|
||||||
|
inkscape:vp_y="0 : 1000 : 0"
|
||||||
|
inkscape:vp_x="0 : 0.5 : 1"
|
||||||
|
sodipodi:type="inkscape:persp3d" />
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="11.197802"
|
||||||
|
inkscape:cx="-15.97056"
|
||||||
|
inkscape:cy="16"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="true"
|
||||||
|
inkscape:grid-bbox="true"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:window-width="1680"
|
||||||
|
inkscape:window-height="997"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="26"
|
||||||
|
inkscape:window-maximized="1" />
|
||||||
|
<metadata
|
||||||
|
id="metadata6508">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
id="layer1"
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
transform="translate(0,-16)">
|
||||||
|
<g
|
||||||
|
style="display:inline;fill:#cbcbcb;fill-opacity:1"
|
||||||
|
transform="translate(-449.85476,-685.85869)"
|
||||||
|
id="g5306">
|
||||||
|
<rect
|
||||||
|
style="fill:#cbcbcb;fill-opacity:1;stroke:#000000;stroke-width:0.99999970000000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.44262299999999999;stroke-dasharray:none"
|
||||||
|
id="rect5308"
|
||||||
|
width="11"
|
||||||
|
height="7"
|
||||||
|
x="450.5"
|
||||||
|
y="710.5"
|
||||||
|
rx="0.99999958"
|
||||||
|
ry="1" />
|
||||||
|
<rect
|
||||||
|
style="fill:#cbcbcb;fill-opacity:1;stroke:#000000;stroke-width:0.99999970000000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.44262299999999999;stroke-dasharray:none;display:inline"
|
||||||
|
id="rect5310"
|
||||||
|
width="11"
|
||||||
|
height="7"
|
||||||
|
x="462.5"
|
||||||
|
y="702.5"
|
||||||
|
rx="0.99999958"
|
||||||
|
ry="1" />
|
||||||
|
<rect
|
||||||
|
style="fill:#cbcbcb;fill-opacity:1;stroke:#000000;stroke-width:0.99999976000000002;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.44262299999999999;stroke-dasharray:none;display:inline"
|
||||||
|
id="rect5312"
|
||||||
|
width="11"
|
||||||
|
height="7"
|
||||||
|
x="450.5"
|
||||||
|
y="702.5"
|
||||||
|
rx="0.99999958"
|
||||||
|
ry="1" />
|
||||||
|
<rect
|
||||||
|
style="fill:#cbcbcb;fill-opacity:1;stroke:#000000;stroke-width:0.99999970000000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.44262299999999999;stroke-dasharray:none;display:inline"
|
||||||
|
id="rect5314"
|
||||||
|
width="11"
|
||||||
|
height="7"
|
||||||
|
x="462.5"
|
||||||
|
y="710.5"
|
||||||
|
rx="0.99999958"
|
||||||
|
ry="1" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 3.7 KiB |
113
data/theme/mosaic-view.svg
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="24"
|
||||||
|
height="16"
|
||||||
|
id="svg6503"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.47pre4 r22446"
|
||||||
|
sodipodi:docname="New document 19">
|
||||||
|
<defs
|
||||||
|
id="defs6505">
|
||||||
|
<inkscape:perspective
|
||||||
|
sodipodi:type="inkscape:persp3d"
|
||||||
|
inkscape:vp_x="0 : 16 : 1"
|
||||||
|
inkscape:vp_y="0 : 1000 : 0"
|
||||||
|
inkscape:vp_z="32 : 16 : 1"
|
||||||
|
inkscape:persp3d-origin="16 : 10.666667 : 1"
|
||||||
|
id="perspective6511" />
|
||||||
|
<inkscape:perspective
|
||||||
|
id="perspective6494"
|
||||||
|
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||||
|
inkscape:vp_z="1 : 0.5 : 1"
|
||||||
|
inkscape:vp_y="0 : 1000 : 0"
|
||||||
|
inkscape:vp_x="0 : 0.5 : 1"
|
||||||
|
sodipodi:type="inkscape:persp3d" />
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="11.197802"
|
||||||
|
inkscape:cx="16"
|
||||||
|
inkscape:cy="16"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="true"
|
||||||
|
inkscape:grid-bbox="true"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:window-width="1680"
|
||||||
|
inkscape:window-height="997"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="26"
|
||||||
|
inkscape:window-maximized="1" />
|
||||||
|
<metadata
|
||||||
|
id="metadata6508">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
id="layer1"
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
transform="translate(0,-16)">
|
||||||
|
<g
|
||||||
|
style="display:inline"
|
||||||
|
transform="translate(-449.85476,-685.85869)"
|
||||||
|
id="g5306">
|
||||||
|
<rect
|
||||||
|
style="fill:#666666;fill-opacity:1;stroke:#000000;stroke-width:0.9999997;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.442623;stroke-dasharray:none"
|
||||||
|
id="rect5308"
|
||||||
|
width="11"
|
||||||
|
height="7"
|
||||||
|
x="450.5"
|
||||||
|
y="710.5"
|
||||||
|
rx="0.99999958"
|
||||||
|
ry="1" />
|
||||||
|
<rect
|
||||||
|
style="fill:#666666;fill-opacity:1;stroke:#000000;stroke-width:0.9999997;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.442623;stroke-dasharray:none;display:inline"
|
||||||
|
id="rect5310"
|
||||||
|
width="11"
|
||||||
|
height="7"
|
||||||
|
x="462.5"
|
||||||
|
y="702.5"
|
||||||
|
rx="0.99999958"
|
||||||
|
ry="1" />
|
||||||
|
<rect
|
||||||
|
style="fill:#666666;fill-opacity:1;stroke:#000000;stroke-width:0.99999976;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.442623;stroke-dasharray:none;display:inline"
|
||||||
|
id="rect5312"
|
||||||
|
width="11"
|
||||||
|
height="7"
|
||||||
|
x="450.5"
|
||||||
|
y="702.5"
|
||||||
|
rx="0.99999958"
|
||||||
|
ry="1" />
|
||||||
|
<rect
|
||||||
|
style="fill:#666666;fill-opacity:1;stroke:#000000;stroke-width:0.9999997;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.442623;stroke-dasharray:none;display:inline"
|
||||||
|
id="rect5314"
|
||||||
|
width="11"
|
||||||
|
height="7"
|
||||||
|
x="462.5"
|
||||||
|
y="710.5"
|
||||||
|
rx="0.99999958"
|
||||||
|
ry="1" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 3.6 KiB |
92
data/theme/remove-workspace.svg
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="23"
|
||||||
|
height="15"
|
||||||
|
id="svg5501"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.47pre4 r22446"
|
||||||
|
sodipodi:docname="add-workspace.svg">
|
||||||
|
<defs
|
||||||
|
id="defs5503">
|
||||||
|
<inkscape:perspective
|
||||||
|
sodipodi:type="inkscape:persp3d"
|
||||||
|
inkscape:vp_x="0 : 16 : 1"
|
||||||
|
inkscape:vp_y="0 : 1000 : 0"
|
||||||
|
inkscape:vp_z="32 : 16 : 1"
|
||||||
|
inkscape:persp3d-origin="16 : 10.666667 : 1"
|
||||||
|
id="perspective5509" />
|
||||||
|
<inkscape:perspective
|
||||||
|
id="perspective5314"
|
||||||
|
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||||
|
inkscape:vp_z="1 : 0.5 : 1"
|
||||||
|
inkscape:vp_y="0 : 1000 : 0"
|
||||||
|
inkscape:vp_x="0 : 0.5 : 1"
|
||||||
|
sodipodi:type="inkscape:persp3d" />
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="11.197802"
|
||||||
|
inkscape:cx="-0.074583208"
|
||||||
|
inkscape:cy="16"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="true"
|
||||||
|
inkscape:grid-bbox="true"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:window-width="1680"
|
||||||
|
inkscape:window-height="997"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="26"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:snap-grids="true"
|
||||||
|
inkscape:snap-bbox="true" />
|
||||||
|
<metadata
|
||||||
|
id="metadata5506">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
id="layer1"
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
transform="translate(0,-17)">
|
||||||
|
<g
|
||||||
|
style="display:inline"
|
||||||
|
id="g6239"
|
||||||
|
transform="translate(-953.97989,-657.32287)">
|
||||||
|
<rect
|
||||||
|
style="fill:#000000;fill-opacity:0.98770495;stroke:#666666;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
|
||||||
|
id="rect5318-6"
|
||||||
|
width="22"
|
||||||
|
height="14"
|
||||||
|
x="954.5"
|
||||||
|
y="675"
|
||||||
|
rx="0.49999979"
|
||||||
|
ry="0.5" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#666666;stroke-width:1.99999952;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
|
||||||
|
d="m 968.71951,682 -6.43902,0"
|
||||||
|
id="path5324-5" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.9 KiB |
81
data/theme/single-view-active.svg
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="23"
|
||||||
|
height="15"
|
||||||
|
id="svg6446"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.47pre4 r22446"
|
||||||
|
sodipodi:docname="single-view-active.svg">
|
||||||
|
<defs
|
||||||
|
id="defs6448">
|
||||||
|
<inkscape:perspective
|
||||||
|
sodipodi:type="inkscape:persp3d"
|
||||||
|
inkscape:vp_x="0 : 16 : 1"
|
||||||
|
inkscape:vp_y="0 : 1000 : 0"
|
||||||
|
inkscape:vp_z="32 : 16 : 1"
|
||||||
|
inkscape:persp3d-origin="16 : 10.666667 : 1"
|
||||||
|
id="perspective6454" />
|
||||||
|
<inkscape:perspective
|
||||||
|
id="perspective6441"
|
||||||
|
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||||
|
inkscape:vp_z="1 : 0.5 : 1"
|
||||||
|
inkscape:vp_y="0 : 1000 : 0"
|
||||||
|
inkscape:vp_x="0 : 0.5 : 1"
|
||||||
|
sodipodi:type="inkscape:persp3d" />
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="11.197802"
|
||||||
|
inkscape:cx="0.014720032"
|
||||||
|
inkscape:cy="16"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="true"
|
||||||
|
inkscape:grid-bbox="true"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:window-width="1680"
|
||||||
|
inkscape:window-height="997"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="26"
|
||||||
|
inkscape:window-maximized="1" />
|
||||||
|
<metadata
|
||||||
|
id="metadata6451">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
id="layer1"
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
transform="translate(0,-17)">
|
||||||
|
<rect
|
||||||
|
ry="0.5"
|
||||||
|
rx="0.49999979"
|
||||||
|
y="17.483809"
|
||||||
|
x="0.53483802"
|
||||||
|
height="14"
|
||||||
|
width="22"
|
||||||
|
id="rect5304"
|
||||||
|
style="fill:#cccccc;fill-opacity:1;stroke:#cccccc;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.4 KiB |
81
data/theme/single-view.svg
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="23"
|
||||||
|
height="15"
|
||||||
|
id="svg6446"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.47pre4 r22446"
|
||||||
|
sodipodi:docname="single-view.svg">
|
||||||
|
<defs
|
||||||
|
id="defs6448">
|
||||||
|
<inkscape:perspective
|
||||||
|
sodipodi:type="inkscape:persp3d"
|
||||||
|
inkscape:vp_x="0 : 16 : 1"
|
||||||
|
inkscape:vp_y="0 : 1000 : 0"
|
||||||
|
inkscape:vp_z="32 : 16 : 1"
|
||||||
|
inkscape:persp3d-origin="16 : 10.666667 : 1"
|
||||||
|
id="perspective6454" />
|
||||||
|
<inkscape:perspective
|
||||||
|
id="perspective6441"
|
||||||
|
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||||
|
inkscape:vp_z="1 : 0.5 : 1"
|
||||||
|
inkscape:vp_y="0 : 1000 : 0"
|
||||||
|
inkscape:vp_x="0 : 0.5 : 1"
|
||||||
|
sodipodi:type="inkscape:persp3d" />
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="11.197802"
|
||||||
|
inkscape:cx="0.014720032"
|
||||||
|
inkscape:cy="16"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="true"
|
||||||
|
inkscape:grid-bbox="true"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:window-width="1680"
|
||||||
|
inkscape:window-height="997"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="26"
|
||||||
|
inkscape:window-maximized="1" />
|
||||||
|
<metadata
|
||||||
|
id="metadata6451">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
id="layer1"
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
transform="translate(0,-17)">
|
||||||
|
<rect
|
||||||
|
ry="0.5"
|
||||||
|
rx="0.49999979"
|
||||||
|
y="17.483809"
|
||||||
|
x="0.53483802"
|
||||||
|
height="14"
|
||||||
|
width="22"
|
||||||
|
id="rect5304"
|
||||||
|
style="fill:#626262;fill-opacity:1;stroke:#cccccc;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.4 KiB |
123
data/theme/switch-scroll-hhandle.svg
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="300"
|
||||||
|
height="16"
|
||||||
|
id="svg5337"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.47pre4 r22446"
|
||||||
|
sodipodi:docname="New document 2">
|
||||||
|
<defs
|
||||||
|
id="defs5339">
|
||||||
|
<inkscape:perspective
|
||||||
|
sodipodi:type="inkscape:persp3d"
|
||||||
|
inkscape:vp_x="0 : 16 : 1"
|
||||||
|
inkscape:vp_y="0 : 1000 : 0"
|
||||||
|
inkscape:vp_z="32 : 16 : 1"
|
||||||
|
inkscape:persp3d-origin="16 : 10.666667 : 1"
|
||||||
|
id="perspective5345" />
|
||||||
|
<inkscape:perspective
|
||||||
|
id="perspective5323"
|
||||||
|
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||||
|
inkscape:vp_z="1 : 0.5 : 1"
|
||||||
|
inkscape:vp_y="0 : 1000 : 0"
|
||||||
|
inkscape:vp_x="0 : 0.5 : 1"
|
||||||
|
sodipodi:type="inkscape:persp3d" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient356"
|
||||||
|
id="linearGradient5313"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="495.75"
|
||||||
|
y1="675.5"
|
||||||
|
x2="495.75"
|
||||||
|
y2="683" />
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient356">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#999999;stop-opacity:0.60000002;"
|
||||||
|
offset="0"
|
||||||
|
id="stop357" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#fffff3;stop-opacity:0.0000000;"
|
||||||
|
offset="1.0000000"
|
||||||
|
id="stop358" />
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="2.7994505"
|
||||||
|
inkscape:cx="111.6181"
|
||||||
|
inkscape:cy="33.67855"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="true"
|
||||||
|
inkscape:grid-bbox="true"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:window-width="1680"
|
||||||
|
inkscape:window-height="997"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="26"
|
||||||
|
inkscape:window-maximized="1" />
|
||||||
|
<metadata
|
||||||
|
id="metadata5342">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
id="layer1"
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
transform="translate(0,-16)">
|
||||||
|
<g
|
||||||
|
style="display:inline"
|
||||||
|
id="g6342"
|
||||||
|
transform="translate(-334.52404,-658.85869)">
|
||||||
|
<rect
|
||||||
|
ry="8"
|
||||||
|
rx="8"
|
||||||
|
y="675.5"
|
||||||
|
x="335.5"
|
||||||
|
height="15"
|
||||||
|
width="299"
|
||||||
|
id="rect5457-5"
|
||||||
|
style="fill:url(#linearGradient5313);fill-opacity:1;stroke:#999999;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
|
||||||
|
<g
|
||||||
|
transform="translate(0.5,0)"
|
||||||
|
id="g6337">
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#666666;stroke-width:0.99999994px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.8"
|
||||||
|
d="m 480.5,680.3717 0,5.2566"
|
||||||
|
id="path6304" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#666666;stroke-width:0.99999994px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.8;display:inline"
|
||||||
|
d="m 484.5,680.3717 0,5.2566"
|
||||||
|
id="path6304-0" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#666666;stroke-width:0.99999994px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.8;display:inline"
|
||||||
|
d="m 488.5,680.3717 0,5.2566"
|
||||||
|
id="path6304-8" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 3.9 KiB |
@ -30,4 +30,5 @@ dist_jsui_DATA = \
|
|||||||
widget.js \
|
widget.js \
|
||||||
widgetBox.js \
|
widgetBox.js \
|
||||||
windowManager.js \
|
windowManager.js \
|
||||||
workspaces.js
|
workspacesView.js \
|
||||||
|
workspace.js
|
||||||
|
@ -19,7 +19,7 @@ const DND = imports.ui.dnd;
|
|||||||
const GenericDisplay = imports.ui.genericDisplay;
|
const GenericDisplay = imports.ui.genericDisplay;
|
||||||
const Main = imports.ui.main;
|
const Main = imports.ui.main;
|
||||||
const Search = imports.ui.search;
|
const Search = imports.ui.search;
|
||||||
const Workspaces = imports.ui.workspaces;
|
const Workspace = imports.ui.workspace;
|
||||||
|
|
||||||
const APPICON_SIZE = 48;
|
const APPICON_SIZE = 48;
|
||||||
const WELL_MAX_COLUMNS = 8;
|
const WELL_MAX_COLUMNS = 8;
|
||||||
@ -697,7 +697,7 @@ AppIconMenu.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
_findMetaWindowForActor: function (actor) {
|
_findMetaWindowForActor: function (actor) {
|
||||||
if (actor._delegate instanceof Workspaces.WindowClone)
|
if (actor._delegate instanceof Workspace.WindowClone)
|
||||||
return actor._delegate.metaWindow;
|
return actor._delegate.metaWindow;
|
||||||
else if (actor.get_meta_window)
|
else if (actor.get_meta_window)
|
||||||
return actor.get_meta_window();
|
return actor.get_meta_window();
|
||||||
@ -1011,7 +1011,7 @@ AppWell.prototype = {
|
|||||||
let app = null;
|
let app = null;
|
||||||
if (source instanceof AppDisplayItem) {
|
if (source instanceof AppDisplayItem) {
|
||||||
app = this._appSystem.get_app(source.getId());
|
app = this._appSystem.get_app(source.getId());
|
||||||
} else if (source instanceof Workspaces.WindowClone) {
|
} else if (source instanceof Workspace.WindowClone) {
|
||||||
app = this._tracker.get_window_app(source.metaWindow);
|
app = this._tracker.get_window_app(source.metaWindow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ const Mainloop = imports.mainloop;
|
|||||||
const Shell = imports.gi.Shell;
|
const Shell = imports.gi.Shell;
|
||||||
const Signals = imports.signals;
|
const Signals = imports.signals;
|
||||||
const Lang = imports.lang;
|
const Lang = imports.lang;
|
||||||
|
const St = imports.gi.St;
|
||||||
|
|
||||||
const AppDisplay = imports.ui.appDisplay;
|
const AppDisplay = imports.ui.appDisplay;
|
||||||
const DocDisplay = imports.ui.docDisplay;
|
const DocDisplay = imports.ui.docDisplay;
|
||||||
@ -16,7 +17,7 @@ const Main = imports.ui.main;
|
|||||||
const Panel = imports.ui.panel;
|
const Panel = imports.ui.panel;
|
||||||
const Dash = imports.ui.dash;
|
const Dash = imports.ui.dash;
|
||||||
const Tweener = imports.ui.tweener;
|
const Tweener = imports.ui.tweener;
|
||||||
const Workspaces = imports.ui.workspaces;
|
const WorkspacesView = imports.ui.workspacesView;
|
||||||
|
|
||||||
const ROOT_OVERVIEW_COLOR = new Clutter.Color();
|
const ROOT_OVERVIEW_COLOR = new Clutter.Color();
|
||||||
ROOT_OVERVIEW_COLOR.from_pixel(0x000000ff);
|
ROOT_OVERVIEW_COLOR.from_pixel(0x000000ff);
|
||||||
@ -76,7 +77,6 @@ const NUMBER_OF_SECTIONS_IN_SEARCH = 2;
|
|||||||
let wideScreen = false;
|
let wideScreen = false;
|
||||||
let displayGridColumnWidth = null;
|
let displayGridColumnWidth = null;
|
||||||
let displayGridRowHeight = null;
|
let displayGridRowHeight = null;
|
||||||
let addRemoveButtonSize = null;
|
|
||||||
|
|
||||||
function Overview() {
|
function Overview() {
|
||||||
this._init();
|
this._init();
|
||||||
@ -87,6 +87,9 @@ Overview.prototype = {
|
|||||||
this._group = new Clutter.Group();
|
this._group = new Clutter.Group();
|
||||||
this._group._delegate = this;
|
this._group._delegate = this;
|
||||||
|
|
||||||
|
this._workspacesViewSwitch = new WorkspacesView.WorkspacesViewSwitch();
|
||||||
|
this._workspacesViewSwitch.connect('view-changed', Lang.bind(this, this._onViewChanged));
|
||||||
|
|
||||||
this.visible = false;
|
this.visible = false;
|
||||||
this.animationInProgress = false;
|
this.animationInProgress = false;
|
||||||
this._hideInProgress = false;
|
this._hideInProgress = false;
|
||||||
@ -139,6 +142,45 @@ Overview.prototype = {
|
|||||||
this._workspaces = null;
|
this._workspaces = null;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_createControlsBar: function() {
|
||||||
|
this._workspacesBar = new St.BoxLayout({ 'pack-start': true,
|
||||||
|
style_class: 'workspaces-bar' });
|
||||||
|
this._workspacesBar.move_by(this._workspacesBarX, this._workspacesBarY);
|
||||||
|
|
||||||
|
let controlsBar = this._workspacesViewSwitch.createControlsBar();
|
||||||
|
let bar = this._workspaces.createControllerBar();
|
||||||
|
this._workspacesBar.add(bar, { expand: true, 'x-fill': true, 'y-fill': true,
|
||||||
|
y_align: St.Align.MIDDLE, x_align: St.Align.START });
|
||||||
|
this._workspacesBar.add(controlsBar, {x_align: St.Align.END});
|
||||||
|
this._workspacesBar.width = this._workspacesBarWidth;
|
||||||
|
|
||||||
|
this._group.add_actor(this._workspacesBar);
|
||||||
|
this._workspacesBar.raise(this._workspaces.actor);
|
||||||
|
},
|
||||||
|
|
||||||
|
_onViewChanged: function() {
|
||||||
|
if (!this.visible)
|
||||||
|
return;
|
||||||
|
//Remove old worspacesView
|
||||||
|
this._group.remove_actor(this._workspacesBar);
|
||||||
|
this._workspaces.hide();
|
||||||
|
this._group.remove_actor(this._workspaces.actor);
|
||||||
|
this._workspaces.destroy();
|
||||||
|
this._workspacesBar.destroy();
|
||||||
|
|
||||||
|
this._workspaces = this._workspacesViewSwitch.createCurrentWorkspaceView(this._workspacesWidth, this._workspacesHeight,
|
||||||
|
this._workspacesX, this._workspacesY, false);
|
||||||
|
|
||||||
|
//Show new workspacesView
|
||||||
|
this._group.add_actor(this._workspaces.actor);
|
||||||
|
this._dash.actor.raise(this._workspaces.actor);
|
||||||
|
|
||||||
|
this._createControlsBar();
|
||||||
|
|
||||||
|
// Set new position and scale to workspaces.
|
||||||
|
this.emit('showing');
|
||||||
|
},
|
||||||
|
|
||||||
_recalculateGridSizes: function () {
|
_recalculateGridSizes: function () {
|
||||||
let primary = global.get_primary_monitor();
|
let primary = global.get_primary_monitor();
|
||||||
wideScreen = (primary.width/primary.height > WIDE_SCREEN_CUT_OFF_RATIO) &&
|
wideScreen = (primary.width/primary.height > WIDE_SCREEN_CUT_OFF_RATIO) &&
|
||||||
@ -188,9 +230,9 @@ Overview.prototype = {
|
|||||||
this._dash.searchResults.actor.height = this._workspacesHeight;
|
this._dash.searchResults.actor.height = this._workspacesHeight;
|
||||||
|
|
||||||
// place the 'Add Workspace' button in the bottom row of the grid
|
// place the 'Add Workspace' button in the bottom row of the grid
|
||||||
addRemoveButtonSize = Math.floor(displayGridRowHeight * 3/5);
|
this._workspacesBarX = this._workspacesX;
|
||||||
this._addButtonX = this._workspacesX + this._workspacesWidth - addRemoveButtonSize;
|
this._workspacesBarWidth = primary.width - this._workspacesBarX - WORKSPACE_GRID_PADDING;
|
||||||
this._addButtonY = primary.height - Math.floor(displayGridRowHeight * 4/5);
|
this._workspacesBarY = primary.height - displayGridRowHeight + 5;
|
||||||
|
|
||||||
// The parent (this._group) is positioned at the top left of the primary monitor
|
// The parent (this._group) is positioned at the top left of the primary monitor
|
||||||
// while this._backOver occupies the entire screen.
|
// while this._backOver occupies the entire screen.
|
||||||
@ -298,8 +340,8 @@ Overview.prototype = {
|
|||||||
this._dash.show();
|
this._dash.show();
|
||||||
|
|
||||||
/* TODO: make this stuff dynamic */
|
/* TODO: make this stuff dynamic */
|
||||||
this._workspaces = new Workspaces.Workspaces(this._workspacesWidth, this._workspacesHeight,
|
this._workspaces = this._workspacesViewSwitch.createCurrentWorkspaceView(this._workspacesWidth, this._workspacesHeight,
|
||||||
this._workspacesX, this._workspacesY);
|
this._workspacesX, this._workspacesY, true);
|
||||||
this._group.add_actor(this._workspaces.actor);
|
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
|
// The workspaces actor is as big as the screen, so we have to raise the dash above it
|
||||||
@ -307,11 +349,7 @@ Overview.prototype = {
|
|||||||
// be as big as the screen.
|
// be as big as the screen.
|
||||||
this._dash.actor.raise(this._workspaces.actor);
|
this._dash.actor.raise(this._workspaces.actor);
|
||||||
|
|
||||||
// Create (+) button
|
this._createControlsBar();
|
||||||
this._addButton = new AddWorkspaceButton(addRemoveButtonSize, this._addButtonX, this._addButtonY, Lang.bind(this, this._acceptNewWorkspaceDrop));
|
|
||||||
this._addButton.actor.connect('button-release-event', Lang.bind(this, this._addNewWorkspace));
|
|
||||||
this._group.add_actor(this._addButton.actor);
|
|
||||||
this._addButton.actor.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
|
||||||
@ -363,9 +401,8 @@ Overview.prototype = {
|
|||||||
this._activeDisplayPane.close();
|
this._activeDisplayPane.close();
|
||||||
this._workspaces.hide();
|
this._workspaces.hide();
|
||||||
|
|
||||||
this._addButton.actor.destroy();
|
this._workspacesBar.destroy();
|
||||||
this._addButton.actor = null;
|
this._workspacesBar = null;
|
||||||
this._addButton = null;
|
|
||||||
|
|
||||||
// Create a zoom in effect by transforming the Overview group so that
|
// Create a zoom in effect by transforming the Overview group so that
|
||||||
// the active workspace fills up the whole screen. The opposite
|
// the active workspace fills up the whole screen. The opposite
|
||||||
@ -456,61 +493,6 @@ Overview.prototype = {
|
|||||||
|
|
||||||
Main.popModal(this._dash.actor);
|
Main.popModal(this._dash.actor);
|
||||||
this.emit('hidden');
|
this.emit('hidden');
|
||||||
},
|
|
||||||
|
|
||||||
_addNewWorkspace: function() {
|
|
||||||
global.screen.append_new_workspace(false, global.get_current_time());
|
|
||||||
},
|
|
||||||
|
|
||||||
_acceptNewWorkspaceDrop: function(source, dropActor, x, y, time) {
|
|
||||||
this._addNewWorkspace();
|
|
||||||
return this._workspaces.acceptNewWorkspaceDrop(source, dropActor, x, y, time);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Signals.addSignalMethods(Overview.prototype);
|
Signals.addSignalMethods(Overview.prototype);
|
||||||
|
|
||||||
// Note that mutter has a compile-time limit of 36
|
|
||||||
const MAX_WORKSPACES = 16;
|
|
||||||
|
|
||||||
function AddWorkspaceButton(buttonSize, buttonX, buttonY, acceptDropCallback) {
|
|
||||||
this._init(buttonSize, buttonX, buttonY, acceptDropCallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
AddWorkspaceButton.prototype = {
|
|
||||||
_init: function(buttonSize, buttonX, buttonY, acceptDropCallback) {
|
|
||||||
this.actor = new Clutter.Group({ x: buttonX,
|
|
||||||
y: buttonY,
|
|
||||||
width: global.screen_width - buttonX,
|
|
||||||
height: global.screen_height - buttonY,
|
|
||||||
reactive: true });
|
|
||||||
this.actor._delegate = this;
|
|
||||||
this._acceptDropCallback = acceptDropCallback;
|
|
||||||
|
|
||||||
let plus = new Clutter.Texture({ x: 0,
|
|
||||||
y: 0,
|
|
||||||
width: buttonSize,
|
|
||||||
height: buttonSize });
|
|
||||||
plus.set_from_file(global.imagedir + 'add-workspace.svg');
|
|
||||||
this.actor.add_actor(plus);
|
|
||||||
|
|
||||||
global.screen.connect('notify::n-workspaces', Lang.bind(this, this._nWorkspacesChanged));
|
|
||||||
this._nWorkspacesChanged();
|
|
||||||
},
|
|
||||||
|
|
||||||
_nWorkspacesChanged: function() {
|
|
||||||
let canAddAnother = global.screen.n_workspaces < MAX_WORKSPACES;
|
|
||||||
|
|
||||||
if (canAddAnother && !this.actor.reactive) {
|
|
||||||
this.actor.reactive = true;
|
|
||||||
this.actor.opacity = 255;
|
|
||||||
} else if (!canAddAnother && this.actor.reactive) {
|
|
||||||
this.actor.reactive = false;
|
|
||||||
this.actor.opacity = 85;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// Draggable target interface
|
|
||||||
acceptDrop: function(source, actor, x, y, time) {
|
|
||||||
return this.reactive && this._acceptDropCallback(source, actor, x, y, time);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
@ -322,7 +322,7 @@ WindowOverlay.prototype = {
|
|||||||
this._parentActor = parentActor;
|
this._parentActor = parentActor;
|
||||||
|
|
||||||
let title = new St.Label({ style_class: "window-caption",
|
let title = new St.Label({ style_class: "window-caption",
|
||||||
text : metaWindow.title });
|
text: metaWindow.title });
|
||||||
title.connect('style-changed',
|
title.connect('style-changed',
|
||||||
Lang.bind(this, this._onStyleChanged));
|
Lang.bind(this, this._onStyleChanged));
|
||||||
title.clutter_text.ellipsize = Pango.EllipsizeMode.END;
|
title.clutter_text.ellipsize = Pango.EllipsizeMode.END;
|
||||||
@ -368,6 +368,8 @@ WindowOverlay.prototype = {
|
|||||||
x, y);
|
x, y);
|
||||||
if (actor == this._windowClone.actor) {
|
if (actor == this._windowClone.actor) {
|
||||||
this.closeButton.show();
|
this.closeButton.show();
|
||||||
|
// Reposition the close button in case we've changed display modes
|
||||||
|
this._updatePositions();
|
||||||
}
|
}
|
||||||
this.title.show();
|
this.title.show();
|
||||||
},
|
},
|
||||||
@ -375,7 +377,7 @@ WindowOverlay.prototype = {
|
|||||||
fadeIn: function() {
|
fadeIn: function() {
|
||||||
this.title.opacity = 0;
|
this.title.opacity = 0;
|
||||||
this.title.show();
|
this.title.show();
|
||||||
this.title.raise_top();
|
this._parentActor.raise_top();
|
||||||
Tweener.addTween(this.title,
|
Tweener.addTween(this.title,
|
||||||
{ opacity: 255,
|
{ opacity: 255,
|
||||||
time: Overview.ANIMATION_TIME,
|
time: Overview.ANIMATION_TIME,
|
||||||
@ -391,6 +393,12 @@ WindowOverlay.prototype = {
|
|||||||
this.title.height + this.title._spacing;
|
this.title.height + this.title._spacing;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_updatePositions: function() {
|
||||||
|
let [cloneX, cloneY] = this._windowClone.actor.get_transformed_position();
|
||||||
|
let [cloneWidth, cloneHeight] = this._windowClone.actor.get_transformed_size();
|
||||||
|
this.updatePositions(cloneX, cloneY, cloneWidth, cloneHeight);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @cloneX: x position of windowClone
|
* @cloneX: x position of windowClone
|
||||||
* @cloneY: y position of windowClone
|
* @cloneY: y position of windowClone
|
||||||
@ -460,7 +468,9 @@ WindowOverlay.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
_onEnter: function() {
|
_onEnter: function() {
|
||||||
this.closeButton.raise_top();
|
this._updatePositions();
|
||||||
|
|
||||||
|
this._parentActor.raise_top();
|
||||||
this.closeButton.show();
|
this.closeButton.show();
|
||||||
this.emit('show-close-button');
|
this.emit('show-close-button');
|
||||||
},
|
},
|
||||||
@ -510,6 +520,10 @@ WindowOverlay.prototype = {
|
|||||||
|
|
||||||
Signals.addSignalMethods(WindowOverlay.prototype);
|
Signals.addSignalMethods(WindowOverlay.prototype);
|
||||||
|
|
||||||
|
const WindowPositionFlags = {
|
||||||
|
ZOOM: 1 << 0,
|
||||||
|
ANIMATE: 1 << 1
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @workspaceNum: Workspace index
|
* @workspaceNum: Workspace index
|
||||||
@ -524,9 +538,14 @@ function Workspace(workspaceNum, parentActor) {
|
|||||||
Workspace.prototype = {
|
Workspace.prototype = {
|
||||||
_init : function(workspaceNum, parentActor) {
|
_init : function(workspaceNum, parentActor) {
|
||||||
this.workspaceNum = workspaceNum;
|
this.workspaceNum = workspaceNum;
|
||||||
|
this._windowOverlaysGroup = new Clutter.Group();
|
||||||
|
// Without this the drop area will be overlapped.
|
||||||
|
this._windowOverlaysGroup.set_size(0, 0);
|
||||||
|
|
||||||
this._metaWorkspace = global.screen.get_workspace_by_index(workspaceNum);
|
this._metaWorkspace = global.screen.get_workspace_by_index(workspaceNum);
|
||||||
|
|
||||||
this.parentActor = parentActor;
|
parentActor.add_actor(this._windowOverlaysGroup);
|
||||||
|
this._parentActor = parentActor;
|
||||||
|
|
||||||
this.actor = new Clutter.Group();
|
this.actor = new Clutter.Group();
|
||||||
this.actor._delegate = this;
|
this.actor._delegate = this;
|
||||||
@ -578,7 +597,6 @@ Workspace.prototype = {
|
|||||||
this._windowRemovedId = this._metaWorkspace.connect('window-removed',
|
this._windowRemovedId = this._metaWorkspace.connect('window-removed',
|
||||||
Lang.bind(this, this._windowRemoved));
|
Lang.bind(this, this._windowRemoved));
|
||||||
|
|
||||||
this._removeButton = null;
|
|
||||||
this._visible = false;
|
this._visible = false;
|
||||||
|
|
||||||
this._frame = null;
|
this._frame = null;
|
||||||
@ -586,51 +604,6 @@ Workspace.prototype = {
|
|||||||
this.leavingOverview = false;
|
this.leavingOverview = false;
|
||||||
},
|
},
|
||||||
|
|
||||||
updateRemovable : function() {
|
|
||||||
let removable = (this._windows.length == 1 /* just desktop */ &&
|
|
||||||
this.workspaceNum != 0 &&
|
|
||||||
this.workspaceNum == global.screen.n_workspaces - 1);
|
|
||||||
|
|
||||||
if (removable) {
|
|
||||||
if (this._removeButton)
|
|
||||||
return;
|
|
||||||
|
|
||||||
this._removeButton = new Clutter.Texture({ width: Overview.addRemoveButtonSize,
|
|
||||||
height: Overview.addRemoveButtonSize,
|
|
||||||
reactive: true
|
|
||||||
});
|
|
||||||
this._removeButton.set_from_file(global.imagedir + "remove-workspace.svg");
|
|
||||||
this._removeButton.connect('button-release-event', Lang.bind(this, this._removeSelf));
|
|
||||||
|
|
||||||
this.actor.add_actor(this._removeButton);
|
|
||||||
this._adjustRemoveButton();
|
|
||||||
this._adjustRemoveButtonId = this.actor.connect('notify::scale-x', Lang.bind(this, this._adjustRemoveButton));
|
|
||||||
|
|
||||||
if (this._visible) {
|
|
||||||
this._removeButton.set_opacity(0);
|
|
||||||
Tweener.addTween(this._removeButton,
|
|
||||||
{ opacity: 255,
|
|
||||||
time: Overview.ANIMATION_TIME,
|
|
||||||
transition: "easeOutQuad"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!this._removeButton)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (this._visible) {
|
|
||||||
Tweener.addTween(this._removeButton,
|
|
||||||
{ opacity: 0,
|
|
||||||
time: Overview.ANIMATION_TIME,
|
|
||||||
transition: "easeOutQuad",
|
|
||||||
onComplete: this._removeRemoveButton,
|
|
||||||
onCompleteScope: this
|
|
||||||
});
|
|
||||||
} else
|
|
||||||
this._removeRemoveButton();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_lookupIndex: function (metaWindow) {
|
_lookupIndex: function (metaWindow) {
|
||||||
let index, clone;
|
let index, clone;
|
||||||
for (let i = 0; i < this._windows.length; i++) {
|
for (let i = 0; i < this._windows.length; i++) {
|
||||||
@ -661,7 +634,7 @@ Workspace.prototype = {
|
|||||||
this._showOnlyWindows = showOnlyWindows;
|
this._showOnlyWindows = showOnlyWindows;
|
||||||
this._resetCloneVisibility();
|
this._resetCloneVisibility();
|
||||||
if (reposition)
|
if (reposition)
|
||||||
this.positionWindows(false);
|
this.positionWindows(WindowPositionFlags.ANIMATE);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -697,20 +670,6 @@ Workspace.prototype = {
|
|||||||
this._lightbox.highlight(actor);
|
this._lightbox.highlight(actor);
|
||||||
},
|
},
|
||||||
|
|
||||||
_adjustRemoveButton : function() {
|
|
||||||
this._removeButton.set_scale(1.0 / this.actor.scale_x,
|
|
||||||
1.0 / this.actor.scale_y);
|
|
||||||
this._removeButton.set_position(
|
|
||||||
(this.actor.width - this._removeButton.width / this.actor.scale_x) / 2,
|
|
||||||
(this.actor.height - this._removeButton.height / this.actor.scale_y) / 2);
|
|
||||||
},
|
|
||||||
|
|
||||||
_removeRemoveButton : function() {
|
|
||||||
this._removeButton.destroy();
|
|
||||||
this._removeButton = null;
|
|
||||||
this.actor.disconnect(this._adjustRemoveButtonId);
|
|
||||||
},
|
|
||||||
|
|
||||||
// Mark the workspace selected/not-selected
|
// Mark the workspace selected/not-selected
|
||||||
setSelected : function(selected) {
|
setSelected : function(selected) {
|
||||||
// Don't draw a frame if we only have one workspace
|
// Don't draw a frame if we only have one workspace
|
||||||
@ -1007,13 +966,18 @@ Workspace.prototype = {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* positionWindows:
|
* positionWindows:
|
||||||
* @workspaceZooming: If true, then the workspace is moving at the same time and we need to take that into account.
|
* @flags:
|
||||||
|
* ZOOM - workspace is moving at the same time and we need to take that into account.
|
||||||
|
* ANIMATE - Indicates that we need animate changing position.
|
||||||
*/
|
*/
|
||||||
positionWindows : function(workspaceZooming) {
|
positionWindows : function(flags) {
|
||||||
let totalVisible = 0;
|
let totalVisible = 0;
|
||||||
|
|
||||||
let visibleWindows = this._getVisibleWindows();
|
let visibleWindows = this._getVisibleWindows();
|
||||||
|
|
||||||
|
let workspaceZooming = flags & WindowPositionFlags.ZOOM;
|
||||||
|
let animate = flags & WindowPositionFlags.ANIMATE;
|
||||||
|
|
||||||
// Start the animations
|
// Start the animations
|
||||||
let slots = this._computeAllWindowSlots(visibleWindows.length);
|
let slots = this._computeAllWindowSlots(visibleWindows.length);
|
||||||
visibleWindows = this._orderWindowsByMotionAndStartup(visibleWindows, slots);
|
visibleWindows = this._orderWindowsByMotionAndStartup(visibleWindows, slots);
|
||||||
@ -1028,6 +992,7 @@ Workspace.prototype = {
|
|||||||
let [x, y, scale] = this._computeWindowRelativeLayout(metaWindow, slot);
|
let [x, y, scale] = this._computeWindowRelativeLayout(metaWindow, slot);
|
||||||
|
|
||||||
overlay.hide();
|
overlay.hide();
|
||||||
|
if (animate) {
|
||||||
Tweener.addTween(clone.actor,
|
Tweener.addTween(clone.actor,
|
||||||
{ x: x,
|
{ x: x,
|
||||||
y: y,
|
y: y,
|
||||||
@ -1040,6 +1005,11 @@ Workspace.prototype = {
|
|||||||
this._fadeInWindowOverlay(clone, overlay);
|
this._fadeInWindowOverlay(clone, overlay);
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
clone.actor.set_position(x, y);
|
||||||
|
clone.actor.set_scale(scale, scale);
|
||||||
|
this._fadeInWindowOverlay(clone, overlay);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1127,8 +1097,7 @@ Workspace.prototype = {
|
|||||||
}
|
}
|
||||||
clone.destroy();
|
clone.destroy();
|
||||||
|
|
||||||
this.positionWindows(false);
|
this.positionWindows(WindowPositionFlags.ANIMATE);
|
||||||
this.updateRemovable();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_windowAdded : function(metaWorkspace, metaWin) {
|
_windowAdded : function(metaWorkspace, metaWin) {
|
||||||
@ -1164,29 +1133,19 @@ Workspace.prototype = {
|
|||||||
clone.actor.set_scale (scale, scale);
|
clone.actor.set_scale (scale, scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.positionWindows(false);
|
this.positionWindows(WindowPositionFlags.ANIMATE);
|
||||||
this.updateRemovable();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Animate the full-screen to Overview transition.
|
// Animate the full-screen to Overview transition.
|
||||||
zoomToOverview : function() {
|
zoomToOverview : function(animate) {
|
||||||
this.actor.set_position(this.gridX, this.gridY);
|
this.actor.set_position(this.gridX, this.gridY);
|
||||||
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.
|
||||||
this.positionWindows(true);
|
if (animate)
|
||||||
|
this.positionWindows(WindowPositionFlags.ANIMATE | WindowPositionFlags.ZOOM);
|
||||||
// Fade in the remove button if available, so that it doesn't appear
|
else
|
||||||
// too abrubtly and doesn't start at a too big size.
|
this.positionWindows(WindowPositionFlags.ZOOM);
|
||||||
if (this._removeButton) {
|
|
||||||
Tweener.removeTweens(this._removeButton);
|
|
||||||
this._removeButton.opacity = 0;
|
|
||||||
Tweener.addTween(this._removeButton,
|
|
||||||
{ opacity: 255,
|
|
||||||
time: Overview.ANIMATION_TIME,
|
|
||||||
transition: 'easeOutQuad'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
this._visible = true;
|
this._visible = true;
|
||||||
},
|
},
|
||||||
@ -1200,17 +1159,6 @@ Workspace.prototype = {
|
|||||||
Main.overview.connect('hidden', Lang.bind(this,
|
Main.overview.connect('hidden', Lang.bind(this,
|
||||||
this._doneLeavingOverview));
|
this._doneLeavingOverview));
|
||||||
|
|
||||||
// Fade out the remove button if available, so that it doesn't
|
|
||||||
// disappear too abrubtly and doesn't become too big.
|
|
||||||
if (this._removeButton) {
|
|
||||||
Tweener.removeTweens(this._removeButton);
|
|
||||||
Tweener.addTween(this._removeButton,
|
|
||||||
{ opacity: 0,
|
|
||||||
time: Overview.ANIMATION_TIME,
|
|
||||||
transition: 'easeOutQuad'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Position and scale the windows.
|
// Position and scale the windows.
|
||||||
for (let i = 1; i < this._windows.length; i++) {
|
for (let i = 1; i < this._windows.length; i++) {
|
||||||
let clone = this._windows[i];
|
let clone = this._windows[i];
|
||||||
@ -1296,6 +1244,7 @@ Workspace.prototype = {
|
|||||||
Tweener.removeTweens(this.actor);
|
Tweener.removeTweens(this.actor);
|
||||||
this.actor.destroy();
|
this.actor.destroy();
|
||||||
this.actor = null;
|
this.actor = null;
|
||||||
|
this._windowOverlaysGroup.destroy();
|
||||||
|
|
||||||
this._metaWorkspace.disconnect(this._windowAddedId);
|
this._metaWorkspace.disconnect(this._windowAddedId);
|
||||||
this._metaWorkspace.disconnect(this._windowRemovedId);
|
this._metaWorkspace.disconnect(this._windowRemovedId);
|
||||||
@ -1321,7 +1270,7 @@ Workspace.prototype = {
|
|||||||
// Create a clone of a (non-desktop) window and add it to the window list
|
// Create a clone of a (non-desktop) window and add it to the window list
|
||||||
_addWindowClone : function(win) {
|
_addWindowClone : function(win) {
|
||||||
let clone = new WindowClone(win);
|
let clone = new WindowClone(win);
|
||||||
let overlay = new WindowOverlay(clone, this.parentActor);
|
let overlay = new WindowOverlay(clone, this._windowOverlaysGroup);
|
||||||
|
|
||||||
clone.connect('selected',
|
clone.connect('selected',
|
||||||
Lang.bind(this, this._onCloneSelected));
|
Lang.bind(this, this._onCloneSelected));
|
||||||
@ -1421,399 +1370,3 @@ Workspace.prototype = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Signals.addSignalMethods(Workspace.prototype);
|
Signals.addSignalMethods(Workspace.prototype);
|
||||||
|
|
||||||
function Workspaces(width, height, x, y) {
|
|
||||||
this._init(width, height, x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
Workspaces.prototype = {
|
|
||||||
_init : function(width, height, x, y) {
|
|
||||||
this.actor = new St.Bin({ style_class: "workspaces" });
|
|
||||||
this._actor = new Clutter.Group();
|
|
||||||
|
|
||||||
this.actor.add_actor(this._actor);
|
|
||||||
|
|
||||||
this._width = width;
|
|
||||||
this._height = height;
|
|
||||||
this._x = x;
|
|
||||||
this._y = y;
|
|
||||||
|
|
||||||
this._windowSelectionAppId = null;
|
|
||||||
|
|
||||||
this._workspaces = [];
|
|
||||||
|
|
||||||
this._highlightWindow = null;
|
|
||||||
|
|
||||||
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
|
|
||||||
let activeWorkspace;
|
|
||||||
|
|
||||||
// Create and position workspace objects
|
|
||||||
for (let w = 0; w < global.screen.n_workspaces; w++) {
|
|
||||||
this._addWorkspaceActor(w);
|
|
||||||
if (w == activeWorkspaceIndex) {
|
|
||||||
activeWorkspace = this._workspaces[w];
|
|
||||||
activeWorkspace.setSelected(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
activeWorkspace.actor.raise_top();
|
|
||||||
this._positionWorkspaces();
|
|
||||||
|
|
||||||
let lastWorkspace = this._workspaces[this._workspaces.length - 1];
|
|
||||||
lastWorkspace.updateRemovable(true);
|
|
||||||
|
|
||||||
// Position/scale the desktop windows and their children after the
|
|
||||||
// workspaces have been created. This cannot be done first because
|
|
||||||
// window movement depends on the Workspaces object being accessible
|
|
||||||
// as an Overview member.
|
|
||||||
this._overviewShowingId =
|
|
||||||
Main.overview.connect('showing',
|
|
||||||
Lang.bind(this, function() {
|
|
||||||
this._onRestacked();
|
|
||||||
for (let w = 0; w < this._workspaces.length; w++)
|
|
||||||
this._workspaces[w].zoomToOverview();
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Track changes to the number of workspaces
|
|
||||||
this._nWorkspacesNotifyId =
|
|
||||||
global.screen.connect('notify::n-workspaces',
|
|
||||||
Lang.bind(this, this._workspacesChanged));
|
|
||||||
this._switchWorkspaceNotifyId =
|
|
||||||
global.window_manager.connect('switch-workspace',
|
|
||||||
Lang.bind(this, this._activeWorkspaceChanged));
|
|
||||||
this._restackedNotifyId =
|
|
||||||
global.screen.connect('restacked',
|
|
||||||
Lang.bind(this, this._onRestacked));
|
|
||||||
},
|
|
||||||
|
|
||||||
_lookupWorkspaceForMetaWindow: function (metaWindow) {
|
|
||||||
for (let i = 0; i < this._workspaces.length; i++) {
|
|
||||||
if (this._workspaces[i].containsMetaWindow(metaWindow))
|
|
||||||
return this._workspaces[i];
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
|
|
||||||
_lookupCloneForMetaWindow: function (metaWindow) {
|
|
||||||
for (let i = 0; i < this._workspaces.length; i++) {
|
|
||||||
let clone = this._workspaces[i].lookupCloneForMetaWindow(metaWindow);
|
|
||||||
if (clone)
|
|
||||||
return clone;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
|
|
||||||
setHighlightWindow: function (metaWindow) {
|
|
||||||
// Looping over all workspaces is easier than keeping track of the last
|
|
||||||
// highlighted window while trying to handle the window or workspace possibly
|
|
||||||
// going away.
|
|
||||||
for (let i = 0; i < this._workspaces.length; i++) {
|
|
||||||
this._workspaces[i].setHighlightWindow(null);
|
|
||||||
}
|
|
||||||
if (metaWindow != null) {
|
|
||||||
let workspace = this._lookupWorkspaceForMetaWindow(metaWindow);
|
|
||||||
workspace.setHighlightWindow(metaWindow);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_clearApplicationWindowSelection: function(reposition) {
|
|
||||||
if (this._windowSelectionAppId == null)
|
|
||||||
return;
|
|
||||||
this._windowSelectionAppId = null;
|
|
||||||
|
|
||||||
for (let i = 0; i < this._workspaces.length; i++) {
|
|
||||||
this._workspaces[i].setLightboxMode(false);
|
|
||||||
this._workspaces[i].setShowOnlyWindows(null, reposition);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* setApplicationWindowSelection:
|
|
||||||
* @appid: Application identifier string
|
|
||||||
*
|
|
||||||
* Enter a mode which shows only the windows owned by the
|
|
||||||
* given application, and allow highlighting of a specific
|
|
||||||
* window with setHighlightWindow().
|
|
||||||
*/
|
|
||||||
setApplicationWindowSelection: function (appId) {
|
|
||||||
if (appId == null) {
|
|
||||||
this._clearApplicationWindowSelection(true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (appId == this._windowSelectionAppId)
|
|
||||||
return;
|
|
||||||
|
|
||||||
this._windowSelectionAppId = appId;
|
|
||||||
|
|
||||||
let appSys = Shell.AppSystem.get_default();
|
|
||||||
|
|
||||||
let showOnlyWindows = {};
|
|
||||||
let app = appSys.get_app(appId);
|
|
||||||
let windows = app.get_windows();
|
|
||||||
for (let i = 0; i < windows.length; i++) {
|
|
||||||
showOnlyWindows[windows[i]] = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < this._workspaces.length; i++) {
|
|
||||||
this._workspaces[i].setLightboxMode(true);
|
|
||||||
this._workspaces[i].setShowOnlyWindows(showOnlyWindows, true);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* activateWindowFromOverview:
|
|
||||||
* @metaWindow: A #MetaWindow
|
|
||||||
* @time: Integer even timestamp
|
|
||||||
*
|
|
||||||
* This function exits the overview, switching to the given @metaWindow.
|
|
||||||
* If an application filter is in effect, it will be cleared.
|
|
||||||
*/
|
|
||||||
activateWindowFromOverview: function (metaWindow, time) {
|
|
||||||
if (this._windowSelectionAppId != null) {
|
|
||||||
this._clearApplicationWindowSelection(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
Main.activateWindow(metaWindow, time);
|
|
||||||
Main.overview.hide();
|
|
||||||
},
|
|
||||||
|
|
||||||
hide : function() {
|
|
||||||
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
|
|
||||||
let activeWorkspace = this._workspaces[activeWorkspaceIndex];
|
|
||||||
|
|
||||||
this._positionWorkspaces();
|
|
||||||
activeWorkspace.actor.raise_top();
|
|
||||||
|
|
||||||
for (let w = 0; w < this._workspaces.length; w++)
|
|
||||||
this._workspaces[w].zoomFromOverview();
|
|
||||||
},
|
|
||||||
|
|
||||||
destroy : function() {
|
|
||||||
for (let w = 0; w < this._workspaces.length; w++)
|
|
||||||
this._workspaces[w].destroy();
|
|
||||||
this._workspaces = [];
|
|
||||||
|
|
||||||
this.actor.destroy();
|
|
||||||
this.actor = null;
|
|
||||||
|
|
||||||
Main.overview.disconnect(this._overviewShowingId);
|
|
||||||
global.screen.disconnect(this._nWorkspacesNotifyId);
|
|
||||||
global.window_manager.disconnect(this._switchWorkspaceNotifyId);
|
|
||||||
global.screen.disconnect(this._restackedNotifyId);
|
|
||||||
},
|
|
||||||
|
|
||||||
getScale : function() {
|
|
||||||
return this._workspaces[0].scale;
|
|
||||||
},
|
|
||||||
|
|
||||||
// Get the grid position of the active workspace.
|
|
||||||
getActiveWorkspacePosition : function() {
|
|
||||||
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
|
|
||||||
let activeWorkspace = this._workspaces[activeWorkspaceIndex];
|
|
||||||
|
|
||||||
return [activeWorkspace.gridX, activeWorkspace.gridY];
|
|
||||||
},
|
|
||||||
|
|
||||||
// Assign grid positions to workspaces. We can't just do a simple
|
|
||||||
// row-major or column-major numbering, because we don't want the
|
|
||||||
// existing workspaces to get rearranged when we add a row or
|
|
||||||
// column. So we alternate between adding to rows and adding to
|
|
||||||
// columns. (So, eg, when going from a 2x2 grid of 4 workspaces to
|
|
||||||
// a 3x2 grid of 5 workspaces, the 4 existing workspaces stay
|
|
||||||
// where they are, and the 5th one is added to the end of the
|
|
||||||
// first row.)
|
|
||||||
//
|
|
||||||
// FIXME: need to make the metacity internal layout agree with this!
|
|
||||||
_positionWorkspaces : function() {
|
|
||||||
let gridWidth = Math.ceil(Math.sqrt(this._workspaces.length));
|
|
||||||
let gridHeight = Math.ceil(this._workspaces.length / gridWidth);
|
|
||||||
|
|
||||||
let wsWidth = (this._width - (gridWidth - 1) * GRID_SPACING) / gridWidth;
|
|
||||||
let wsHeight = (this._height - (gridHeight - 1) * GRID_SPACING) / gridHeight;
|
|
||||||
let scale = wsWidth / global.screen_width;
|
|
||||||
|
|
||||||
let span = 1, n = 0, row = 0, col = 0, horiz = true;
|
|
||||||
|
|
||||||
for (let w = 0; w < this._workspaces.length; w++) {
|
|
||||||
let workspace = this._workspaces[w];
|
|
||||||
|
|
||||||
workspace.gridRow = row;
|
|
||||||
workspace.gridCol = col;
|
|
||||||
|
|
||||||
workspace.gridX = this._x + workspace.gridCol * (wsWidth + GRID_SPACING);
|
|
||||||
workspace.gridY = this._y + workspace.gridRow * (wsHeight + GRID_SPACING);
|
|
||||||
workspace.scale = scale;
|
|
||||||
|
|
||||||
if (horiz) {
|
|
||||||
col++;
|
|
||||||
if (col == span) {
|
|
||||||
row = 0;
|
|
||||||
horiz = false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
row++;
|
|
||||||
if (row == span) {
|
|
||||||
col = 0;
|
|
||||||
horiz = true;
|
|
||||||
span++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_workspacesChanged : function() {
|
|
||||||
let oldNumWorkspaces = this._workspaces.length;
|
|
||||||
let newNumWorkspaces = global.screen.n_workspaces;
|
|
||||||
|
|
||||||
if (oldNumWorkspaces == newNumWorkspaces)
|
|
||||||
return;
|
|
||||||
|
|
||||||
let oldScale = this._workspaces[0].scale;
|
|
||||||
let oldGridWidth = Math.ceil(Math.sqrt(oldNumWorkspaces));
|
|
||||||
let oldGridHeight = Math.ceil(oldNumWorkspaces / oldGridWidth);
|
|
||||||
let lostWorkspaces = [];
|
|
||||||
|
|
||||||
// The old last workspace is no longer removable.
|
|
||||||
this._workspaces[oldNumWorkspaces - 1].updateRemovable();
|
|
||||||
|
|
||||||
if (newNumWorkspaces > oldNumWorkspaces) {
|
|
||||||
// Create new workspace groups
|
|
||||||
for (let w = oldNumWorkspaces; w < newNumWorkspaces; w++) {
|
|
||||||
this._addWorkspaceActor(w);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// Truncate the list of workspaces
|
|
||||||
// FIXME: assumes that the workspaces are being removed from
|
|
||||||
// the end of the list, not the start/middle
|
|
||||||
lostWorkspaces = this._workspaces.splice(newNumWorkspaces);
|
|
||||||
}
|
|
||||||
|
|
||||||
// The new last workspace may be removable
|
|
||||||
let newLastWorkspace = this._workspaces[this._workspaces.length - 1];
|
|
||||||
newLastWorkspace.updateRemovable();
|
|
||||||
|
|
||||||
// Figure out the new layout
|
|
||||||
this._positionWorkspaces();
|
|
||||||
let newScale = this._workspaces[0].scale;
|
|
||||||
let newGridWidth = Math.ceil(Math.sqrt(newNumWorkspaces));
|
|
||||||
let newGridHeight = Math.ceil(newNumWorkspaces / newGridWidth);
|
|
||||||
|
|
||||||
if (newGridWidth != oldGridWidth || newGridHeight != oldGridHeight) {
|
|
||||||
// We need to resize/move the existing workspaces/windows
|
|
||||||
let existingWorkspaces = Math.min(oldNumWorkspaces, newNumWorkspaces);
|
|
||||||
for (let w = 0; w < existingWorkspaces; w++)
|
|
||||||
this._workspaces[w].resizeToGrid(oldScale);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newScale != oldScale) {
|
|
||||||
// The workspace scale affects window size/positioning because we clamp
|
|
||||||
// window size to a 1:1 ratio and never scale them up
|
|
||||||
let existingWorkspaces = Math.min(oldNumWorkspaces, newNumWorkspaces);
|
|
||||||
for (let w = 0; w < existingWorkspaces; w++)
|
|
||||||
this._workspaces[w].positionWindows(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newNumWorkspaces > oldNumWorkspaces) {
|
|
||||||
// Slide new workspaces in from offscreen
|
|
||||||
for (let w = oldNumWorkspaces; w < newNumWorkspaces; w++)
|
|
||||||
this._workspaces[w].slideIn(oldScale);
|
|
||||||
} else {
|
|
||||||
// Slide old workspaces out
|
|
||||||
for (let w = 0; w < lostWorkspaces.length; w++) {
|
|
||||||
let workspace = lostWorkspaces[w];
|
|
||||||
workspace.slideOut(function () { workspace.destroy(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: deal with windows on the lost workspaces
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset the selection state; if we went from > 1 workspace to 1,
|
|
||||||
// this has the side effect of removing the frame border
|
|
||||||
let activeIndex = global.screen.get_active_workspace_index();
|
|
||||||
this._workspaces[activeIndex].setSelected(true);
|
|
||||||
},
|
|
||||||
|
|
||||||
_activeWorkspaceChanged : function(wm, from, to, direction) {
|
|
||||||
this._workspaces[from].setSelected(false);
|
|
||||||
this._workspaces[to].setSelected(true);
|
|
||||||
},
|
|
||||||
|
|
||||||
_addWorkspaceActor : function(workspaceNum) {
|
|
||||||
let workspace = new Workspace(workspaceNum, this._actor);
|
|
||||||
this._workspaces[workspaceNum] = workspace;
|
|
||||||
this._actor.add_actor(workspace.actor);
|
|
||||||
},
|
|
||||||
|
|
||||||
_onRestacked: function() {
|
|
||||||
let stack = global.get_windows();
|
|
||||||
let stackIndices = {};
|
|
||||||
|
|
||||||
for (let i = 0; i < stack.length; i++) {
|
|
||||||
// Use the stable sequence for an integer to use as a hash key
|
|
||||||
stackIndices[stack[i].get_meta_window().get_stable_sequence()] = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < this._workspaces.length; i++)
|
|
||||||
this._workspaces[i].syncStacking(stackIndices);
|
|
||||||
},
|
|
||||||
|
|
||||||
// Handles a drop onto the (+) button; assumes the new workspace
|
|
||||||
// has already been added
|
|
||||||
acceptNewWorkspaceDrop : function(source, dropActor, x, y, time) {
|
|
||||||
return this._workspaces[this._workspaces.length - 1].acceptDrop(source, dropActor, x, y, time);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Create a SpecialPropertyModifier to let us move windows in a
|
|
||||||
// straight line on the screen even though their containing workspace
|
|
||||||
// is also moving.
|
|
||||||
Tweener.registerSpecialPropertyModifier("workspace_relative", _workspaceRelativeModifier, _workspaceRelativeGet);
|
|
||||||
|
|
||||||
function _workspaceRelativeModifier(workspace) {
|
|
||||||
let [startX, startY] = Main.overview.getPosition();
|
|
||||||
let overviewPosX, overviewPosY, overviewScale;
|
|
||||||
|
|
||||||
if (!workspace)
|
|
||||||
return [];
|
|
||||||
|
|
||||||
if (workspace.leavingOverview) {
|
|
||||||
let [zoomedInX, zoomedInY] = Main.overview.getZoomedInPosition();
|
|
||||||
overviewPosX = { begin: startX, end: zoomedInX };
|
|
||||||
overviewPosY = { begin: startY, end: zoomedInY };
|
|
||||||
overviewScale = { begin: Main.overview.getScale(),
|
|
||||||
end: Main.overview.getZoomedInScale() };
|
|
||||||
} else {
|
|
||||||
overviewPosX = { begin: startX, end: 0 };
|
|
||||||
overviewPosY = { begin: startY, end: 0 };
|
|
||||||
overviewScale = { begin: Main.overview.getScale(), end: 1 };
|
|
||||||
}
|
|
||||||
|
|
||||||
return [ { name: "x",
|
|
||||||
parameters: { workspacePos: workspace.gridX,
|
|
||||||
overviewPos: overviewPosX,
|
|
||||||
overviewScale: overviewScale } },
|
|
||||||
{ name: "y",
|
|
||||||
parameters: { workspacePos: workspace.gridY,
|
|
||||||
overviewPos: overviewPosY,
|
|
||||||
overviewScale: overviewScale } }
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
function _workspaceRelativeGet(begin, end, time, params) {
|
|
||||||
let curOverviewPos = (1 - time) * params.overviewPos.begin +
|
|
||||||
time * params.overviewPos.end;
|
|
||||||
let curOverviewScale = (1 - time) * params.overviewScale.begin +
|
|
||||||
time * params.overviewScale.end;
|
|
||||||
|
|
||||||
// Calculate the screen position of the window.
|
|
||||||
let screen = (1 - time) *
|
|
||||||
((begin + params.workspacePos) * params.overviewScale.begin +
|
|
||||||
params.overviewPos.begin) +
|
|
||||||
time *
|
|
||||||
((end + params.workspacePos) * params.overviewScale.end +
|
|
||||||
params.overviewPos.end);
|
|
||||||
|
|
||||||
// Return the workspace coordinates.
|
|
||||||
return (screen - curOverviewPos) / curOverviewScale - params.workspacePos;
|
|
||||||
}
|
|
956
js/ui/workspacesView.js
Normal file
@ -0,0 +1,956 @@
|
|||||||
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
|
const Big = imports.gi.Big;
|
||||||
|
const Clutter = imports.gi.Clutter;
|
||||||
|
const GdkPixbuf = imports.gi.GdkPixbuf;
|
||||||
|
const Gdk = imports.gi.Gdk;
|
||||||
|
const Gtk = imports.gi.Gtk;
|
||||||
|
const Lang = imports.lang;
|
||||||
|
const Mainloop = imports.mainloop;
|
||||||
|
const Meta = imports.gi.Meta;
|
||||||
|
const Pango = imports.gi.Pango;
|
||||||
|
const Shell = imports.gi.Shell;
|
||||||
|
const St = imports.gi.St;
|
||||||
|
const Signals = imports.signals;
|
||||||
|
|
||||||
|
const DND = imports.ui.dnd;
|
||||||
|
const Lightbox = imports.ui.lightbox;
|
||||||
|
const Main = imports.ui.main;
|
||||||
|
const Overview = imports.ui.overview;
|
||||||
|
const Panel = imports.ui.panel;
|
||||||
|
const Tweener = imports.ui.tweener;
|
||||||
|
const Workspace = imports.ui.workspace;
|
||||||
|
|
||||||
|
const WORKSPACE_SWITCH_TIME = 0.25;
|
||||||
|
// Note that mutter has a compile-time limit of 36
|
||||||
|
const MAX_WORKSPACES = 16;
|
||||||
|
|
||||||
|
const GRID_SPACING = 15;
|
||||||
|
|
||||||
|
const WorkspacesViewType = {
|
||||||
|
SINGLE: 0,
|
||||||
|
MOSAIC: 1
|
||||||
|
};
|
||||||
|
|
||||||
|
function GenericWorkspacesView(width, height, x, y, animate) {
|
||||||
|
this._init(width, height, x, y, animate);
|
||||||
|
}
|
||||||
|
|
||||||
|
GenericWorkspacesView.prototype = {
|
||||||
|
_init: function(width, height, x, y, animate) {
|
||||||
|
this.actor = new St.Bin({ style_class: "workspaces" });
|
||||||
|
this._actor = new Clutter.Group();
|
||||||
|
|
||||||
|
this.actor.add_actor(this._actor);
|
||||||
|
|
||||||
|
this._width = width;
|
||||||
|
this._height = height;
|
||||||
|
this._x = x;
|
||||||
|
this._y = y;
|
||||||
|
|
||||||
|
this._windowSelectionAppId = null;
|
||||||
|
|
||||||
|
this._workspaces = [];
|
||||||
|
|
||||||
|
this._highlightWindow = null;
|
||||||
|
|
||||||
|
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
|
||||||
|
|
||||||
|
// Create and position workspace objects
|
||||||
|
for (let w = 0; w < global.screen.n_workspaces; w++) {
|
||||||
|
this._addWorkspaceActor(w);
|
||||||
|
}
|
||||||
|
this._workspaces[activeWorkspaceIndex].actor.raise_top();
|
||||||
|
this._positionWorkspaces();
|
||||||
|
|
||||||
|
// Position/scale the desktop windows and their children after the
|
||||||
|
// workspaces have been created. This cannot be done first because
|
||||||
|
// window movement depends on the Workspaces object being accessible
|
||||||
|
// as an Overview member.
|
||||||
|
this._overviewShowingId =
|
||||||
|
Main.overview.connect('showing',
|
||||||
|
Lang.bind(this, function() {
|
||||||
|
this._onRestacked();
|
||||||
|
for (let w = 0; w < this._workspaces.length; w++)
|
||||||
|
this._workspaces[w].zoomToOverview(animate);
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Track changes to the number of workspaces
|
||||||
|
this._nWorkspacesNotifyId =
|
||||||
|
global.screen.connect('notify::n-workspaces',
|
||||||
|
Lang.bind(this, this._workspacesChanged));
|
||||||
|
this._switchWorkspaceNotifyId =
|
||||||
|
global.window_manager.connect('switch-workspace',
|
||||||
|
Lang.bind(this, this._activeWorkspaceChanged));
|
||||||
|
this._restackedNotifyId =
|
||||||
|
global.screen.connect('restacked',
|
||||||
|
Lang.bind(this, this._onRestacked));
|
||||||
|
},
|
||||||
|
|
||||||
|
_lookupWorkspaceForMetaWindow: function (metaWindow) {
|
||||||
|
for (let i = 0; i < this._workspaces.length; i++) {
|
||||||
|
if (this._workspaces[i].containsMetaWindow(metaWindow))
|
||||||
|
return this._workspaces[i];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
|
||||||
|
_lookupCloneForMetaWindow: function (metaWindow) {
|
||||||
|
for (let i = 0; i < this._workspaces.length; i++) {
|
||||||
|
let clone = this._workspaces[i].lookupCloneForMetaWindow(metaWindow);
|
||||||
|
if (clone)
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
|
||||||
|
setHighlightWindow: function (metaWindow) {
|
||||||
|
// Looping over all workspaces is easier than keeping track of the last
|
||||||
|
// highlighted window while trying to handle the window or workspace possibly
|
||||||
|
// going away.
|
||||||
|
for (let i = 0; i < this._workspaces.length; i++) {
|
||||||
|
this._workspaces[i].setHighlightWindow(null);
|
||||||
|
}
|
||||||
|
if (metaWindow != null) {
|
||||||
|
let workspace = this._lookupWorkspaceForMetaWindow(metaWindow);
|
||||||
|
workspace.setHighlightWindow(metaWindow);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_clearApplicationWindowSelection: function(reposition) {
|
||||||
|
if (this._windowSelectionAppId == null)
|
||||||
|
return;
|
||||||
|
this._windowSelectionAppId = null;
|
||||||
|
|
||||||
|
for (let i = 0; i < this._workspaces.length; i++) {
|
||||||
|
this._workspaces[i].setLightboxMode(false);
|
||||||
|
this._workspaces[i].setShowOnlyWindows(null, reposition);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* setApplicationWindowSelection:
|
||||||
|
* @appid: Application identifier string
|
||||||
|
*
|
||||||
|
* Enter a mode which shows only the windows owned by the
|
||||||
|
* given application, and allow highlighting of a specific
|
||||||
|
* window with setHighlightWindow().
|
||||||
|
*/
|
||||||
|
setApplicationWindowSelection: function (appId) {
|
||||||
|
if (appId == null) {
|
||||||
|
this._clearApplicationWindowSelection(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (appId == this._windowSelectionAppId)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this._windowSelectionAppId = appId;
|
||||||
|
|
||||||
|
let appSys = Shell.AppSystem.get_default();
|
||||||
|
|
||||||
|
let showOnlyWindows = {};
|
||||||
|
let app = appSys.get_app(appId);
|
||||||
|
let windows = app.get_windows();
|
||||||
|
for (let i = 0; i < windows.length; i++) {
|
||||||
|
showOnlyWindows[windows[i]] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < this._workspaces.length; i++) {
|
||||||
|
this._workspaces[i].setLightboxMode(true);
|
||||||
|
this._workspaces[i].setShowOnlyWindows(showOnlyWindows, true);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* activateWindowFromOverview:
|
||||||
|
* @metaWindow: A #MetaWindow
|
||||||
|
* @time: Integer even timestamp
|
||||||
|
*
|
||||||
|
* This function exits the overview, switching to the given @metaWindow.
|
||||||
|
* If an application filter is in effect, it will be cleared.
|
||||||
|
*/
|
||||||
|
activateWindowFromOverview: function (metaWindow, time) {
|
||||||
|
if (this._windowSelectionAppId != null) {
|
||||||
|
this._clearApplicationWindowSelection(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
Main.activateWindow(metaWindow, time);
|
||||||
|
Main.overview.hide();
|
||||||
|
},
|
||||||
|
|
||||||
|
hide: function() {
|
||||||
|
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
|
||||||
|
let activeWorkspace = this._workspaces[activeWorkspaceIndex];
|
||||||
|
|
||||||
|
this._positionWorkspaces();
|
||||||
|
activeWorkspace.actor.raise_top();
|
||||||
|
|
||||||
|
for (let w = 0; w < this._workspaces.length; w++)
|
||||||
|
this._workspaces[w].zoomFromOverview();
|
||||||
|
},
|
||||||
|
|
||||||
|
destroy: function() {
|
||||||
|
for (let w = 0; w < this._workspaces.length; w++)
|
||||||
|
this._workspaces[w].destroy();
|
||||||
|
this._workspaces = [];
|
||||||
|
|
||||||
|
this.actor.destroy();
|
||||||
|
this.actor = null;
|
||||||
|
|
||||||
|
Main.overview.disconnect(this._overviewShowingId);
|
||||||
|
global.screen.disconnect(this._nWorkspacesNotifyId);
|
||||||
|
global.window_manager.disconnect(this._switchWorkspaceNotifyId);
|
||||||
|
global.screen.disconnect(this._restackedNotifyId);
|
||||||
|
},
|
||||||
|
|
||||||
|
getScale: function() {
|
||||||
|
return this._workspaces[0].scale;
|
||||||
|
},
|
||||||
|
|
||||||
|
_onRestacked: function() {
|
||||||
|
let stack = global.get_windows();
|
||||||
|
let stackIndices = {};
|
||||||
|
|
||||||
|
for (let i = 0; i < stack.length; i++) {
|
||||||
|
// Use the stable sequence for an integer to use as a hash key
|
||||||
|
stackIndices[stack[i].get_meta_window().get_stable_sequence()] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < this._workspaces.length; i++)
|
||||||
|
this._workspaces[i].syncStacking(stackIndices);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Handles a drop onto the (+) button; assumes the new workspace
|
||||||
|
// has already been added
|
||||||
|
acceptNewWorkspaceDrop: function(source, dropActor, x, y, time) {
|
||||||
|
return this._workspaces[this._workspaces.length - 1].acceptDrop(source, dropActor, x, y, time);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Get the grid position of the active workspace.
|
||||||
|
getActiveWorkspacePosition: function() {
|
||||||
|
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
|
||||||
|
let activeWorkspace = this._workspaces[activeWorkspaceIndex];
|
||||||
|
|
||||||
|
return [activeWorkspace.gridX, activeWorkspace.gridY];
|
||||||
|
},
|
||||||
|
|
||||||
|
createControllerBar: function() {
|
||||||
|
throw new Error("Not implemented");
|
||||||
|
},
|
||||||
|
|
||||||
|
_positionWorkspaces: function() {
|
||||||
|
throw new Error("Not implemented");
|
||||||
|
},
|
||||||
|
|
||||||
|
_workspacesChanged: function() {
|
||||||
|
throw new Error("Not implemented");
|
||||||
|
},
|
||||||
|
|
||||||
|
_activeWorkspaceChanged: function() {
|
||||||
|
throw new Error("Not implemented");
|
||||||
|
},
|
||||||
|
|
||||||
|
_addWorkspaceActor: function() {
|
||||||
|
throw new Error("Not implemented");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function MosaicView(width, height, x, y, animate) {
|
||||||
|
this._init(width, height, x, y, animate);
|
||||||
|
}
|
||||||
|
|
||||||
|
MosaicView.prototype = {
|
||||||
|
__proto__: GenericWorkspacesView.prototype,
|
||||||
|
|
||||||
|
_init: function(width, height, x, y, animate) {
|
||||||
|
GenericWorkspacesView.prototype._init.call(this, width, height, x, y, animate);
|
||||||
|
|
||||||
|
this._workspaces[global.screen.get_active_workspace_index()].setSelected(true);
|
||||||
|
|
||||||
|
this._removeButton = null;
|
||||||
|
this._addButton = null;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Assign grid positions to workspaces. We can't just do a simple
|
||||||
|
// row-major or column-major numbering, because we don't want the
|
||||||
|
// existing workspaces to get rearranged when we add a row or
|
||||||
|
// column. So we alternate between adding to rows and adding to
|
||||||
|
// columns. (So, eg, when going from a 2x2 grid of 4 workspaces to
|
||||||
|
// a 3x2 grid of 5 workspaces, the 4 existing workspaces stay
|
||||||
|
// where they are, and the 5th one is added to the end of the
|
||||||
|
// first row.)
|
||||||
|
//
|
||||||
|
// FIXME: need to make the metacity internal layout agree with this!
|
||||||
|
_positionWorkspaces: function() {
|
||||||
|
let gridWidth = Math.ceil(Math.sqrt(this._workspaces.length));
|
||||||
|
let gridHeight = Math.ceil(this._workspaces.length / gridWidth);
|
||||||
|
|
||||||
|
let wsWidth = (this._width - (gridWidth - 1) * GRID_SPACING) / gridWidth;
|
||||||
|
let wsHeight = (this._height - (gridHeight - 1) * GRID_SPACING) / gridHeight;
|
||||||
|
let scale = wsWidth / global.screen_width;
|
||||||
|
|
||||||
|
let span = 1, n = 0, row = 0, col = 0, horiz = true;
|
||||||
|
|
||||||
|
for (let w = 0; w < this._workspaces.length; w++) {
|
||||||
|
let workspace = this._workspaces[w];
|
||||||
|
|
||||||
|
workspace.gridRow = row;
|
||||||
|
workspace.gridCol = col;
|
||||||
|
|
||||||
|
workspace.gridX = this._x + workspace.gridCol * (wsWidth + GRID_SPACING);
|
||||||
|
workspace.gridY = this._y + workspace.gridRow * (wsHeight + GRID_SPACING);
|
||||||
|
workspace.scale = scale;
|
||||||
|
|
||||||
|
if (horiz) {
|
||||||
|
col++;
|
||||||
|
if (col == span) {
|
||||||
|
row = 0;
|
||||||
|
horiz = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
row++;
|
||||||
|
if (row == span) {
|
||||||
|
col = 0;
|
||||||
|
horiz = true;
|
||||||
|
span++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_workspacesChanged: function() {
|
||||||
|
let oldNumWorkspaces = this._workspaces.length;
|
||||||
|
let newNumWorkspaces = global.screen.n_workspaces;
|
||||||
|
|
||||||
|
if (oldNumWorkspaces == newNumWorkspaces)
|
||||||
|
return;
|
||||||
|
|
||||||
|
let oldScale = this._workspaces[0].scale;
|
||||||
|
let oldGridWidth = Math.ceil(Math.sqrt(oldNumWorkspaces));
|
||||||
|
let oldGridHeight = Math.ceil(oldNumWorkspaces / oldGridWidth);
|
||||||
|
let lostWorkspaces = [];
|
||||||
|
|
||||||
|
// The old last workspace is no longer removable.
|
||||||
|
|
||||||
|
if (newNumWorkspaces > oldNumWorkspaces) {
|
||||||
|
// Create new workspace groups
|
||||||
|
for (let w = oldNumWorkspaces; w < newNumWorkspaces; w++) {
|
||||||
|
this._addWorkspaceActor(w);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Truncate the list of workspaces
|
||||||
|
// FIXME: assumes that the workspaces are being removed from
|
||||||
|
// the end of the list, not the start/middle
|
||||||
|
lostWorkspaces = this._workspaces.splice(newNumWorkspaces);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The new last workspace may be removable
|
||||||
|
let newLastWorkspace = this._workspaces[this._workspaces.length - 1];
|
||||||
|
|
||||||
|
// Figure out the new layout
|
||||||
|
this._positionWorkspaces();
|
||||||
|
let newScale = this._workspaces[0].scale;
|
||||||
|
let newGridWidth = Math.ceil(Math.sqrt(newNumWorkspaces));
|
||||||
|
let newGridHeight = Math.ceil(newNumWorkspaces / newGridWidth);
|
||||||
|
|
||||||
|
if (newGridWidth != oldGridWidth || newGridHeight != oldGridHeight) {
|
||||||
|
// We need to resize/move the existing workspaces/windows
|
||||||
|
let existingWorkspaces = Math.min(oldNumWorkspaces, newNumWorkspaces);
|
||||||
|
for (let w = 0; w < existingWorkspaces; w++)
|
||||||
|
this._workspaces[w].resizeToGrid(oldScale);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newScale != oldScale) {
|
||||||
|
// The workspace scale affects window size/positioning because we clamp
|
||||||
|
// window size to a 1:1 ratio and never scale them up
|
||||||
|
let existingWorkspaces = Math.min(oldNumWorkspaces, newNumWorkspaces);
|
||||||
|
for (let w = 0; w < existingWorkspaces; w++)
|
||||||
|
this._workspaces[w].positionWindows(Workspace.WindowPositionFlags.ANIMATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newNumWorkspaces > oldNumWorkspaces) {
|
||||||
|
// Slide new workspaces in from offscreen
|
||||||
|
for (let w = oldNumWorkspaces; w < newNumWorkspaces; w++)
|
||||||
|
this._workspaces[w].slideIn(oldScale);
|
||||||
|
} else {
|
||||||
|
// Slide old workspaces out
|
||||||
|
for (let w = 0; w < lostWorkspaces.length; w++) {
|
||||||
|
let workspace = lostWorkspaces[w];
|
||||||
|
workspace.slideOut(function () { workspace.destroy(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: deal with windows on the lost workspaces
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset the selection state; if we went from > 1 workspace to 1,
|
||||||
|
// this has the side effect of removing the frame border
|
||||||
|
let activeIndex = global.screen.get_active_workspace_index();
|
||||||
|
this._workspaces[activeIndex].setSelected(true);
|
||||||
|
|
||||||
|
this._updateButtonsVisibility();
|
||||||
|
},
|
||||||
|
|
||||||
|
_activeWorkspaceChanged: function(wm, from, to, direction) {
|
||||||
|
this._workspaces[from].setSelected(false);
|
||||||
|
this._workspaces[to].setSelected(true);
|
||||||
|
},
|
||||||
|
|
||||||
|
_addWorkspaceActor: function(workspaceNum) {
|
||||||
|
let workspace = new Workspace.Workspace(workspaceNum, this._actor);
|
||||||
|
this._workspaces[workspaceNum] = workspace;
|
||||||
|
this._actor.add_actor(workspace.actor);
|
||||||
|
},
|
||||||
|
|
||||||
|
createControllerBar: function() {
|
||||||
|
let actor = new St.BoxLayout({ 'pack-start': true });
|
||||||
|
let bin = new St.Bin();
|
||||||
|
let addButton = new St.Button({ style_class: "single-view-add" });
|
||||||
|
this._addButton = addButton;
|
||||||
|
addButton.connect('clicked', Lang.bind(this, this._addNewWorkspace));
|
||||||
|
addButton._delegate = addButton;
|
||||||
|
addButton._delegate.acceptDrop = Lang.bind(this, function(source, actor, x, y, time) {
|
||||||
|
return this._acceptNewWorkspaceDrop(source, actor, x, y, time);
|
||||||
|
});
|
||||||
|
actor.add(bin, { x_align: St.Align.END });
|
||||||
|
bin.set_child(addButton);
|
||||||
|
bin.set_alignment(St.Align.END, St.Align.START);
|
||||||
|
|
||||||
|
bin = new St.Bin();
|
||||||
|
let removeButton = new St.Button({ style_class: "single-view-remove" });
|
||||||
|
this._removeButton = removeButton;
|
||||||
|
removeButton.connect('clicked', Lang.bind(this, function() {
|
||||||
|
if (this._workspaces.length <= 1)
|
||||||
|
return;
|
||||||
|
global.screen.remove_workspace(this._workspaces[this._workspaces.length - 1]._metaWorkspace, global.get_current_time());
|
||||||
|
}));
|
||||||
|
actor.add(bin, { expand: true, x_fill: true, x_align: St.Align.END });
|
||||||
|
this._updateButtonsVisibility();
|
||||||
|
bin.set_child(removeButton);
|
||||||
|
bin.set_alignment(St.Align.END, St.Align.START);
|
||||||
|
|
||||||
|
return actor;
|
||||||
|
},
|
||||||
|
|
||||||
|
_updateButtonsVisibility: function() {
|
||||||
|
//_removeButton may yet not exist.
|
||||||
|
if (this._removeButton == null)
|
||||||
|
return;
|
||||||
|
if (global.screen.n_workspaces == 1)
|
||||||
|
this._removeButton.hide();
|
||||||
|
else
|
||||||
|
this._removeButton.show();
|
||||||
|
if (this._addButton == null)
|
||||||
|
return;
|
||||||
|
if (global.screen.n_workspaces >= MAX_WORKSPACES)
|
||||||
|
this._addButton.hide();
|
||||||
|
else
|
||||||
|
this._addButton.show();
|
||||||
|
},
|
||||||
|
|
||||||
|
_addNewWorkspace: function() {
|
||||||
|
global.screen.append_new_workspace(false, global.get_current_time());
|
||||||
|
},
|
||||||
|
|
||||||
|
_acceptNewWorkspaceDrop: function(source, dropActor, x, y, time) {
|
||||||
|
this._addNewWorkspace();
|
||||||
|
return this.acceptNewWorkspaceDrop(source, dropActor, x, y, time);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create a SpecialPropertyModifier to let us move windows in a
|
||||||
|
// straight line on the screen even though their containing workspace
|
||||||
|
// is also moving.
|
||||||
|
Tweener.registerSpecialPropertyModifier("workspace_relative", _workspaceRelativeModifier, _workspaceRelativeGet);
|
||||||
|
|
||||||
|
function SingleView(width, height, x, y, animate) {
|
||||||
|
this._init(width, height, x, y, animate);
|
||||||
|
}
|
||||||
|
|
||||||
|
SingleView.prototype = {
|
||||||
|
__proto__: GenericWorkspacesView.prototype,
|
||||||
|
|
||||||
|
_init: function(width, height, x, y, animate) {
|
||||||
|
this._scroll = null;
|
||||||
|
GenericWorkspacesView.prototype._init.call(this, width, height, x, y, animate);
|
||||||
|
|
||||||
|
this._actor.set_clip(x, y, width, height);
|
||||||
|
this._addButton = null;
|
||||||
|
this._removeButton = null;
|
||||||
|
this._indicatorsPanel = null;
|
||||||
|
this._indicatorsPanelWidth = null;
|
||||||
|
|
||||||
|
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
|
||||||
|
for (let w = 0; w < this._workspaces.length; w++) {
|
||||||
|
if (w != activeWorkspaceIndex) {
|
||||||
|
this._workspaces[w].actor.hide();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
this._workspaces[w].actor.show();
|
||||||
|
this._workspaces[w]._windowOverlaysGroup.show();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_positionWorkspaces: function() {
|
||||||
|
let position = global.screen.get_active_workspace_index();
|
||||||
|
let scale = this._width / global.screen_width;
|
||||||
|
|
||||||
|
if (this._scroll != null)
|
||||||
|
position = this._scroll.adjustment.value;
|
||||||
|
let isInt = (Math.round(position) === position);
|
||||||
|
|
||||||
|
for (let w = 0; w < this._workspaces.length; w++) {
|
||||||
|
let workspace = this._workspaces[w];
|
||||||
|
|
||||||
|
workspace.gridRow = 0;
|
||||||
|
workspace.gridCol = 0;
|
||||||
|
|
||||||
|
workspace.scale = scale;
|
||||||
|
workspace.actor.set_scale(scale, scale);
|
||||||
|
workspace.gridX = this._x + (w - position) * workspace.actor.width;
|
||||||
|
workspace.gridY = this._y;
|
||||||
|
workspace.actor.set_position(workspace.gridX, workspace.gridY);
|
||||||
|
if (isInt) {
|
||||||
|
if (this.actor.get_stage() != null)
|
||||||
|
workspace.positionWindows(0);
|
||||||
|
if (w == position) {
|
||||||
|
workspace._windowOverlaysGroup.show();
|
||||||
|
workspace.actor.show();
|
||||||
|
} else {
|
||||||
|
workspace._windowOverlaysGroup.hide();
|
||||||
|
workspace.actor.hide();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
workspace._windowOverlaysGroup.hide();
|
||||||
|
if (Math.abs(w - position) <= 1)
|
||||||
|
workspace.actor.show();
|
||||||
|
else
|
||||||
|
workspace.actor.hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_workspacesChanged: function() {
|
||||||
|
let oldNumWorkspaces = this._workspaces.length;
|
||||||
|
let newNumWorkspaces = global.screen.n_workspaces;
|
||||||
|
|
||||||
|
if (oldNumWorkspaces == newNumWorkspaces)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (this._scroll != null) {
|
||||||
|
let adj = this._scroll.get_adjustment();
|
||||||
|
adj.upper = newNumWorkspaces;
|
||||||
|
this._scroll.adjustment = adj;
|
||||||
|
}
|
||||||
|
let lostWorkspaces = [];
|
||||||
|
|
||||||
|
if (newNumWorkspaces > oldNumWorkspaces) {
|
||||||
|
// Create new workspace groups
|
||||||
|
for (let w = oldNumWorkspaces; w < newNumWorkspaces; w++) {
|
||||||
|
this._addWorkspaceActor(w);
|
||||||
|
this._workspaces[w].actor.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
for (let i = 0; i < this._workspaces.length; i++)
|
||||||
|
this._workspaces[i].destroy();
|
||||||
|
this._actor.remove_all();
|
||||||
|
|
||||||
|
//Without this will be a lot of warnings
|
||||||
|
this._actor.hide();
|
||||||
|
|
||||||
|
this._workspaces = [];
|
||||||
|
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
|
||||||
|
for (let w = 0; w < global.screen.n_workspaces; w++) {
|
||||||
|
this._addWorkspaceActor(w);
|
||||||
|
if (w == activeWorkspaceIndex) {
|
||||||
|
this._workspaces[w].actor.show();
|
||||||
|
} else {
|
||||||
|
this._workspaces[w].actor.hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this._actor.show();
|
||||||
|
}
|
||||||
|
this._positionWorkspaces();
|
||||||
|
|
||||||
|
// Reset the selection state; if we went from > 1 workspace to 1,
|
||||||
|
// this has the side effect of removing the frame border
|
||||||
|
let activeIndex = global.screen.get_active_workspace_index();
|
||||||
|
this._workspaces[activeIndex].actor.show();
|
||||||
|
this._workspaces[activeIndex]._windowOverlaysGroup.show();
|
||||||
|
|
||||||
|
this._updatePanelVisibility();
|
||||||
|
},
|
||||||
|
|
||||||
|
_activeWorkspaceChanged: function(wm, from, to, direction) {
|
||||||
|
this._updatePanelVisibility();
|
||||||
|
let showAnimation = true;
|
||||||
|
|
||||||
|
if (this._scroll != null) {
|
||||||
|
let adj = this._scroll.get_adjustment();
|
||||||
|
if (Math.round(adj.value - to) != adj.value - to)
|
||||||
|
showAnimation = false;
|
||||||
|
if (adj.value - to == 0)
|
||||||
|
showAnimation = false;
|
||||||
|
adj.value = to;
|
||||||
|
this._scroll.adjustment = adj;
|
||||||
|
}
|
||||||
|
if (showAnimation) {
|
||||||
|
let fx;
|
||||||
|
if (from > to) {
|
||||||
|
fx = this._workspaces[0].actor.width;
|
||||||
|
} else {
|
||||||
|
fx = -this._workspaces[0].actor.width;
|
||||||
|
}
|
||||||
|
this._workspaces[from]._windowOverlaysGroup.hide();
|
||||||
|
this._workspaces[to].actor.set_position(this._x - fx, this._workspaces[to].gridY);
|
||||||
|
this._workspaces[to].actor.show();
|
||||||
|
Tweener.addTween(this._workspaces[to].actor,
|
||||||
|
{ x: this._x,
|
||||||
|
transition: 'easeOutQuad',
|
||||||
|
time: WORKSPACE_SWITCH_TIME
|
||||||
|
});
|
||||||
|
|
||||||
|
Tweener.addTween(this._workspaces[from].actor,
|
||||||
|
{ x: this._x + fx,
|
||||||
|
transition: 'easeOutQuad',
|
||||||
|
time: WORKSPACE_SWITCH_TIME,
|
||||||
|
onComplete: this._positionWorkspaces,
|
||||||
|
onCompleteScope: this
|
||||||
|
});
|
||||||
|
} else
|
||||||
|
this._positionWorkspaces();
|
||||||
|
},
|
||||||
|
|
||||||
|
_addWorkspaceActor: function(workspaceNum) {
|
||||||
|
let workspace = new Workspace.Workspace(workspaceNum, this._actor);
|
||||||
|
this._actor.add_actor(workspace.actor);
|
||||||
|
workspace._windowOverlaysGroup.hide();
|
||||||
|
|
||||||
|
this._workspaces[workspaceNum] = workspace;
|
||||||
|
},
|
||||||
|
|
||||||
|
createControllerBar: function() {
|
||||||
|
let panel = new St.BoxLayout({ 'pack-start': true, vertical: true });
|
||||||
|
|
||||||
|
let actor = new St.BoxLayout({ 'pack-start': true });
|
||||||
|
let adj = new St.Adjustment({ value: global.screen.get_active_workspace_index(),
|
||||||
|
lower: 0,
|
||||||
|
'page-increment': 1,
|
||||||
|
'page-size': 1,
|
||||||
|
'step-increment': 1,
|
||||||
|
upper: this._workspaces.length });
|
||||||
|
this._scroll = new St.ScrollBar({ adjustment: null, vertical: false, name: 'SwitchScroll' });
|
||||||
|
|
||||||
|
this._scroll.connect('notify::adjustment', Lang.bind(this, function() {
|
||||||
|
this._scroll.adjustment.connect('notify::value', Lang.bind(this, function () {
|
||||||
|
if (Math.abs(Math.round(this._scroll.adjustment.value) - this._scroll.adjustment.value) < 0.1) {
|
||||||
|
this._scroll.adjustment.set_value (Math.round(this._scroll.adjustment.value));
|
||||||
|
this._workspaces[Math.round(this._scroll.adjustment.value)]._metaWorkspace.activate(global.get_current_time());
|
||||||
|
} else
|
||||||
|
this._positionWorkspaces();
|
||||||
|
}));
|
||||||
|
}));
|
||||||
|
this._scroll.adjustment = adj;
|
||||||
|
|
||||||
|
let addButton = new St.Button({ style_class: "single-view-add" });
|
||||||
|
this._addButton = addButton;
|
||||||
|
addButton.connect('clicked', Lang.bind(this, this._addNewWorkspace));
|
||||||
|
addButton._delegate = addButton;
|
||||||
|
addButton._delegate.acceptDrop = Lang.bind(this, function(source, actor, x, y, time) {
|
||||||
|
return this._acceptNewWorkspaceDrop(source, actor, x, y, time);
|
||||||
|
});
|
||||||
|
actor.add(addButton, {x_align: St.Align.END, y_align: St.Align.START, 'y-fill': false});
|
||||||
|
|
||||||
|
let removeButton = new St.Button({ style_class: "single-view-remove" });
|
||||||
|
this._removeButton = removeButton;
|
||||||
|
removeButton.connect('clicked', Lang.bind(this, function() {
|
||||||
|
if (this._workspaces.length <= 1)
|
||||||
|
return;
|
||||||
|
let index = global.screen.get_active_workspace_index();
|
||||||
|
if (index == 0)
|
||||||
|
return;
|
||||||
|
global.screen.remove_workspace(this._workspaces[index]._metaWorkspace, global.get_current_time());
|
||||||
|
}));
|
||||||
|
actor.add(removeButton, { x_align: St.Align.END, y_align: St.Align.START, 'y-fill': false });
|
||||||
|
this._updatePanelVisibility();
|
||||||
|
|
||||||
|
panel.add(this._createPositionalIndicator(), {expand: true, 'x-fill': true, 'y-fill': true});
|
||||||
|
panel.add(this._scroll, { expand: true,
|
||||||
|
'x-fill': true,
|
||||||
|
'y-fill': false,
|
||||||
|
y_align: St.Align.START });
|
||||||
|
// backward-stepper/forward-stepper has const width (= height)
|
||||||
|
let separator = new St.Button({ style_class: 'scroll-separator' });
|
||||||
|
actor.add(separator, {});
|
||||||
|
|
||||||
|
actor.add(panel, {expand: true, 'x-fill': true, 'y-fill': true});
|
||||||
|
|
||||||
|
separator = new St.Button({ style_class: 'scroll-separator' });
|
||||||
|
actor.add(separator, {});
|
||||||
|
|
||||||
|
return actor;
|
||||||
|
},
|
||||||
|
|
||||||
|
_addIndicatorClone: function(i, active) {
|
||||||
|
let actor = new St.Button({ style_class: 'workspace-indicator' });
|
||||||
|
if (active) {
|
||||||
|
actor.style_class = 'workspace-indicator-active';
|
||||||
|
}
|
||||||
|
actor.connect('button-release-event', Lang.bind(this, function() {
|
||||||
|
if (this._workspaces[i] != undefined)
|
||||||
|
this._workspaces[i]._metaWorkspace.activate(global.get_current_time());
|
||||||
|
}));
|
||||||
|
|
||||||
|
this._indicatorsPanel.add_actor(actor);
|
||||||
|
|
||||||
|
let [a, spacing] = actor.get_theme_node().get_length('border-spacing', false);
|
||||||
|
if (this._indicatorsPanelWidth < spacing * (i + 1) + actor.width * (i + 1))
|
||||||
|
actor.hide();
|
||||||
|
actor.x = spacing * i + actor.width * i;
|
||||||
|
},
|
||||||
|
|
||||||
|
_fillPositionalIndicator: function() {
|
||||||
|
if (this._indicatorsPanel == null || this._indicatorsPanelWidth == null)
|
||||||
|
return;
|
||||||
|
let width = this._indicatorsPanelWidth;
|
||||||
|
this._indicatorsPanel.remove_all();
|
||||||
|
|
||||||
|
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
|
||||||
|
for (let i = 0; i < this._workspaces.length; i++) {
|
||||||
|
this._addIndicatorClone(i, i == activeWorkspaceIndex);
|
||||||
|
}
|
||||||
|
this._indicatorsPanel.x = (this._indicatorsPanelWidth - this._indicatorsPanel.width) / 2;
|
||||||
|
},
|
||||||
|
|
||||||
|
_createPositionalIndicator: function() {
|
||||||
|
let actor = new St.Bin({ style_class: 'panel-button' });
|
||||||
|
let group = new Clutter.Group();
|
||||||
|
|
||||||
|
this._indicatorsPanel = new Shell.GenericContainer();
|
||||||
|
this._indicatorsPanel.connect('get-preferred-width', Lang.bind(this, function (actor, fh, alloc) {
|
||||||
|
let children = actor.get_children();
|
||||||
|
let width = 0;
|
||||||
|
for (let i = 0; i < children.length; i++) {
|
||||||
|
if (!children[i].visible)
|
||||||
|
continue;
|
||||||
|
if (children[i].x + children[i].width <= width)
|
||||||
|
continue;
|
||||||
|
width = children[i].x + children[i].width;
|
||||||
|
}
|
||||||
|
alloc.min_size = width;
|
||||||
|
alloc.nat_size = width;
|
||||||
|
}));
|
||||||
|
this._indicatorsPanel.connect('get-preferred-height', Lang.bind(this, function (actor, fw, alloc) {
|
||||||
|
let children = actor.get_children();
|
||||||
|
let height = 0;
|
||||||
|
if (children.length)
|
||||||
|
height = children[0].height;
|
||||||
|
alloc.min_size = height;
|
||||||
|
alloc.nat_size = height;
|
||||||
|
}));
|
||||||
|
this._indicatorsPanel.connect('allocate', Lang.bind(this, function (actor, box, flags) {
|
||||||
|
let children = actor.get_children();
|
||||||
|
for (let i = 0; i < children.length; i++) {
|
||||||
|
if (!children[i].visible)
|
||||||
|
continue;
|
||||||
|
let childBox = new Clutter.ActorBox();
|
||||||
|
childBox.x1 = children[i].x;
|
||||||
|
childBox.y1 = 0;
|
||||||
|
childBox.x2 = children[i].x + children[i].width;
|
||||||
|
childBox.y2 = children[i].height;
|
||||||
|
children[i].allocate(childBox, flags);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
group.add_actor(this._indicatorsPanel);
|
||||||
|
actor.set_child(group);
|
||||||
|
actor.set_alignment(St.Align.START, St.Align.START);
|
||||||
|
actor.set_fill(true, true);
|
||||||
|
this._indicatorsPanel.hide();
|
||||||
|
actor.connect('notify::width', Lang.bind(this, function(actor) {
|
||||||
|
this._indicatorsPanelWidth = actor.width;
|
||||||
|
this._updatePanelVisibility();
|
||||||
|
}));
|
||||||
|
actor.connect('destroy', Lang.bind(this, function() {
|
||||||
|
this._indicatorsPanel = null;
|
||||||
|
}));
|
||||||
|
return actor;
|
||||||
|
},
|
||||||
|
|
||||||
|
_updatePanelVisibility: function() {
|
||||||
|
let n = global.screen.n_workspaces;
|
||||||
|
if (this._removeButton != null) {
|
||||||
|
// set opacity here, because if hide it, _scroll will fill this space.
|
||||||
|
if (global.screen.get_active_workspace_index() == 0)
|
||||||
|
this._removeButton.set_opacity(0);
|
||||||
|
else
|
||||||
|
this._removeButton.set_opacity(255);
|
||||||
|
}
|
||||||
|
if (this._addButton != null) {
|
||||||
|
// same here
|
||||||
|
this._addButton.set_opacity((global.screen.n_workspaces < MAX_WORKSPACES) * 255);
|
||||||
|
}
|
||||||
|
if (this._scroll != null) {
|
||||||
|
if (n > 1)
|
||||||
|
this._scroll.show();
|
||||||
|
else
|
||||||
|
this._scroll.hide();
|
||||||
|
}
|
||||||
|
if (this._indicatorsPanel != null) {
|
||||||
|
if (n == 1) {
|
||||||
|
this._indicatorsPanel.hide();
|
||||||
|
} else {
|
||||||
|
this._indicatorsPanel.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this._fillPositionalIndicator();
|
||||||
|
},
|
||||||
|
|
||||||
|
_addNewWorkspace: function() {
|
||||||
|
// Button with opacity 0 is clickable.
|
||||||
|
if (global.screen.n_workspaces >= MAX_WORKSPACES)
|
||||||
|
return;
|
||||||
|
global.screen.append_new_workspace(false, global.get_current_time());
|
||||||
|
this._workspaces[this._workspaces.length - 1]._metaWorkspace.activate(Clutter.get_current_event_time());
|
||||||
|
},
|
||||||
|
|
||||||
|
_acceptNewWorkspaceDrop: function(source, dropActor, x, y, time) {
|
||||||
|
this._addNewWorkspace();
|
||||||
|
return this.acceptNewWorkspaceDrop(source, dropActor, x, y, time);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function _workspaceRelativeModifier(workspace) {
|
||||||
|
let [startX, startY] = Main.overview.getPosition();
|
||||||
|
let overviewPosX, overviewPosY, overviewScale;
|
||||||
|
|
||||||
|
if (!workspace)
|
||||||
|
return [];
|
||||||
|
|
||||||
|
if (workspace.leavingOverview) {
|
||||||
|
let [zoomedInX, zoomedInY] = Main.overview.getZoomedInPosition();
|
||||||
|
overviewPosX = { begin: startX, end: zoomedInX };
|
||||||
|
overviewPosY = { begin: startY, end: zoomedInY };
|
||||||
|
overviewScale = { begin: Main.overview.getScale(),
|
||||||
|
end: Main.overview.getZoomedInScale() };
|
||||||
|
} else {
|
||||||
|
overviewPosX = { begin: startX, end: 0 };
|
||||||
|
overviewPosY = { begin: startY, end: 0 };
|
||||||
|
overviewScale = { begin: Main.overview.getScale(), end: 1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
return [ { name: "x",
|
||||||
|
parameters: { workspacePos: workspace.gridX,
|
||||||
|
overviewPos: overviewPosX,
|
||||||
|
overviewScale: overviewScale } },
|
||||||
|
{ name: "y",
|
||||||
|
parameters: { workspacePos: workspace.gridY,
|
||||||
|
overviewPos: overviewPosY,
|
||||||
|
overviewScale: overviewScale } }
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
function _workspaceRelativeGet(begin, end, time, params) {
|
||||||
|
let curOverviewPos = (1 - time) * params.overviewPos.begin +
|
||||||
|
time * params.overviewPos.end;
|
||||||
|
let curOverviewScale = (1 - time) * params.overviewScale.begin +
|
||||||
|
time * params.overviewScale.end;
|
||||||
|
|
||||||
|
// Calculate the screen position of the window.
|
||||||
|
let screen = (1 - time) *
|
||||||
|
((begin + params.workspacePos) * params.overviewScale.begin +
|
||||||
|
params.overviewPos.begin) +
|
||||||
|
time *
|
||||||
|
((end + params.workspacePos) * params.overviewScale.end +
|
||||||
|
params.overviewPos.end);
|
||||||
|
|
||||||
|
// Return the workspace coordinates.
|
||||||
|
return (screen - curOverviewPos) / curOverviewScale - params.workspacePos;
|
||||||
|
}
|
||||||
|
|
||||||
|
function WorkspacesViewSwitch() {
|
||||||
|
this._init();
|
||||||
|
}
|
||||||
|
|
||||||
|
WorkspacesViewSwitch.prototype = {
|
||||||
|
VIEW_KEY: 'view',
|
||||||
|
|
||||||
|
_init: function() {
|
||||||
|
this._gconf = Shell.GConf.get_default();
|
||||||
|
this._mosaicViewButton = null;
|
||||||
|
this._singleViewButton = null;
|
||||||
|
this._currentViewType = this._gconf.get_int(this.VIEW_KEY);
|
||||||
|
this._controlsBar = null;
|
||||||
|
},
|
||||||
|
|
||||||
|
_setView: function(view) {
|
||||||
|
this._mosaicViewButton.set_checked(WorkspacesViewType.MOSAIC == view);
|
||||||
|
this._singleViewButton.set_checked(WorkspacesViewType.SINGLE == view);
|
||||||
|
|
||||||
|
if (this._currentViewType == view)
|
||||||
|
return;
|
||||||
|
this._currentViewType = view;
|
||||||
|
this._gconf.set_int(this.VIEW_KEY, view);
|
||||||
|
this.emit('view-changed');
|
||||||
|
},
|
||||||
|
|
||||||
|
createCurrentWorkspaceView: function(width, height, x, y, animate) {
|
||||||
|
switch (this._currentViewType) {
|
||||||
|
case WorkspacesViewType.SINGLE:
|
||||||
|
return new SingleView(width, height, x, y, animate);
|
||||||
|
case WorkspacesViewType.MOSAIC:
|
||||||
|
return new MosaicView(width, height, x, y, animate);
|
||||||
|
default:
|
||||||
|
return new MosaicView(width, height, x, y, animate);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
createControlsBar: function() {
|
||||||
|
let actor = new St.BoxLayout();
|
||||||
|
|
||||||
|
this._mosaicViewButton = new St.Button({ style_class: "switch-view-mosaic" });
|
||||||
|
this._mosaicViewButton.set_toggle_mode(true);
|
||||||
|
this._mosaicViewButton.connect('clicked', Lang.bind(this, function() {
|
||||||
|
this._setView(WorkspacesViewType.MOSAIC);
|
||||||
|
}));
|
||||||
|
actor.add(this._mosaicViewButton, {'y-fill' : false, 'y-align' : St.Align.START});
|
||||||
|
|
||||||
|
this._singleViewButton = new St.Button({ style_class: "switch-view-single" });
|
||||||
|
this._singleViewButton.set_toggle_mode(true);
|
||||||
|
this._singleViewButton.connect('clicked', Lang.bind(this, function() {
|
||||||
|
this._setView(WorkspacesViewType.SINGLE);
|
||||||
|
}));
|
||||||
|
actor.add(this._singleViewButton, {'y-fill' : false, 'y-align' : St.Align.START});
|
||||||
|
|
||||||
|
if (this._currentViewType == WorkspacesViewType.MOSAIC)
|
||||||
|
this._mosaicViewButton.set_checked(true);
|
||||||
|
else
|
||||||
|
this._singleViewButton.set_checked(true);
|
||||||
|
|
||||||
|
this._nWorkspacesNotifyId =
|
||||||
|
global.screen.connect('notify::n-workspaces',
|
||||||
|
Lang.bind(this, this._workspacesChanged));
|
||||||
|
|
||||||
|
actor.connect('destroy', Lang.bind(this, function() {
|
||||||
|
this._controlsBar = null;
|
||||||
|
global.screen.disconnect(this._nWorkspacesNotifyId);
|
||||||
|
}));
|
||||||
|
|
||||||
|
this._controlsBar = actor;
|
||||||
|
this._workspacesChanged();
|
||||||
|
return actor;
|
||||||
|
},
|
||||||
|
|
||||||
|
_workspacesChanged: function() {
|
||||||
|
if (this._controlsBar == null)
|
||||||
|
return;
|
||||||
|
if (global.screen.n_workspaces == 1)
|
||||||
|
this._controlsBar.set_opacity(0);
|
||||||
|
else
|
||||||
|
this._controlsBar.set_opacity(255);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Signals.addSignalMethods(WorkspacesViewSwitch.prototype);
|