Compare commits
48 Commits
citadel
...
overlay-de
Author | SHA1 | Date | |
---|---|---|---|
|
e191636f34 | ||
|
39e31a3aa9 | ||
|
8293f3423a | ||
|
858a82fcdd | ||
|
2ae89f3b36 | ||
|
cdee026095 | ||
|
340fbfe943 | ||
|
c577951ec9 | ||
|
d588b083d9 | ||
|
e57b7ec335 | ||
|
b5988a57fa | ||
|
d5a80d3063 | ||
|
02a8cd5ce2 | ||
|
aa77762d27 | ||
|
de3f5dec68 | ||
|
84865f416d | ||
|
ca3e3df199 | ||
|
643febebf8 | ||
|
6d002c893d | ||
|
5eaed34047 | ||
|
8f5b55350f | ||
|
c600ebb687 | ||
|
9abc062a64 | ||
|
81d0474926 | ||
|
c41902c188 | ||
|
97b9ccbff7 | ||
|
282daf768f | ||
|
1b057300b0 | ||
|
75da772d05 | ||
|
df9cf98826 | ||
|
d3cb8e5b21 | ||
|
71998a6b43 | ||
|
2fd2293e4a | ||
|
3528eef655 | ||
|
f209d6792d | ||
|
614e83476e | ||
|
4e2a301ef0 | ||
|
6def8cf7dd | ||
|
1204898d1e | ||
|
98530afd87 | ||
|
a9fedcce76 | ||
|
dae1d94258 | ||
|
4a7c328c33 | ||
|
2c0d6fdf89 | ||
|
12f896eb94 | ||
|
230c91b6d4 | ||
|
d7dcfe6a06 | ||
|
275eba17db |
74
data/close.svg
Normal file
74
data/close.svg
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 13.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 14948) -->
|
||||||
|
<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"
|
||||||
|
version="1.1"
|
||||||
|
id="Foreground"
|
||||||
|
x="0px"
|
||||||
|
y="0px"
|
||||||
|
width="16px"
|
||||||
|
height="16px"
|
||||||
|
viewBox="0 0 16 16"
|
||||||
|
enable-background="new 0 0 16 16"
|
||||||
|
xml:space="preserve"
|
||||||
|
sodipodi:version="0.32"
|
||||||
|
inkscape:version="0.46"
|
||||||
|
sodipodi:docname="x_circle_16.svg"
|
||||||
|
inkscape:output_extension="org.inkscape.output.svg.inkscape"><metadata
|
||||||
|
id="metadata2399"><rdf:RDF><cc:Work
|
||||||
|
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
|
||||||
|
id="defs2397"><linearGradient
|
||||||
|
id="linearGradient3173"><stop
|
||||||
|
style="stop-color:#c4c4c4;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop3175" /><stop
|
||||||
|
style="stop-color:#ffffff;stop-opacity:1;"
|
||||||
|
offset="1"
|
||||||
|
id="stop3177" /></linearGradient><inkscape:perspective
|
||||||
|
sodipodi:type="inkscape:persp3d"
|
||||||
|
inkscape:vp_x="0 : 8 : 1"
|
||||||
|
inkscape:vp_y="0 : 1000 : 0"
|
||||||
|
inkscape:vp_z="16 : 8 : 1"
|
||||||
|
inkscape:persp3d-origin="8 : 5.3333333 : 1"
|
||||||
|
id="perspective2401" /><linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient3173"
|
||||||
|
id="linearGradient3179"
|
||||||
|
x1="7.844358"
|
||||||
|
y1="16"
|
||||||
|
x2="7.7198443"
|
||||||
|
y2="-0.062256809"
|
||||||
|
gradientUnits="userSpaceOnUse" /></defs><sodipodi:namedview
|
||||||
|
inkscape:window-height="713"
|
||||||
|
inkscape:window-width="1197"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
guidetolerance="10.0"
|
||||||
|
gridtolerance="10.0"
|
||||||
|
objecttolerance="10.0"
|
||||||
|
borderopacity="1.0"
|
||||||
|
bordercolor="#666666"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
id="base"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="32.125"
|
||||||
|
inkscape:cx="8"
|
||||||
|
inkscape:cy="8"
|
||||||
|
inkscape:window-x="40"
|
||||||
|
inkscape:window-y="40"
|
||||||
|
inkscape:current-layer="Foreground" />
|
||||||
|
<path
|
||||||
|
fill-rule="evenodd"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
d="M10.5,3.5l2,2L10,8l2.5,2.5l-2,2L8,10l-2.5,2.5l-2-2L6,8L3.5,5.5l2-2L8,6L10.5,3.5 z M0,8c0-4.418,3.582-8,8-8s8,3.582,8,8s-3.582,8-8,8S0,12.418,0,8z"
|
||||||
|
id="path2394"
|
||||||
|
style="fill-opacity:1;fill:url(#linearGradient3179)" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.6 KiB |
@ -15,6 +15,21 @@
|
|||||||
</locale>
|
</locale>
|
||||||
</schema>
|
</schema>
|
||||||
|
|
||||||
|
<schema>
|
||||||
|
<key>/schemas/desktop/gnome/shell/favorite_apps</key>
|
||||||
|
<applyto>/desktop/gnome/shell/favorite_apps</applyto>
|
||||||
|
<owner>gnome-shell</owner>
|
||||||
|
<type>list</type>
|
||||||
|
<listtype>string</listtype>
|
||||||
|
<default>[mozilla-firefox.desktop,evolution.desktop,openoffice.org-writer.desktop]</default>
|
||||||
|
<locale name="C">
|
||||||
|
<short>List of desktop file IDs for favorite applications</short>
|
||||||
|
<long>
|
||||||
|
The applications corresponding to these identifiers will be displayed in the favorites area.
|
||||||
|
</long>
|
||||||
|
</locale>
|
||||||
|
</schema>
|
||||||
|
|
||||||
</schemalist>
|
</schemalist>
|
||||||
|
|
||||||
</gconfschemafile>
|
</gconfschemafile>
|
74
data/info.svg
Normal file
74
data/info.svg
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 13.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 14948) -->
|
||||||
|
<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"
|
||||||
|
version="1.1"
|
||||||
|
id="Foreground"
|
||||||
|
x="0px"
|
||||||
|
y="0px"
|
||||||
|
width="16px"
|
||||||
|
height="16px"
|
||||||
|
viewBox="0 0 16 16"
|
||||||
|
enable-background="new 0 0 16 16"
|
||||||
|
xml:space="preserve"
|
||||||
|
sodipodi:version="0.32"
|
||||||
|
inkscape:version="0.46"
|
||||||
|
sodipodi:docname="info_16.svg"
|
||||||
|
inkscape:output_extension="org.inkscape.output.svg.inkscape"><metadata
|
||||||
|
id="metadata2389"><rdf:RDF><cc:Work
|
||||||
|
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
|
||||||
|
id="defs2387"><linearGradient
|
||||||
|
id="linearGradient3710"><stop
|
||||||
|
style="stop-color:#c4c4c4;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop3712" /><stop
|
||||||
|
style="stop-color:#ffffff;stop-opacity:1;"
|
||||||
|
offset="1"
|
||||||
|
id="stop3714" /></linearGradient><inkscape:perspective
|
||||||
|
sodipodi:type="inkscape:persp3d"
|
||||||
|
inkscape:vp_x="0 : 8 : 1"
|
||||||
|
inkscape:vp_y="0 : 1000 : 0"
|
||||||
|
inkscape:vp_z="16 : 8 : 1"
|
||||||
|
inkscape:persp3d-origin="8 : 5.3333333 : 1"
|
||||||
|
id="perspective2391" /><linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient3710"
|
||||||
|
id="linearGradient3716"
|
||||||
|
x1="7.9066148"
|
||||||
|
y1="15.937743"
|
||||||
|
x2="7.9377432"
|
||||||
|
y2="0.031128405"
|
||||||
|
gradientUnits="userSpaceOnUse" /></defs><sodipodi:namedview
|
||||||
|
inkscape:window-height="713"
|
||||||
|
inkscape:window-width="722"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
guidetolerance="10.0"
|
||||||
|
gridtolerance="10.0"
|
||||||
|
objecttolerance="10.0"
|
||||||
|
borderopacity="1.0"
|
||||||
|
bordercolor="#666666"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
id="base"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="32.125"
|
||||||
|
inkscape:cx="8"
|
||||||
|
inkscape:cy="8.154146"
|
||||||
|
inkscape:window-x="20"
|
||||||
|
inkscape:window-y="20"
|
||||||
|
inkscape:current-layer="Foreground" />
|
||||||
|
<path
|
||||||
|
fill-rule="evenodd"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
d="M7,3h2v2H7V3z M5.5,12H7V8H5.5V7H9v5h1.5v1h-5V12z M0,8c0-4.418,3.582-8,8-8 s8,3.582,8,8s-3.582,8-8,8S0,12.418,0,8z"
|
||||||
|
id="path2384"
|
||||||
|
style="fill-opacity:1;fill:url(#linearGradient3716)" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.5 KiB |
66
data/view-more-activated.svg
Normal file
66
data/view-more-activated.svg
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 13.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 14948) -->
|
||||||
|
<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"
|
||||||
|
version="1.1"
|
||||||
|
id="Foreground"
|
||||||
|
x="0px"
|
||||||
|
y="0px"
|
||||||
|
width="29px"
|
||||||
|
height="18px"
|
||||||
|
viewBox="0 0 29 18"
|
||||||
|
enable-background="new 0 0 29 18"
|
||||||
|
xml:space="preserve"
|
||||||
|
sodipodi:version="0.32"
|
||||||
|
inkscape:version="0.46"
|
||||||
|
sodipodi:docname="search_2.svg"
|
||||||
|
inkscape:output_extension="org.inkscape.output.svg.inkscape"><metadata
|
||||||
|
id="metadata16"><rdf:RDF><cc:Work
|
||||||
|
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
|
||||||
|
id="defs14"><inkscape:perspective
|
||||||
|
sodipodi:type="inkscape:persp3d"
|
||||||
|
inkscape:vp_x="0 : 9 : 1"
|
||||||
|
inkscape:vp_y="0 : 1000 : 0"
|
||||||
|
inkscape:vp_z="29 : 9 : 1"
|
||||||
|
inkscape:persp3d-origin="14.5 : 6 : 1"
|
||||||
|
id="perspective18" />
|
||||||
|
|
||||||
|
|
||||||
|
</defs><sodipodi:namedview
|
||||||
|
inkscape:window-height="728"
|
||||||
|
inkscape:window-width="1103"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
guidetolerance="10.0"
|
||||||
|
gridtolerance="10.0"
|
||||||
|
objecttolerance="10.0"
|
||||||
|
borderopacity="1.0"
|
||||||
|
bordercolor="#666666"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
id="base"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="19.275862"
|
||||||
|
inkscape:cx="14.5"
|
||||||
|
inkscape:cy="9"
|
||||||
|
inkscape:window-x="40"
|
||||||
|
inkscape:window-y="40"
|
||||||
|
inkscape:current-layer="Foreground"><inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid2391" /></sodipodi:namedview>
|
||||||
|
|
||||||
|
<path
|
||||||
|
style="fill:#4669a9;fill-opacity:1"
|
||||||
|
id="path9"
|
||||||
|
d="" />
|
||||||
|
<path
|
||||||
|
id="path3"
|
||||||
|
style="fill:#3d5a93;fill-opacity:1"
|
||||||
|
d="M 0,3 C 0,1.343 1.343,0 3,0 L 20,0 C 20.515,0 21.027,0.195 21.42,0.588 L 28.412,7.58 C 29.196,8.364 29.196,9.636 28.412,10.42 L 21.42,17.412 C 21.028,17.804 20.514,18 20,18 L 3,18 C 1.343,18 0,16.657 0,15 L 0,3 zM 13.5,3 C 11.015,3 9,5.015 9,7.5 C 9,8.2423219 9.1815696,8.9452421 9.5,9.5625 L 6.25,12.8125 C 5.931,13.1325 5.9310002,13.64975 6.25,13.96875 L 7.03125,14.78125 C 7.35025,15.10025 7.8674999,15.10025 8.1875,14.78125 L 11.46875,11.5 C 12.080227,11.810879 12.767137,12 13.5,12 C 15.985,12 18,9.985 18,7.5 C 18,5.015 15.985,3 13.5,3 z M 11.25,7.5 C 11.25,6.257 12.257,5.25 13.5,5.25 C 14.743,5.25 15.75,6.257 15.75,7.5 C 15.75,8.743 14.743,9.75 13.5,9.75 C 12.257,9.75 11.25,8.743 11.25,7.5 z" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.7 KiB |
79
data/view-more.svg
Normal file
79
data/view-more.svg
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 13.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 14948) -->
|
||||||
|
<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"
|
||||||
|
version="1.1"
|
||||||
|
id="Foreground"
|
||||||
|
x="0px"
|
||||||
|
y="0px"
|
||||||
|
width="29px"
|
||||||
|
height="18px"
|
||||||
|
viewBox="0 0 29 18"
|
||||||
|
enable-background="new 0 0 29 18"
|
||||||
|
xml:space="preserve"
|
||||||
|
sodipodi:version="0.32"
|
||||||
|
inkscape:version="0.46"
|
||||||
|
sodipodi:docname="search_1.svg"
|
||||||
|
inkscape:output_extension="org.inkscape.output.svg.inkscape"><metadata
|
||||||
|
id="metadata16"><rdf:RDF><cc:Work
|
||||||
|
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
|
||||||
|
id="defs14"><inkscape:perspective
|
||||||
|
sodipodi:type="inkscape:persp3d"
|
||||||
|
inkscape:vp_x="0 : 9 : 1"
|
||||||
|
inkscape:vp_y="0 : 1000 : 0"
|
||||||
|
inkscape:vp_z="29 : 9 : 1"
|
||||||
|
inkscape:persp3d-origin="14.5 : 6 : 1"
|
||||||
|
id="perspective18" /></defs><sodipodi:namedview
|
||||||
|
inkscape:window-height="728"
|
||||||
|
inkscape:window-width="1103"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
guidetolerance="10.0"
|
||||||
|
gridtolerance="10.0"
|
||||||
|
objecttolerance="10.0"
|
||||||
|
borderopacity="1.0"
|
||||||
|
bordercolor="#666666"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
id="base"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="19.275862"
|
||||||
|
inkscape:cx="14.5"
|
||||||
|
inkscape:cy="9"
|
||||||
|
inkscape:window-x="40"
|
||||||
|
inkscape:window-y="40"
|
||||||
|
inkscape:current-layer="Foreground"><inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid2391" /></sodipodi:namedview>
|
||||||
|
<path
|
||||||
|
d="M0,3c0-1.657,1.343-3,3-3h17c0.515,0,1.027,0.195,1.42,0.588l6.992,6.992c0.784,0.784,0.784,2.056,0,2.84l-6.992,6.992 C21.028,17.804,20.514,18,20,18H3c-1.657,0-3-1.343-3-3V3z"
|
||||||
|
id="path3"
|
||||||
|
style="fill:#151e2f;fill-opacity:1" />
|
||||||
|
<g
|
||||||
|
id="g5"
|
||||||
|
style="fill:#4669a9;fill-opacity:1">
|
||||||
|
<path
|
||||||
|
fill="#FFFFFF"
|
||||||
|
d="M6.246,13.98c-0.319-0.319-0.319-0.837,0-1.157l3.717-3.717c0.319-0.319,0.837-0.319,1.157,0l0.786,0.787 c0.32,0.319,0.32,0.837,0,1.157l-3.717,3.717c-0.32,0.319-0.838,0.319-1.157,0L6.246,13.98L6.246,13.98z"
|
||||||
|
id="path7"
|
||||||
|
style="fill:#4669a9;fill-opacity:1" />
|
||||||
|
<path
|
||||||
|
fill="#FFFFFF"
|
||||||
|
d="M9.076,11.937"
|
||||||
|
id="path9"
|
||||||
|
style="fill:#4669a9;fill-opacity:1" />
|
||||||
|
</g>
|
||||||
|
<path
|
||||||
|
fill-rule="evenodd"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
fill="#FFFFFF"
|
||||||
|
d="M11.25,7.5c0-1.243,1.007-2.25,2.25-2.25s2.25,1.007,2.25,2.25 s-1.007,2.25-2.25,2.25S11.25,8.743,11.25,7.5z M9,7.5C9,5.015,11.015,3,13.5,3S18,5.015,18,7.5S15.985,12,13.5,12S9,9.985,9,7.5z"
|
||||||
|
id="path11"
|
||||||
|
style="fill:#4669a9;fill-opacity:1" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.8 KiB |
@ -7,32 +7,6 @@ const Shell = imports.gi.Shell;
|
|||||||
|
|
||||||
const Main = imports.ui.main;
|
const Main = imports.ui.main;
|
||||||
|
|
||||||
// TODO - move this into GConf once we're not a plugin anymore
|
|
||||||
// but have taken over metacity
|
|
||||||
// This list is taken from GNOME Online popular applications
|
|
||||||
// http://online.gnome.org/applications
|
|
||||||
// but with nautilus removed (since it should already be running)
|
|
||||||
// and evince, totem, and gnome-file-roller removed (since they're
|
|
||||||
// usually started by opening documents, not by opening the app
|
|
||||||
// directly)
|
|
||||||
const DEFAULT_APPLICATIONS = [
|
|
||||||
'mozilla-firefox.desktop',
|
|
||||||
'gnome-terminal.desktop',
|
|
||||||
'evolution.desktop',
|
|
||||||
'gedit.desktop',
|
|
||||||
'mozilla-thunderbird.desktop',
|
|
||||||
'rhythmbox.desktop',
|
|
||||||
'epiphany.desktop',
|
|
||||||
'xchat.desktop',
|
|
||||||
'openoffice.org-1.9-writer.desktop',
|
|
||||||
'emacs.desktop',
|
|
||||||
'gnome-system-monitor.desktop',
|
|
||||||
'openoffice.org-1.9-calc.desktop',
|
|
||||||
'eclipse.desktop',
|
|
||||||
'openoffice.org-1.9-impress.desktop',
|
|
||||||
'vncviewer.desktop'
|
|
||||||
];
|
|
||||||
|
|
||||||
function AppInfo(appId) {
|
function AppInfo(appId) {
|
||||||
this._init(appId);
|
this._init(appId);
|
||||||
}
|
}
|
||||||
@ -41,8 +15,9 @@ AppInfo.prototype = {
|
|||||||
_init : function(appId) {
|
_init : function(appId) {
|
||||||
this.appId = appId;
|
this.appId = appId;
|
||||||
this._gAppInfo = Gio.DesktopAppInfo.new(appId);
|
this._gAppInfo = Gio.DesktopAppInfo.new(appId);
|
||||||
if (!this._gAppInfo)
|
if (!this._gAppInfo) {
|
||||||
throw new Error('Unknown appId ' + appId);
|
throw new Error('Unknown appId ' + appId);
|
||||||
|
}
|
||||||
|
|
||||||
this.id = this._gAppInfo.get_id();
|
this.id = this._gAppInfo.get_id();
|
||||||
this.name = this._gAppInfo.get_name();
|
this.name = this._gAppInfo.get_name();
|
||||||
@ -52,7 +27,7 @@ AppInfo.prototype = {
|
|||||||
this._gicon = this._gAppInfo.get_icon();
|
this._gicon = this._gAppInfo.get_icon();
|
||||||
},
|
},
|
||||||
|
|
||||||
getIcon : function(size) {
|
createIcon : function(size) {
|
||||||
if (this._gicon)
|
if (this._gicon)
|
||||||
return Shell.TextureCache.get_default().load_gicon(this._gicon, size);
|
return Shell.TextureCache.get_default().load_gicon(this._gicon, size);
|
||||||
else
|
else
|
||||||
@ -96,40 +71,64 @@ function getAppInfo(appId) {
|
|||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
// getMostUsedApps:
|
// getTopApps:
|
||||||
// @count: maximum number of apps to retrieve
|
// @count: maximum number of apps to retrieve
|
||||||
//
|
//
|
||||||
// Gets a list of #AppInfos for the @count most-frequently-used
|
// Gets a list of #AppInfos for the @count most-frequently-used
|
||||||
// applications
|
// applications, with explicitly-chosen favorites first.
|
||||||
//
|
//
|
||||||
// Return value: the list of #AppInfo
|
// Return value: the list of #AppInfo
|
||||||
function getMostUsedApps(count) {
|
function getTopApps(count) {
|
||||||
let appMonitor = Shell.AppMonitor.get_default();
|
let appMonitor = Shell.AppMonitor.get_default();
|
||||||
|
|
||||||
|
let matches = [], alreadyAdded = {};
|
||||||
|
|
||||||
|
let favs = getFavorites();
|
||||||
|
for (let i = 0; i < favs.length && favs.length <= count; i++) {
|
||||||
|
let appId = favs[i].appId;
|
||||||
|
|
||||||
|
if (alreadyAdded[appId])
|
||||||
|
continue;
|
||||||
|
alreadyAdded[appId] = true;
|
||||||
|
|
||||||
|
matches.push(favs[i]);
|
||||||
|
}
|
||||||
|
|
||||||
// Ask for more apps than we need, since the list of recently used
|
// Ask for more apps than we need, since the list of recently used
|
||||||
// apps might contain an app we don't have a desktop file for
|
// apps might contain an app we don't have a desktop file for
|
||||||
let apps = appMonitor.get_most_used_apps (0, Math.round(count * 1.5));
|
let apps = appMonitor.get_most_used_apps (0, Math.round(count * 1.5));
|
||||||
let matches = [], alreadyAdded = {};
|
|
||||||
|
|
||||||
for (let i = 0; i < apps.length && matches.length <= count; i++) {
|
for (let i = 0; i < apps.length && matches.length <= count; i++) {
|
||||||
let appId = apps[i] + ".desktop";
|
let appId = apps[i] + ".desktop";
|
||||||
|
if (alreadyAdded[appId])
|
||||||
|
continue;
|
||||||
|
alreadyAdded[appId] = true;
|
||||||
let appInfo = getAppInfo(appId);
|
let appInfo = getAppInfo(appId);
|
||||||
if (appInfo) {
|
if (appInfo) {
|
||||||
matches.push(appInfo);
|
matches.push(appInfo);
|
||||||
alreadyAdded[appId] = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fill the list with default applications it's not full yet
|
|
||||||
for (let i = 0; i < DEFAULT_APPLICATIONS.length && matches.length <= count; i++) {
|
|
||||||
let appId = DEFAULT_APPLICATIONS[i];
|
|
||||||
if (alreadyAdded[appId])
|
|
||||||
continue;
|
|
||||||
|
|
||||||
let appInfo = getAppInfo(appId);
|
|
||||||
if (appInfo)
|
|
||||||
matches.push(appInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
return matches;
|
return matches;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _idListToInfos(ids) {
|
||||||
|
let infos = [];
|
||||||
|
for (let i = 0; i < ids.length; i++) {
|
||||||
|
let display = getAppInfo(ids[i]);
|
||||||
|
if (display == null)
|
||||||
|
continue;
|
||||||
|
infos.push(display);
|
||||||
|
}
|
||||||
|
return infos;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFavorites() {
|
||||||
|
let system = Shell.AppSystem.get_default();
|
||||||
|
|
||||||
|
return _idListToInfos(system.get_favorites());
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRunning() {
|
||||||
|
let monitor = Shell.AppMonitor.get_default();
|
||||||
|
return _idListToInfos(monitor.get_running_app_ids());
|
||||||
|
}
|
||||||
|
@ -21,7 +21,7 @@ DocInfo.prototype = {
|
|||||||
this.mimeType = recentInfo.get_mime_type();
|
this.mimeType = recentInfo.get_mime_type();
|
||||||
},
|
},
|
||||||
|
|
||||||
getIcon : function(size) {
|
createIcon : function(size) {
|
||||||
let icon = new Clutter.Texture();
|
let icon = new Clutter.Texture();
|
||||||
let iconPixbuf;
|
let iconPixbuf;
|
||||||
|
|
||||||
|
@ -5,16 +5,21 @@ const Clutter = imports.gi.Clutter;
|
|||||||
const Pango = imports.gi.Pango;
|
const Pango = imports.gi.Pango;
|
||||||
const Gio = imports.gi.Gio;
|
const Gio = imports.gi.Gio;
|
||||||
const Gtk = imports.gi.Gtk;
|
const Gtk = imports.gi.Gtk;
|
||||||
|
const Tidy = imports.gi.Tidy;
|
||||||
const Shell = imports.gi.Shell;
|
const Shell = imports.gi.Shell;
|
||||||
const Lang = imports.lang;
|
const Lang = imports.lang;
|
||||||
const Signals = imports.signals;
|
const Signals = imports.signals;
|
||||||
|
const Mainloop = imports.mainloop;
|
||||||
|
|
||||||
const AppInfo = imports.misc.appInfo;
|
const AppInfo = imports.misc.appInfo;
|
||||||
|
const DND = imports.ui.dnd;
|
||||||
const GenericDisplay = imports.ui.genericDisplay;
|
const GenericDisplay = imports.ui.genericDisplay;
|
||||||
|
|
||||||
const ENTERED_MENU_COLOR = new Clutter.Color();
|
const ENTERED_MENU_COLOR = new Clutter.Color();
|
||||||
ENTERED_MENU_COLOR.from_pixel(0x00ff0022);
|
ENTERED_MENU_COLOR.from_pixel(0x00ff0022);
|
||||||
|
|
||||||
|
const APP_ICON_SIZE = 48;
|
||||||
|
|
||||||
const MENU_ICON_SIZE = 24;
|
const MENU_ICON_SIZE = 24;
|
||||||
const MENU_SPACING = 15;
|
const MENU_SPACING = 15;
|
||||||
|
|
||||||
@ -33,11 +38,10 @@ AppDisplayItem.prototype = {
|
|||||||
__proto__: GenericDisplay.GenericDisplayItem.prototype,
|
__proto__: GenericDisplay.GenericDisplayItem.prototype,
|
||||||
|
|
||||||
_init : function(appInfo, availableWidth) {
|
_init : function(appInfo, availableWidth) {
|
||||||
GenericDisplay.GenericDisplayItem.prototype._init.call(this, availableWidth);
|
GenericDisplay.GenericDisplayItem.prototype._init.call(this, availableWidth);
|
||||||
this._appInfo = appInfo;
|
this._appInfo = appInfo;
|
||||||
|
|
||||||
this._setItemInfo(appInfo.name, appInfo.description,
|
this._setItemInfo(appInfo.name, appInfo.description);
|
||||||
appInfo.getIcon(GenericDisplay.ITEM_DISPLAY_ICON_SIZE));
|
|
||||||
},
|
},
|
||||||
|
|
||||||
//// Public method overrides ////
|
//// Public method overrides ////
|
||||||
@ -49,15 +53,20 @@ AppDisplayItem.prototype = {
|
|||||||
|
|
||||||
//// Protected method overrides ////
|
//// Protected method overrides ////
|
||||||
|
|
||||||
|
// Returns an icon for the item.
|
||||||
|
_createIcon : function() {
|
||||||
|
return this._appInfo.createIcon(GenericDisplay.ITEM_DISPLAY_ICON_SIZE);
|
||||||
|
},
|
||||||
|
|
||||||
// Ensures the preview icon is created.
|
// Ensures the preview icon is created.
|
||||||
_ensurePreviewIconCreated : function() {
|
_ensurePreviewIconCreated : function() {
|
||||||
if (!this._showPreview || this._previewIcon)
|
if (!this._showPreview || this._previewIcon)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
let previewIconPath = this._appInfo.getIconPath(GenericDisplay.PREVIEW_ICON_SIZE);
|
let previewIconPath = this._appInfo.getIconPath(GenericDisplay.PREVIEW_ICON_SIZE);
|
||||||
if (previewIconPath) {
|
if (previewIconPath) {
|
||||||
try {
|
try {
|
||||||
this._previewIcon = new Clutter.Texture({ width: GenericDisplay.PREVIEW_ICON_SIZE, height: GenericDisplay.PREVIEW_ICON_SIZE});
|
this._previewIcon = new Clutter.Texture({ width: GenericDisplay.PREVIEW_ICON_SIZE, height: GenericDisplay.PREVIEW_ICON_SIZE});
|
||||||
this._previewIcon.set_from_file(previewIconPath);
|
this._previewIcon.set_from_file(previewIconPath);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// we can get an error here if the file path doesn't exist on the system
|
// we can get an error here if the file path doesn't exist on the system
|
||||||
@ -147,6 +156,7 @@ MenuItem.prototype = {
|
|||||||
}
|
}
|
||||||
Signals.addSignalMethods(MenuItem.prototype);
|
Signals.addSignalMethods(MenuItem.prototype);
|
||||||
|
|
||||||
|
|
||||||
/* This class represents a display containing a collection of application items.
|
/* This class represents a display containing a collection of application items.
|
||||||
* The applications are sorted based on their popularity by default, and based on
|
* The applications are sorted based on their popularity by default, and based on
|
||||||
* their name if some search filter is applied.
|
* their name if some search filter is applied.
|
||||||
@ -173,16 +183,15 @@ AppDisplay.prototype = {
|
|||||||
this._appMonitor = Shell.AppMonitor.get_default();
|
this._appMonitor = Shell.AppMonitor.get_default();
|
||||||
this._appSystem = Shell.AppSystem.get_default();
|
this._appSystem = Shell.AppSystem.get_default();
|
||||||
this._appsStale = true;
|
this._appsStale = true;
|
||||||
this._appSystem.connect('changed', Lang.bind(this, function(appSys) {
|
this._appSystem.connect('installed-changed', Lang.bind(this, function(appSys) {
|
||||||
this._appsStale = true;
|
this._appsStale = true;
|
||||||
// We still need to determine what events other than search can trigger
|
|
||||||
// a change in the set of applications that are being shown while the
|
|
||||||
// user in in the overlay mode, however let's redisplay just in case.
|
|
||||||
this._redisplay(false);
|
this._redisplay(false);
|
||||||
this._redisplayMenus();
|
this._redisplayMenus();
|
||||||
}));
|
}));
|
||||||
|
this._appSystem.connect('favorites-changed', Lang.bind(this, function(appSys) {
|
||||||
|
this._redisplay(false);
|
||||||
|
}));
|
||||||
this._appMonitor.connect('changed', Lang.bind(this, function(monitor) {
|
this._appMonitor.connect('changed', Lang.bind(this, function(monitor) {
|
||||||
this._appsStale = true;
|
|
||||||
this._redisplay(false);
|
this._redisplay(false);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -308,8 +317,6 @@ AppDisplay.prototype = {
|
|||||||
this._appCategories[appId] = categories;
|
this._appCategories[appId] = categories;
|
||||||
},
|
},
|
||||||
|
|
||||||
//// Protected method overrides ////
|
|
||||||
|
|
||||||
// Gets information about all applications by calling Gio.app_info_get_all().
|
// Gets information about all applications by calling Gio.app_info_get_all().
|
||||||
_refreshCache : function() {
|
_refreshCache : function() {
|
||||||
let me = this;
|
let me = this;
|
||||||
@ -339,21 +346,12 @@ AppDisplay.prototype = {
|
|||||||
this._addAppForId(appId);
|
this._addAppForId(appId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Some applications, such as Evince, might not be in the menus,
|
|
||||||
// but might be returned by the applications monitor as most used
|
|
||||||
// applications, in which case we include them.
|
|
||||||
let mostUsedAppInfos = AppInfo.getMostUsedApps(MAX_ITEMS);
|
|
||||||
for (let i = 0; i < mostUsedAppInfos.length; i++) {
|
|
||||||
let appInfo = mostUsedAppInfos[i];
|
|
||||||
this._addApp(appInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
this._appsStale = false;
|
this._appsStale = false;
|
||||||
},
|
},
|
||||||
|
|
||||||
// Sets the list of the displayed items based on the most used apps.
|
// Sets the list of the displayed items based on the most used apps.
|
||||||
_setDefaultList : function() {
|
_setDefaultList : function() {
|
||||||
let matchedInfos = AppInfo.getMostUsedApps(MAX_ITEMS);
|
let matchedInfos = AppInfo.getTopApps(MAX_ITEMS);
|
||||||
this._matchedItems = matchedInfos.map(function(info) { return info.appId; });
|
this._matchedItems = matchedInfos.map(function(info) { return info.appId; });
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -430,3 +428,197 @@ AppDisplay.prototype = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Signals.addSignalMethods(AppDisplay.prototype);
|
Signals.addSignalMethods(AppDisplay.prototype);
|
||||||
|
|
||||||
|
function WellDisplayItem(appInfo, isFavorite) {
|
||||||
|
this._init(appInfo, isFavorite);
|
||||||
|
}
|
||||||
|
|
||||||
|
WellDisplayItem.prototype = {
|
||||||
|
_init : function(appInfo, isFavorite) {
|
||||||
|
this.appInfo = appInfo;
|
||||||
|
|
||||||
|
this.isFavorite = isFavorite;
|
||||||
|
|
||||||
|
this.actor = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
||||||
|
width: APP_ICON_SIZE,
|
||||||
|
reactive: true });
|
||||||
|
this.actor._delegate = this;
|
||||||
|
this.actor.connect('button-release-event', Lang.bind(this, function (b, e) {
|
||||||
|
this.launch();
|
||||||
|
this.emit('activated');
|
||||||
|
}));
|
||||||
|
|
||||||
|
let draggable = DND.makeDraggable(this.actor);
|
||||||
|
|
||||||
|
this._icon = appInfo.createIcon(APP_ICON_SIZE);
|
||||||
|
|
||||||
|
this.actor.append(this._icon, Big.BoxPackFlags.NONE);
|
||||||
|
|
||||||
|
let count = Shell.AppMonitor.get_default().get_window_count(appInfo.appId);
|
||||||
|
|
||||||
|
this._name = new Clutter.Text({ color: GenericDisplay.ITEM_DISPLAY_NAME_COLOR,
|
||||||
|
font_name: "Sans 12px",
|
||||||
|
ellipsize: Pango.EllipsizeMode.END,
|
||||||
|
text: appInfo.name });
|
||||||
|
if (count > 0) {
|
||||||
|
let runningBox = new Big.Box({ /* border_color: GenericDisplay.ITEM_DISPLAY_NAME_COLOR,
|
||||||
|
border: 1,
|
||||||
|
padding: 1 */ });
|
||||||
|
runningBox.append(this._name, Big.BoxPackFlags.EXPAND);
|
||||||
|
this.actor.append(runningBox, Big.BoxPackFlags.NONE);
|
||||||
|
} else {
|
||||||
|
this.actor.append(this._name, Big.BoxPackFlags.NONE);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// Opens an application represented by this display item.
|
||||||
|
launch : function() {
|
||||||
|
this.appInfo.launch();
|
||||||
|
},
|
||||||
|
|
||||||
|
// Draggable interface - FIXME deduplicate with GenericDisplay
|
||||||
|
getDragActor: function(stageX, stageY) {
|
||||||
|
this.dragActor = this.appInfo.createIcon(APP_ICON_SIZE);
|
||||||
|
|
||||||
|
// If the user dragged from the icon itself, then position
|
||||||
|
// the dragActor over the original icon. Otherwise center it
|
||||||
|
// around the pointer
|
||||||
|
let [iconX, iconY] = this._icon.get_transformed_position();
|
||||||
|
let [iconWidth, iconHeight] = this._icon.get_transformed_size();
|
||||||
|
if (stageX > iconX && stageX <= iconX + iconWidth &&
|
||||||
|
stageY > iconY && stageY <= iconY + iconHeight)
|
||||||
|
this.dragActor.set_position(iconX, iconY);
|
||||||
|
else
|
||||||
|
this.dragActor.set_position(stageX - this.dragActor.width / 2, stageY - this.dragActor.height / 2);
|
||||||
|
return this.dragActor;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Returns the original icon that is being used as a source for the cloned texture
|
||||||
|
// that represents the item as it is being dragged.
|
||||||
|
getDragActorSource: function() {
|
||||||
|
return this._icon;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Signals.addSignalMethods(WellDisplayItem.prototype);
|
||||||
|
|
||||||
|
function WellArea(width, isFavorite) {
|
||||||
|
this._init(width, isFavorite);
|
||||||
|
}
|
||||||
|
|
||||||
|
WellArea.prototype = {
|
||||||
|
_init : function(width, isFavorite) {
|
||||||
|
this.isFavorite = isFavorite;
|
||||||
|
|
||||||
|
this.actor = new Tidy.Grid({ width: width });
|
||||||
|
this.actor._delegate = this;
|
||||||
|
},
|
||||||
|
|
||||||
|
redisplay: function (infos) {
|
||||||
|
let children;
|
||||||
|
|
||||||
|
children = this.actor.get_children();
|
||||||
|
children.forEach(Lang.bind(this, function (v) {
|
||||||
|
v.destroy();
|
||||||
|
}));
|
||||||
|
|
||||||
|
for (let i = 0; i < infos.length; i++) {
|
||||||
|
let display = new WellDisplayItem(infos[i], this.isFavorite);
|
||||||
|
display.connect('activated', Lang.bind(this, function (display) {
|
||||||
|
this.emit('activated', display);
|
||||||
|
}));
|
||||||
|
this.actor.add_actor(display.actor);
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
// Draggable target interface
|
||||||
|
acceptDrop : function(source, actor, x, y, time) {
|
||||||
|
let global = Shell.Global.get();
|
||||||
|
|
||||||
|
if (!(source instanceof WellDisplayItem)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let appSystem = Shell.AppSystem.get_default();
|
||||||
|
let id = source.appInfo.appId;
|
||||||
|
if (source.isFavorite && (!this.isFavorite)) {
|
||||||
|
Mainloop.idle_add(function () {
|
||||||
|
appSystem.remove_favorite(id);
|
||||||
|
});
|
||||||
|
} else if ((!source.isFavorite) && this.isFavorite) {
|
||||||
|
Mainloop.idle_add(function () {
|
||||||
|
appSystem.add_favorite(id);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Signals.addSignalMethods(WellArea.prototype);
|
||||||
|
|
||||||
|
function AppWell(width) {
|
||||||
|
this._init(width);
|
||||||
|
}
|
||||||
|
|
||||||
|
AppWell.prototype = {
|
||||||
|
_init : function(width) {
|
||||||
|
this._menus = [];
|
||||||
|
this._menuDisplays = [];
|
||||||
|
|
||||||
|
this.actor = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
||||||
|
width: width });
|
||||||
|
|
||||||
|
this._appSystem = Shell.AppSystem.get_default();
|
||||||
|
this._appMonitor = Shell.AppMonitor.get_default();
|
||||||
|
|
||||||
|
this._appSystem.connect('installed-changed', Lang.bind(this, function(appSys) {
|
||||||
|
this._redisplay();
|
||||||
|
}));
|
||||||
|
this._appSystem.connect('favorites-changed', Lang.bind(this, function(appSys) {
|
||||||
|
this._redisplay();
|
||||||
|
}));
|
||||||
|
this._appMonitor.connect('changed', Lang.bind(this, function(monitor) {
|
||||||
|
this._redisplay();
|
||||||
|
}));
|
||||||
|
|
||||||
|
this._favoritesArea = new WellArea(width, true);
|
||||||
|
this._favoritesArea.connect('activated', Lang.bind(this, function (a, display) {
|
||||||
|
this.emit('activated');
|
||||||
|
}));
|
||||||
|
this.actor.append(this._favoritesArea.actor, Big.BoxPackFlags.NONE);
|
||||||
|
|
||||||
|
this._runningBox = new Big.Box({ border_color: GenericDisplay.ITEM_DISPLAY_NAME_COLOR,
|
||||||
|
border: 1,
|
||||||
|
corner_radius: 3,
|
||||||
|
padding: GenericDisplay.PREVIEW_BOX_PADDING });
|
||||||
|
this._runningArea = new WellArea(width, false);
|
||||||
|
this._runningArea.connect('activated', Lang.bind(this, function (a, display) {
|
||||||
|
this.emit('activated');
|
||||||
|
}));
|
||||||
|
this._runningBox.append(this._runningArea.actor, Big.BoxPackFlags.EXPAND);
|
||||||
|
this.actor.append(this._runningBox, Big.BoxPackFlags.NONE);
|
||||||
|
|
||||||
|
this._redisplay();
|
||||||
|
},
|
||||||
|
|
||||||
|
_redisplay: function() {
|
||||||
|
let arrayToObject = function(a) {
|
||||||
|
let o = {};
|
||||||
|
for (let i = 0; i < a.length; i++)
|
||||||
|
o[a[i]] = 1;
|
||||||
|
return o;
|
||||||
|
};
|
||||||
|
let favorites = AppInfo.getFavorites();
|
||||||
|
let favoriteIds = arrayToObject(favorites.map(function (e) { return e.appId; }));
|
||||||
|
let running = AppInfo.getRunning().filter(function (e) {
|
||||||
|
return !(e.appId in favoriteIds);
|
||||||
|
});
|
||||||
|
this._favoritesArea.redisplay(favorites);
|
||||||
|
this._runningArea.redisplay(running);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Signals.addSignalMethods(AppWell.prototype);
|
||||||
|
@ -27,8 +27,7 @@ DocDisplayItem.prototype = {
|
|||||||
GenericDisplay.GenericDisplayItem.prototype._init.call(this, availableWidth);
|
GenericDisplay.GenericDisplayItem.prototype._init.call(this, availableWidth);
|
||||||
this._docInfo = docInfo;
|
this._docInfo = docInfo;
|
||||||
|
|
||||||
this._setItemInfo(docInfo.name, "",
|
this._setItemInfo(docInfo.name, "");
|
||||||
docInfo.getIcon(GenericDisplay.ITEM_DISPLAY_ICON_SIZE));
|
|
||||||
},
|
},
|
||||||
|
|
||||||
//// Public methods ////
|
//// Public methods ////
|
||||||
@ -42,10 +41,15 @@ DocDisplayItem.prototype = {
|
|||||||
|
|
||||||
//// Protected method overrides ////
|
//// Protected method overrides ////
|
||||||
|
|
||||||
|
// Returns an icon for the item.
|
||||||
|
_createIcon : function() {
|
||||||
|
return this._docInfo.createIcon(GenericDisplay.ITEM_DISPLAY_ICON_SIZE);
|
||||||
|
},
|
||||||
|
|
||||||
// Ensures the preview icon is created.
|
// Ensures the preview icon is created.
|
||||||
_ensurePreviewIconCreated : function() {
|
_ensurePreviewIconCreated : function() {
|
||||||
if (!this._previewIcon)
|
if (!this._previewIcon)
|
||||||
this._previewIcon = this._docInfo.getIcon(GenericDisplay.PREVIEW_ICON_SIZE);
|
this._previewIcon = this._docInfo.createIcon(GenericDisplay.PREVIEW_ICON_SIZE);
|
||||||
},
|
},
|
||||||
|
|
||||||
// Creates and returns a large preview icon, but only if this._docInfo is an image file
|
// Creates and returns a large preview icon, but only if this._docInfo is an image file
|
||||||
|
@ -22,7 +22,7 @@ ITEM_DISPLAY_DESCRIPTION_COLOR.from_pixel(0xffffffbb);
|
|||||||
const ITEM_DISPLAY_BACKGROUND_COLOR = new Clutter.Color();
|
const ITEM_DISPLAY_BACKGROUND_COLOR = new Clutter.Color();
|
||||||
ITEM_DISPLAY_BACKGROUND_COLOR.from_pixel(0x00000000);
|
ITEM_DISPLAY_BACKGROUND_COLOR.from_pixel(0x00000000);
|
||||||
const ITEM_DISPLAY_SELECTED_BACKGROUND_COLOR = new Clutter.Color();
|
const ITEM_DISPLAY_SELECTED_BACKGROUND_COLOR = new Clutter.Color();
|
||||||
ITEM_DISPLAY_SELECTED_BACKGROUND_COLOR.from_pixel(0x00ff0055);
|
ITEM_DISPLAY_SELECTED_BACKGROUND_COLOR.from_pixel(0x4f6fadaa);
|
||||||
const DISPLAY_CONTROL_SELECTED_COLOR = new Clutter.Color();
|
const DISPLAY_CONTROL_SELECTED_COLOR = new Clutter.Color();
|
||||||
DISPLAY_CONTROL_SELECTED_COLOR.from_pixel(0x112288ff);
|
DISPLAY_CONTROL_SELECTED_COLOR.from_pixel(0x112288ff);
|
||||||
const PREVIEW_BOX_BACKGROUND_COLOR = new Clutter.Color();
|
const PREVIEW_BOX_BACKGROUND_COLOR = new Clutter.Color();
|
||||||
@ -30,7 +30,8 @@ PREVIEW_BOX_BACKGROUND_COLOR.from_pixel(0xADADADf0);
|
|||||||
|
|
||||||
const ITEM_DISPLAY_HEIGHT = 50;
|
const ITEM_DISPLAY_HEIGHT = 50;
|
||||||
const ITEM_DISPLAY_ICON_SIZE = 48;
|
const ITEM_DISPLAY_ICON_SIZE = 48;
|
||||||
const ITEM_DISPLAY_PADDING = 1;
|
const ITEM_DISPLAY_PADDING_TOP = 1;
|
||||||
|
const ITEM_DISPLAY_PADDING_RIGHT = 2;
|
||||||
const DEFAULT_COLUMN_GAP = 6;
|
const DEFAULT_COLUMN_GAP = 6;
|
||||||
const LABEL_HEIGHT = 16;
|
const LABEL_HEIGHT = 16;
|
||||||
|
|
||||||
@ -42,6 +43,8 @@ const PREVIEW_BOX_CORNER_RADIUS = 10;
|
|||||||
const PREVIEW_PLACING = 3/4;
|
const PREVIEW_PLACING = 3/4;
|
||||||
const PREVIEW_DETAILS_MIN_WIDTH = PREVIEW_ICON_SIZE * 2;
|
const PREVIEW_DETAILS_MIN_WIDTH = PREVIEW_ICON_SIZE * 2;
|
||||||
|
|
||||||
|
const INFORMATION_BUTTON_SIZE = 16;
|
||||||
|
|
||||||
/* This is a virtual class that represents a single display item containing
|
/* This is a virtual class that represents a single display item containing
|
||||||
* a name, a description, and an icon. It allows selecting an item and represents
|
* a name, a description, and an icon. It allows selecting an item and represents
|
||||||
* it by highlighting it with a different background color than the default.
|
* it by highlighting it with a different background color than the default.
|
||||||
@ -55,22 +58,17 @@ function GenericDisplayItem(availableWidth) {
|
|||||||
GenericDisplayItem.prototype = {
|
GenericDisplayItem.prototype = {
|
||||||
_init: function(availableWidth) {
|
_init: function(availableWidth) {
|
||||||
this._availableWidth = availableWidth;
|
this._availableWidth = availableWidth;
|
||||||
this._showPreview = false;
|
|
||||||
this._havePointer = false;
|
|
||||||
this._previewEventSourceId = null;
|
|
||||||
|
|
||||||
this.actor = new Clutter.Group({ reactive: true,
|
this.actor = new Clutter.Group({ reactive: true,
|
||||||
width: availableWidth,
|
width: availableWidth,
|
||||||
height: ITEM_DISPLAY_HEIGHT });
|
height: ITEM_DISPLAY_HEIGHT });
|
||||||
this.actor._delegate = this;
|
this.actor._delegate = this;
|
||||||
this.actor.connect('button-press-event',
|
this.actor.connect('button-release-event',
|
||||||
Lang.bind(this,
|
Lang.bind(this,
|
||||||
function(actor, e) {
|
function() {
|
||||||
let clickCount = Shell.get_button_event_click_count(e);
|
// Activates the item by launching it
|
||||||
if (clickCount == 1)
|
this.emit('activate');
|
||||||
this.select();
|
return true;
|
||||||
else if (clickCount == 2)
|
|
||||||
this.activate();
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let draggable = DND.makeDraggable(this.actor);
|
let draggable = DND.makeDraggable(this.actor);
|
||||||
@ -81,11 +79,40 @@ GenericDisplayItem.prototype = {
|
|||||||
x: 0, y: 0,
|
x: 0, y: 0,
|
||||||
width: availableWidth, height: ITEM_DISPLAY_HEIGHT });
|
width: availableWidth, height: ITEM_DISPLAY_HEIGHT });
|
||||||
this.actor.add_actor(this._bg);
|
this.actor.add_actor(this._bg);
|
||||||
|
|
||||||
|
let global = Shell.Global.get();
|
||||||
|
let infoIconUri = "file://" + global.imagedir + "info.svg";
|
||||||
|
|
||||||
|
this._informationButton = Shell.TextureCache.get_default().load_uri_sync(infoIconUri,
|
||||||
|
INFORMATION_BUTTON_SIZE,
|
||||||
|
INFORMATION_BUTTON_SIZE);
|
||||||
|
|
||||||
|
this._informationButton.x = availableWidth - ITEM_DISPLAY_PADDING_RIGHT - INFORMATION_BUTTON_SIZE;
|
||||||
|
this._informationButton.y = ITEM_DISPLAY_HEIGHT / 2 - INFORMATION_BUTTON_SIZE / 2;
|
||||||
|
this._informationButton.reactive = true;
|
||||||
|
|
||||||
|
// Connecting to the button-press-event for the information button ensures that the actor,
|
||||||
|
// which is a draggable actor, does not get the button-press-event and doesn't initiate
|
||||||
|
// the dragging, which then prevents us from getting the button-release-event for the button.
|
||||||
|
this._informationButton.connect('button-press-event',
|
||||||
|
Lang.bind(this,
|
||||||
|
function() {
|
||||||
|
return true;
|
||||||
|
}));
|
||||||
|
this._informationButton.connect('button-release-event',
|
||||||
|
Lang.bind(this,
|
||||||
|
function() {
|
||||||
|
// Selects the item by highlighting it and displaying its details
|
||||||
|
this.emit('select');
|
||||||
|
return true;
|
||||||
|
}));
|
||||||
|
this._informationButton.hide();
|
||||||
|
this.actor.add_actor(this._informationButton);
|
||||||
|
this._informationButton.lower_bottom();
|
||||||
|
|
||||||
this._name = null;
|
this._name = null;
|
||||||
this._description = null;
|
this._description = null;
|
||||||
this._icon = null;
|
this._icon = null;
|
||||||
this._preview = null;
|
|
||||||
this._previewIcon = null;
|
this._previewIcon = null;
|
||||||
|
|
||||||
this.dragActor = null;
|
this.dragActor = null;
|
||||||
@ -99,8 +126,7 @@ GenericDisplayItem.prototype = {
|
|||||||
// Returns a cloned texture of the item's icon to represent the item as it
|
// Returns a cloned texture of the item's icon to represent the item as it
|
||||||
// is being dragged.
|
// is being dragged.
|
||||||
getDragActor: function(stageX, stageY) {
|
getDragActor: function(stageX, stageY) {
|
||||||
this.dragActor = new Clutter.Clone({ source: this._icon });
|
this.dragActor = this._createIcon();
|
||||||
[this.dragActor.width, this.dragActor.height] = this._icon.get_transformed_size();
|
|
||||||
|
|
||||||
// If the user dragged from the icon itself, then position
|
// If the user dragged from the icon itself, then position
|
||||||
// the dragActor over the original icon. Otherwise center it
|
// the dragActor over the original icon. Otherwise center it
|
||||||
@ -115,58 +141,19 @@ GenericDisplayItem.prototype = {
|
|||||||
return this.dragActor;
|
return this.dragActor;
|
||||||
},
|
},
|
||||||
|
|
||||||
// Returns the original icon that is being used as a source for the cloned texture
|
// Returns the item icon, a separate copy of which is used to
|
||||||
// that represents the item as it is being dragged.
|
// represent the item as it is being dragged. This is used to
|
||||||
|
// determine a snap-back location for the drag icon if it does
|
||||||
|
// not get accepted by any drop target.
|
||||||
getDragActorSource: function() {
|
getDragActorSource: function() {
|
||||||
return this._icon;
|
return this._icon;
|
||||||
},
|
},
|
||||||
|
|
||||||
//// Public methods ////
|
//// Public methods ////
|
||||||
|
|
||||||
// Sets a boolean value that indicates whether the item should display a pop-up preview on mouse over.
|
// Shows the information button when the item was drawn under the mouse pointer.
|
||||||
setShowPreview: function(showPreview) {
|
|
||||||
this._showPreview = showPreview;
|
|
||||||
},
|
|
||||||
|
|
||||||
// Returns a boolean value that indicates whether the item displays a pop-up preview on mouse over.
|
|
||||||
getShowPreview: function() {
|
|
||||||
return this._showPreview;
|
|
||||||
},
|
|
||||||
|
|
||||||
// Displays the preview for the item.
|
|
||||||
showPreview: function() {
|
|
||||||
if(!this._showPreview)
|
|
||||||
return;
|
|
||||||
|
|
||||||
this._ensurePreviewCreated();
|
|
||||||
|
|
||||||
let [x, y] = this.actor.get_transformed_position();
|
|
||||||
let global = Shell.Global.get();
|
|
||||||
let previewX = Math.min(x + this._availableWidth * PREVIEW_PLACING, global.screen_width - this._preview.width);
|
|
||||||
let previewY = Math.min(y, global.screen_height - this._preview.height);
|
|
||||||
this._preview.set_position(previewX, previewY);
|
|
||||||
|
|
||||||
this._preview.show();
|
|
||||||
},
|
|
||||||
|
|
||||||
// Hides the preview for the item and removes the preview event source so that
|
|
||||||
// there is no preview scheduled to show up.
|
|
||||||
hidePreview: function() {
|
|
||||||
if (this._previewEventSourceId) {
|
|
||||||
Mainloop.source_remove(this._previewEventSourceId);
|
|
||||||
this._previewEventSourceId = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._preview)
|
|
||||||
this._preview.hide();
|
|
||||||
},
|
|
||||||
|
|
||||||
// Shows a preview when the item was drawn under the mouse pointer.
|
|
||||||
onDrawnUnderPointer: function() {
|
onDrawnUnderPointer: function() {
|
||||||
this._havePointer = true;
|
this._informationButton.show();
|
||||||
// This code is usually triggered when we just had a different preview showing on the same spot
|
|
||||||
// and having a delay before showing a new preview looks bad. So we just show it right away.
|
|
||||||
this.showPreview();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Highlights the item by setting a different background color than the default
|
// Highlights the item by setting a different background color than the default
|
||||||
@ -180,17 +167,6 @@ GenericDisplayItem.prototype = {
|
|||||||
this._bg.background_color = color;
|
this._bg.background_color = color;
|
||||||
},
|
},
|
||||||
|
|
||||||
// Activates the item, as though it was launched
|
|
||||||
activate: function() {
|
|
||||||
this.hidePreview();
|
|
||||||
this.emit('activate');
|
|
||||||
},
|
|
||||||
|
|
||||||
// Selects the item, as though it was clicked
|
|
||||||
select: function() {
|
|
||||||
this.emit('select');
|
|
||||||
},
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns an actor containing item details. In the future details can have more information than what
|
* Returns an actor containing item details. In the future details can have more information than what
|
||||||
* the preview pop-up has and be item-type specific.
|
* the preview pop-up has and be item-type specific.
|
||||||
@ -199,7 +175,7 @@ GenericDisplayItem.prototype = {
|
|||||||
* availableHeight - height available for displaying details
|
* availableHeight - height available for displaying details
|
||||||
*/
|
*/
|
||||||
createDetailsActor: function(availableWidth, availableHeight) {
|
createDetailsActor: function(availableWidth, availableHeight) {
|
||||||
|
|
||||||
let details = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
let details = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
||||||
spacing: PREVIEW_BOX_SPACING,
|
spacing: PREVIEW_BOX_SPACING,
|
||||||
width: availableWidth });
|
width: availableWidth });
|
||||||
@ -241,28 +217,12 @@ GenericDisplayItem.prototype = {
|
|||||||
details.append(largePreview, Big.BoxPackFlags.NONE);
|
details.append(largePreview, Big.BoxPackFlags.NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We hide the preview pop-up if the details are shown elsewhere.
|
|
||||||
details.connect("show",
|
|
||||||
Lang.bind(this,
|
|
||||||
function() {
|
|
||||||
// Right now "show" signal is emitted when an actor is added to a parent that
|
|
||||||
// has not been added to anything and "visible" property is also set to true
|
|
||||||
// at this point, so checking if the parent that the actor has been added to
|
|
||||||
// has a parent of its own is a temporary workaround. That other actor is
|
|
||||||
// presumed to be displayed, which is a limitation of this workaround, but is
|
|
||||||
// the case with our usage of the details actor now.
|
|
||||||
// http://bugzilla.openedhand.com/show_bug.cgi?id=1138
|
|
||||||
if (details.get_parent() != null && details.get_parent().get_parent() != null)
|
|
||||||
this.hidePreview();
|
|
||||||
}));
|
|
||||||
return details;
|
return details;
|
||||||
},
|
},
|
||||||
|
|
||||||
// Destoys the item, as well as a preview for the item if it exists.
|
// Destoys the item.
|
||||||
destroy: function() {
|
destroy: function() {
|
||||||
this.actor.destroy();
|
this.actor.destroy();
|
||||||
if (this._preview != null)
|
|
||||||
this._preview.destroy();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
//// Pure virtual public methods ////
|
//// Pure virtual public methods ////
|
||||||
@ -279,9 +239,8 @@ GenericDisplayItem.prototype = {
|
|||||||
*
|
*
|
||||||
* nameText - name of the item
|
* nameText - name of the item
|
||||||
* descriptionText - short description of the item
|
* descriptionText - short description of the item
|
||||||
* iconActor - ClutterTexture containing the icon image which should be ITEM_DISPLAY_ICON_SIZE size
|
|
||||||
*/
|
*/
|
||||||
_setItemInfo: function(nameText, descriptionText, iconActor) {
|
_setItemInfo: function(nameText, descriptionText) {
|
||||||
if (this._name != null) {
|
if (this._name != null) {
|
||||||
// this also removes this._name from the parent container,
|
// this also removes this._name from the parent container,
|
||||||
// so we don't need to call this.actor.remove_actor(this._name) directly
|
// so we don't need to call this.actor.remove_actor(this._name) directly
|
||||||
@ -298,27 +257,23 @@ GenericDisplayItem.prototype = {
|
|||||||
this._icon.destroy();
|
this._icon.destroy();
|
||||||
this._icon = null;
|
this._icon = null;
|
||||||
}
|
}
|
||||||
// This ensures we'll create a new preview and previewIcon next time we need a preview
|
// This ensures we'll create a new previewIcon next time we need it
|
||||||
if (this._preview != null) {
|
|
||||||
this._preview.destroy();
|
|
||||||
this._preview = null;
|
|
||||||
}
|
|
||||||
if (this._previewIcon != null) {
|
if (this._previewIcon != null) {
|
||||||
this._previewIcon.destroy();
|
this._previewIcon.destroy();
|
||||||
this._previewIcon = null;
|
this._previewIcon = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._icon = iconActor;
|
this._icon = this._createIcon();
|
||||||
this.actor.add_actor(this._icon);
|
this.actor.add_actor(this._icon);
|
||||||
|
|
||||||
let textWidth = this._availableWidth - (ITEM_DISPLAY_ICON_SIZE + 4);
|
let textWidth = this._availableWidth - (ITEM_DISPLAY_ICON_SIZE + 4) - INFORMATION_BUTTON_SIZE - ITEM_DISPLAY_PADDING_RIGHT;
|
||||||
this._name = new Clutter.Text({ color: ITEM_DISPLAY_NAME_COLOR,
|
this._name = new Clutter.Text({ color: ITEM_DISPLAY_NAME_COLOR,
|
||||||
font_name: "Sans 14px",
|
font_name: "Sans 14px",
|
||||||
width: textWidth,
|
width: textWidth,
|
||||||
ellipsize: Pango.EllipsizeMode.END,
|
ellipsize: Pango.EllipsizeMode.END,
|
||||||
text: nameText,
|
text: nameText,
|
||||||
x: ITEM_DISPLAY_ICON_SIZE + 4,
|
x: ITEM_DISPLAY_ICON_SIZE + 4,
|
||||||
y: ITEM_DISPLAY_PADDING });
|
y: ITEM_DISPLAY_PADDING_TOP });
|
||||||
this.actor.add_actor(this._name);
|
this.actor.add_actor(this._name);
|
||||||
this._description = new Clutter.Text({ color: ITEM_DISPLAY_DESCRIPTION_COLOR,
|
this._description = new Clutter.Text({ color: ITEM_DISPLAY_DESCRIPTION_COLOR,
|
||||||
font_name: "Sans 12px",
|
font_name: "Sans 12px",
|
||||||
@ -339,6 +294,11 @@ GenericDisplayItem.prototype = {
|
|||||||
|
|
||||||
//// Pure virtual protected methods ////
|
//// Pure virtual protected methods ////
|
||||||
|
|
||||||
|
// Returns an icon for the item.
|
||||||
|
_createIcon: function() {
|
||||||
|
throw new Error("Not implemented");
|
||||||
|
},
|
||||||
|
|
||||||
// Ensures the preview icon is created.
|
// Ensures the preview icon is created.
|
||||||
_ensurePreviewIconCreated: function() {
|
_ensurePreviewIconCreated: function() {
|
||||||
throw new Error("Not implemented");
|
throw new Error("Not implemented");
|
||||||
@ -346,79 +306,21 @@ GenericDisplayItem.prototype = {
|
|||||||
|
|
||||||
//// Private methods ////
|
//// Private methods ////
|
||||||
|
|
||||||
// Ensures the preview actor is created.
|
// Performs actions on mouse enter event for the item. Currently, shows the information button for the item.
|
||||||
_ensurePreviewCreated: function() {
|
|
||||||
if (!this._showPreview || this._preview)
|
|
||||||
return;
|
|
||||||
|
|
||||||
this._preview = new Big.Box({ background_color: PREVIEW_BOX_BACKGROUND_COLOR,
|
|
||||||
orientation: Big.BoxOrientation.HORIZONTAL,
|
|
||||||
corner_radius: PREVIEW_BOX_CORNER_RADIUS,
|
|
||||||
padding: PREVIEW_BOX_PADDING,
|
|
||||||
spacing: PREVIEW_BOX_SPACING });
|
|
||||||
|
|
||||||
let textDetailsWidth = this._availableWidth - PREVIEW_BOX_PADDING * 2;
|
|
||||||
|
|
||||||
this._ensurePreviewIconCreated();
|
|
||||||
|
|
||||||
if (this._previewIcon != null) {
|
|
||||||
this._preview.append(this._previewIcon, Big.BoxPackFlags.EXPAND);
|
|
||||||
textDetailsWidth = this._availableWidth - this._previewIcon.width - PREVIEW_BOX_PADDING * 2 - PREVIEW_BOX_SPACING;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Inner box with name and description
|
|
||||||
let textDetails = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
|
||||||
spacing: PREVIEW_BOX_SPACING });
|
|
||||||
let detailsName = new Clutter.Text({ color: ITEM_DISPLAY_NAME_COLOR,
|
|
||||||
font_name: "Sans bold 14px",
|
|
||||||
text: this._name.text});
|
|
||||||
|
|
||||||
textDetails.width = Math.max(PREVIEW_DETAILS_MIN_WIDTH, textDetailsWidth, detailsName.width);
|
|
||||||
|
|
||||||
textDetails.append(detailsName, Big.BoxPackFlags.NONE);
|
|
||||||
|
|
||||||
let detailsDescription = new Clutter.Text({ color: ITEM_DISPLAY_NAME_COLOR,
|
|
||||||
font_name: "Sans 14px",
|
|
||||||
line_wrap: true,
|
|
||||||
text: this._description.text });
|
|
||||||
textDetails.append(detailsDescription, Big.BoxPackFlags.NONE);
|
|
||||||
|
|
||||||
this._preview.append(textDetails, Big.BoxPackFlags.EXPAND);
|
|
||||||
|
|
||||||
// Add the preview to global stage to allow for top-level layering
|
|
||||||
let global = Shell.Global.get();
|
|
||||||
global.stage.add_actor(this._preview);
|
|
||||||
this._preview.hide();
|
|
||||||
},
|
|
||||||
|
|
||||||
// Performs actions on mouse enter event for the item. Currently, shows the preview for the item.
|
|
||||||
_onEnter: function(actor, event) {
|
_onEnter: function(actor, event) {
|
||||||
this._havePointer = true;
|
this._informationButton.show();
|
||||||
let tooltipTimeout = Gtk.Settings.get_default().gtk_tooltip_timeout;
|
|
||||||
this._previewEventSourceId = Mainloop.timeout_add(tooltipTimeout,
|
|
||||||
Lang.bind(this,
|
|
||||||
function() {
|
|
||||||
if (this._havePointer) {
|
|
||||||
this.showPreview();
|
|
||||||
}
|
|
||||||
this._previewEventSourceId = null;
|
|
||||||
return false;
|
|
||||||
}));
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Performs actions on mouse leave event for the item. Currently, hides the preview for the item.
|
// Performs actions on mouse leave event for the item. Currently, hides the information button for the item.
|
||||||
_onLeave: function(actor, event) {
|
_onLeave: function(actor, event) {
|
||||||
this._havePointer = false;
|
this._informationButton.hide();
|
||||||
this.hidePreview();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Hides the preview once the item starts being dragged.
|
// Hides the information button once the item starts being dragged.
|
||||||
_onDragBegin : function (draggable, time) {
|
_onDragBegin : function (draggable, time) {
|
||||||
// For some reason, we are not getting leave-event signal when we are dragging an item,
|
// For some reason, we are not getting leave-event signal when we are dragging an item,
|
||||||
// so the preview box stays behind if we didn't have the call here. It makes sense to hide
|
// so we should remove the link manually.
|
||||||
// the preview as soon as the item starts being dragged anyway.
|
this._informationButton.hide();
|
||||||
this._havePointer = false;
|
|
||||||
this.hidePreview();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -469,8 +371,6 @@ GenericDisplay.prototype = {
|
|||||||
// See also getSideArea.
|
// See also getSideArea.
|
||||||
this.actor = this._grid;
|
this.actor = this._grid;
|
||||||
this.displayControl = new Big.Box({ background_color: ITEM_DISPLAY_BACKGROUND_COLOR,
|
this.displayControl = new Big.Box({ background_color: ITEM_DISPLAY_BACKGROUND_COLOR,
|
||||||
corner_radius: 4,
|
|
||||||
height: 24,
|
|
||||||
spacing: 12,
|
spacing: 12,
|
||||||
orientation: Big.BoxOrientation.HORIZONTAL});
|
orientation: Big.BoxOrientation.HORIZONTAL});
|
||||||
|
|
||||||
@ -557,14 +457,6 @@ GenericDisplay.prototype = {
|
|||||||
this._selectIndex(-1);
|
this._selectIndex(-1);
|
||||||
},
|
},
|
||||||
|
|
||||||
// Hides the preview if any item has one being displayed.
|
|
||||||
hidePreview: function() {
|
|
||||||
for (itemId in this._displayedItems) {
|
|
||||||
let item = this._displayedItems[itemId];
|
|
||||||
item.hidePreview();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// Returns true if the display has any displayed items.
|
// Returns true if the display has any displayed items.
|
||||||
hasItems: function() {
|
hasItems: function() {
|
||||||
return this._displayedItemsCount > 0;
|
return this._displayedItemsCount > 0;
|
||||||
@ -645,13 +537,13 @@ GenericDisplay.prototype = {
|
|||||||
Mainloop.timeout_add(5,
|
Mainloop.timeout_add(5,
|
||||||
Lang.bind(this,
|
Lang.bind(this,
|
||||||
function() {
|
function() {
|
||||||
// Check if the pointer is over one of the items and display the preview pop-up if it is.
|
// Check if the pointer is over one of the items and display the information button if it is.
|
||||||
let [child, x, y, mask] = Gdk.Screen.get_default().get_root_window().get_pointer();
|
let [child, x, y, mask] = Gdk.Screen.get_default().get_root_window().get_pointer();
|
||||||
let global = Shell.Global.get();
|
let global = Shell.Global.get();
|
||||||
let actor = global.stage.get_actor_at_pos(Clutter.PickMode.REACTIVE,
|
let actor = global.stage.get_actor_at_pos(Clutter.PickMode.REACTIVE,
|
||||||
x, y);
|
x, y);
|
||||||
if (actor != null) {
|
if (actor != null) {
|
||||||
let item = this._findDisplayedByActor(actor.get_parent());
|
let item = this._findDisplayedByActor(actor);
|
||||||
if (item != null) {
|
if (item != null) {
|
||||||
item.onDrawnUnderPointer();
|
item.onDrawnUnderPointer();
|
||||||
}
|
}
|
||||||
@ -670,7 +562,6 @@ GenericDisplay.prototype = {
|
|||||||
|
|
||||||
let itemInfo = this._allItems[itemId];
|
let itemInfo = this._allItems[itemId];
|
||||||
let displayItem = this._createDisplayItem(itemInfo);
|
let displayItem = this._createDisplayItem(itemInfo);
|
||||||
displayItem.setShowPreview(true);
|
|
||||||
|
|
||||||
displayItem.connect('activate',
|
displayItem.connect('activate',
|
||||||
Lang.bind(this,
|
Lang.bind(this,
|
||||||
@ -702,32 +593,8 @@ GenericDisplay.prototype = {
|
|||||||
this.selectUp();
|
this.selectUp();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (displayItem.dragActor) {
|
displayItem.destroy();
|
||||||
// The user might be handling a dragActor when the list of items
|
|
||||||
// changes (for example, if the dragging caused us to transition
|
|
||||||
// from an expanded overlay view to the regular view). So we need
|
|
||||||
// to keep the item around so that the drag and drop action initiated
|
|
||||||
// by the user can be completed. However, we remove the item from the list.
|
|
||||||
//
|
|
||||||
// For some reason, just removing the displayItem.actor
|
|
||||||
// is not enough to get displayItem._icon.visible
|
|
||||||
// to return false, so we hide the display item and
|
|
||||||
// all its children first. (We check displayItem._icon.visible
|
|
||||||
// when deciding if a dragActor has a place to snap back to
|
|
||||||
// in case the drop was not accepted by any actor.)
|
|
||||||
displayItem.actor.hide_all();
|
|
||||||
this._grid.remove_actor(displayItem.actor);
|
|
||||||
// We should not destroy the item up-front, because that would also
|
|
||||||
// destroy the icon that was used to clone the image for the drag actor.
|
|
||||||
// We destroy it once the dragActor is destroyed instead.
|
|
||||||
displayItem.dragActor.connect('destroy',
|
|
||||||
function(item) {
|
|
||||||
displayItem.destroy();
|
|
||||||
});
|
|
||||||
|
|
||||||
} else {
|
|
||||||
displayItem.destroy();
|
|
||||||
}
|
|
||||||
delete this._displayedItems[itemId];
|
delete this._displayedItems[itemId];
|
||||||
this._displayedItemsCount--;
|
this._displayedItemsCount--;
|
||||||
},
|
},
|
||||||
|
889
js/ui/overlay.js
889
js/ui/overlay.js
File diff suppressed because it is too large
Load Diff
@ -182,7 +182,7 @@ LauncherWidget.prototype = {
|
|||||||
spacing: ITEM_SPACING,
|
spacing: ITEM_SPACING,
|
||||||
reactive: true });
|
reactive: true });
|
||||||
item._info = info;
|
item._info = info;
|
||||||
item.append(info.getIcon(ITEM_ICON_SIZE), Big.BoxPackFlags.NONE);
|
item.append(info.createIcon(ITEM_ICON_SIZE), Big.BoxPackFlags.NONE);
|
||||||
item.append(new Clutter.Text({ color: ITEM_NAME_COLOR,
|
item.append(new Clutter.Text({ color: ITEM_NAME_COLOR,
|
||||||
font_name: "Sans 14px",
|
font_name: "Sans 14px",
|
||||||
ellipsize: Pango.EllipsizeMode.END,
|
ellipsize: Pango.EllipsizeMode.END,
|
||||||
@ -203,7 +203,7 @@ LauncherWidget.prototype = {
|
|||||||
padding: ITEM_PADDING,
|
padding: ITEM_PADDING,
|
||||||
reactive: true });
|
reactive: true });
|
||||||
item._info = info;
|
item._info = info;
|
||||||
item.append(info.getIcon(COLLAPSED_WIDTH - 2 * ITEM_PADDING),
|
item.append(info.createIcon(COLLAPSED_WIDTH - 2 * ITEM_PADDING),
|
||||||
Big.BoxPackFlags.NONE);
|
Big.BoxPackFlags.NONE);
|
||||||
|
|
||||||
this.collapsedActor.append(item, Big.BoxPackFlags.NONE);
|
this.collapsedActor.append(item, Big.BoxPackFlags.NONE);
|
||||||
@ -284,7 +284,7 @@ AppsWidget.prototype = {
|
|||||||
this.actor = new Big.Box({ spacing: 2 });
|
this.actor = new Big.Box({ spacing: 2 });
|
||||||
this.collapsedActor = new Big.Box({ spacing: 2});
|
this.collapsedActor = new Big.Box({ spacing: 2});
|
||||||
|
|
||||||
let apps = AppInfo.getMostUsedApps(5);
|
let apps = AppInfo.getTopApps(5);
|
||||||
for (let i = 0; i < apps.length; i++)
|
for (let i = 0; i < apps.length; i++)
|
||||||
this.addItem(apps[i]);
|
this.addItem(apps[i]);
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ const Pango = imports.gi.Pango;
|
|||||||
const Shell = imports.gi.Shell;
|
const Shell = imports.gi.Shell;
|
||||||
const Signals = imports.signals;
|
const Signals = imports.signals;
|
||||||
|
|
||||||
|
const AppDisplay = imports.ui.appDisplay;
|
||||||
const DND = imports.ui.dnd;
|
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;
|
||||||
@ -752,7 +753,7 @@ Workspace.prototype = {
|
|||||||
false, // don't create workspace
|
false, // don't create workspace
|
||||||
time);
|
time);
|
||||||
return true;
|
return true;
|
||||||
} else if (source instanceof GenericDisplay.GenericDisplayItem) {
|
} else if (source instanceof GenericDisplay.GenericDisplayItem || source instanceof AppDisplay.WellDisplayItem) {
|
||||||
this._metaWorkspace.activate(time);
|
this._metaWorkspace.activate(time);
|
||||||
source.launch();
|
source.launch();
|
||||||
return true;
|
return true;
|
||||||
|
@ -13,9 +13,11 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "shell-app-monitor.h"
|
#include "shell-app-monitor.h"
|
||||||
|
#include "shell-app-system.h"
|
||||||
#include "shell-global.h"
|
#include "shell-global.h"
|
||||||
|
|
||||||
#include "display.h"
|
#include "display.h"
|
||||||
|
#include "window.h"
|
||||||
|
|
||||||
/* This file includes modified code from
|
/* This file includes modified code from
|
||||||
* desktop-data-engine/engine-dbus/hippo-application-monitor.c
|
* desktop-data-engine/engine-dbus/hippo-application-monitor.c
|
||||||
@ -63,6 +65,7 @@ static struct
|
|||||||
const char *pattern;
|
const char *pattern;
|
||||||
GRegex *regex;
|
GRegex *regex;
|
||||||
} title_patterns[] = {
|
} title_patterns[] = {
|
||||||
|
{"mozilla-firefox", ".* - Mozilla Firefox", NULL}, \
|
||||||
{"openoffice.org-writer", ".* - OpenOffice.org Writer$", NULL}, \
|
{"openoffice.org-writer", ".* - OpenOffice.org Writer$", NULL}, \
|
||||||
{"openoffice.org-calc", ".* - OpenOffice.org Calc$", NULL}, \
|
{"openoffice.org-calc", ".* - OpenOffice.org Calc$", NULL}, \
|
||||||
{"openoffice.org-impress", ".* - OpenOffice.org Impress$", NULL}, \
|
{"openoffice.org-impress", ".* - OpenOffice.org Impress$", NULL}, \
|
||||||
@ -93,6 +96,12 @@ struct _ShellAppMonitor
|
|||||||
gboolean currently_idle;
|
gboolean currently_idle;
|
||||||
gboolean enable_monitoring;
|
gboolean enable_monitoring;
|
||||||
|
|
||||||
|
/* <char * appid, guint window_count> */
|
||||||
|
GHashTable *running_appids;
|
||||||
|
|
||||||
|
/* <MetaWindow * window, char * appid> */
|
||||||
|
GHashTable *window_to_appid;
|
||||||
|
|
||||||
GHashTable *apps_by_wm_class; /* Seen apps by wm_class */
|
GHashTable *apps_by_wm_class; /* Seen apps by wm_class */
|
||||||
GHashTable *popularities; /* One AppPopularity struct list per activity */
|
GHashTable *popularities; /* One AppPopularity struct list per activity */
|
||||||
int upload_apps_burst_count;
|
int upload_apps_burst_count;
|
||||||
@ -191,6 +200,232 @@ destroy_popularity (gpointer key,
|
|||||||
g_slist_free (list);
|
g_slist_free (list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
get_wmclass_for_window (MetaWindow *window)
|
||||||
|
{
|
||||||
|
static gboolean patterns_initialized = FALSE;
|
||||||
|
const char *wm_class;
|
||||||
|
char *title;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
wm_class = meta_window_get_wm_class (window);
|
||||||
|
g_object_get (window, "title", &title, NULL);
|
||||||
|
|
||||||
|
if (!patterns_initialized) /* Generate match patterns once for all */
|
||||||
|
{
|
||||||
|
patterns_initialized = TRUE;
|
||||||
|
for (i = 0; title_patterns[i].app_id; i++)
|
||||||
|
{
|
||||||
|
title_patterns[i].regex = g_regex_new (title_patterns[i].pattern,
|
||||||
|
0, 0, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Match window title patterns to identifiers for non-standard apps */
|
||||||
|
if (title)
|
||||||
|
{
|
||||||
|
for (i = 0; title_patterns[i].app_id; i++)
|
||||||
|
{
|
||||||
|
if (g_regex_match (title_patterns[i].regex, title, 0, NULL))
|
||||||
|
{
|
||||||
|
/* Set a pseudo WM class, handled like true ones */
|
||||||
|
wm_class = title_patterns[i].app_id;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (title);
|
||||||
|
return g_strdup (wm_class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get_cleaned_wmclass_for_window:
|
||||||
|
*
|
||||||
|
* A "cleaned" wmclass is the WM_CLASS property of a window,
|
||||||
|
* after some transformations to turn it into a form
|
||||||
|
* somewhat more resilient to changes, such as lowercasing.
|
||||||
|
*/
|
||||||
|
static char *
|
||||||
|
get_cleaned_wmclass_for_window (MetaWindow *window)
|
||||||
|
{
|
||||||
|
char *wmclass;
|
||||||
|
char *cleaned_wmclass;
|
||||||
|
|
||||||
|
if (meta_window_get_window_type (window) != META_WINDOW_NORMAL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
wmclass = get_wmclass_for_window (window);
|
||||||
|
if (!wmclass)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
cleaned_wmclass = g_utf8_strdown (wmclass, -1);
|
||||||
|
g_free (wmclass);
|
||||||
|
/* This handles "Fedora Eclipse", probably others */
|
||||||
|
g_strdelimit (cleaned_wmclass, " ", '-');
|
||||||
|
wmclass = g_strdup (cleaned_wmclass);
|
||||||
|
g_free (cleaned_wmclass);
|
||||||
|
return wmclass;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get_appid_for_window:
|
||||||
|
*
|
||||||
|
* Returns a desktop file ID for an application, or %NULL if
|
||||||
|
* we're unable to determine one.
|
||||||
|
*/
|
||||||
|
static char *
|
||||||
|
get_appid_for_window (MetaWindow *window)
|
||||||
|
{
|
||||||
|
char *wmclass;
|
||||||
|
char *with_desktop;
|
||||||
|
char *result;
|
||||||
|
ShellAppSystem *appsys;
|
||||||
|
|
||||||
|
wmclass = get_cleaned_wmclass_for_window (window);
|
||||||
|
|
||||||
|
if (!wmclass)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
with_desktop = g_strjoin (NULL, wmclass, ".desktop", NULL);
|
||||||
|
g_free (wmclass);
|
||||||
|
|
||||||
|
appsys = shell_app_system_get_default ();
|
||||||
|
result = shell_app_system_lookup_basename (appsys, with_desktop);
|
||||||
|
g_free (with_desktop);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
track_window (ShellAppMonitor *self,
|
||||||
|
MetaWindow *window)
|
||||||
|
{
|
||||||
|
char *appid;
|
||||||
|
guint window_count;
|
||||||
|
|
||||||
|
appid = get_appid_for_window (window);
|
||||||
|
if (!appid)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_hash_table_insert (self->window_to_appid, window, appid);
|
||||||
|
|
||||||
|
window_count = GPOINTER_TO_UINT (g_hash_table_lookup (self->running_appids, appid));
|
||||||
|
|
||||||
|
window_count += 1;
|
||||||
|
g_hash_table_insert (self->running_appids, g_strdup (appid), GUINT_TO_POINTER (window_count));
|
||||||
|
if (window_count == 1)
|
||||||
|
g_signal_emit (self, signals[CHANGED], 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
shell_app_monitor_on_window_added (MetaWorkspace *workspace,
|
||||||
|
MetaWindow *window,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
ShellAppMonitor *self = SHELL_APP_MONITOR (user_data);
|
||||||
|
|
||||||
|
track_window (self, window);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
shell_app_monitor_on_window_removed (MetaWorkspace *workspace,
|
||||||
|
MetaWindow *window,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
ShellAppMonitor *self = SHELL_APP_MONITOR (user_data);
|
||||||
|
char *appid;
|
||||||
|
guint window_count;
|
||||||
|
|
||||||
|
appid = g_hash_table_lookup (self->window_to_appid, window);
|
||||||
|
if (!appid)
|
||||||
|
return;
|
||||||
|
|
||||||
|
window_count = GPOINTER_TO_UINT (g_hash_table_lookup (self->running_appids, appid));
|
||||||
|
|
||||||
|
window_count -= 1;
|
||||||
|
if (window_count == 0)
|
||||||
|
{
|
||||||
|
g_hash_table_remove (self->running_appids, appid);
|
||||||
|
g_free (appid);
|
||||||
|
g_signal_emit (self, signals[CHANGED], 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_hash_table_insert (self->running_appids, appid, GUINT_TO_POINTER (window_count));
|
||||||
|
}
|
||||||
|
g_hash_table_remove (self->window_to_appid, window);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
load_initial_windows (ShellAppMonitor *monitor)
|
||||||
|
{
|
||||||
|
GList *workspaces, *iter;
|
||||||
|
MetaScreen *screen = shell_global_get_screen (shell_global_get ());
|
||||||
|
workspaces = meta_screen_get_workspaces (screen);
|
||||||
|
|
||||||
|
for (iter = workspaces; iter; iter = iter->next)
|
||||||
|
{
|
||||||
|
MetaWorkspace *workspace = iter->data;
|
||||||
|
GList *windows = meta_workspace_list_windows (workspace);
|
||||||
|
GList *window_iter;
|
||||||
|
|
||||||
|
for (window_iter = windows; window_iter; window_iter = window_iter->next)
|
||||||
|
track_window (monitor, (MetaWindow*)window_iter->data);
|
||||||
|
|
||||||
|
g_list_free (windows);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
guint
|
||||||
|
shell_app_monitor_get_window_count (ShellAppMonitor *self,
|
||||||
|
const char *appid)
|
||||||
|
{
|
||||||
|
return GPOINTER_TO_UINT (g_hash_table_lookup (self->running_appids, appid));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
shell_app_monitor_on_n_workspaces_changed (MetaScreen *screen,
|
||||||
|
GParamSpec *pspec,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
ShellAppMonitor *self = SHELL_APP_MONITOR (user_data);
|
||||||
|
GList *workspaces, *iter;
|
||||||
|
|
||||||
|
workspaces = meta_screen_get_workspaces (screen);
|
||||||
|
|
||||||
|
for (iter = workspaces; iter; iter = iter->next)
|
||||||
|
{
|
||||||
|
MetaWorkspace *workspace = iter->data;
|
||||||
|
|
||||||
|
/* This pair of disconnect/connect is idempotent if we were
|
||||||
|
* already connected, while ensuring we get connected for
|
||||||
|
* new workspaces.
|
||||||
|
*/
|
||||||
|
g_signal_handlers_disconnect_by_func (workspace,
|
||||||
|
shell_app_monitor_on_window_added,
|
||||||
|
self);
|
||||||
|
g_signal_handlers_disconnect_by_func (workspace,
|
||||||
|
shell_app_monitor_on_window_removed,
|
||||||
|
self);
|
||||||
|
|
||||||
|
g_signal_connect (workspace, "window-added",
|
||||||
|
G_CALLBACK (shell_app_monitor_on_window_added), self);
|
||||||
|
g_signal_connect (workspace, "window-removed",
|
||||||
|
G_CALLBACK (shell_app_monitor_on_window_removed), self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
init_window_monitoring (ShellAppMonitor *self)
|
||||||
|
{
|
||||||
|
MetaScreen *screen = shell_global_get_screen (shell_global_get ());
|
||||||
|
|
||||||
|
g_signal_connect (screen, "notify::n-workspaces",
|
||||||
|
G_CALLBACK (shell_app_monitor_on_n_workspaces_changed), self);
|
||||||
|
shell_app_monitor_on_n_workspaces_changed (screen, NULL, self);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
shell_app_monitor_init (ShellAppMonitor *self)
|
shell_app_monitor_init (ShellAppMonitor *self)
|
||||||
{
|
{
|
||||||
@ -223,6 +458,15 @@ shell_app_monitor_init (ShellAppMonitor *self)
|
|||||||
(GDestroyNotify) g_free,
|
(GDestroyNotify) g_free,
|
||||||
(GDestroyNotify) g_free);
|
(GDestroyNotify) g_free);
|
||||||
|
|
||||||
|
self->running_appids = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||||
|
g_free, NULL);
|
||||||
|
|
||||||
|
self->window_to_appid = g_hash_table_new_full (g_direct_hash, g_direct_equal,
|
||||||
|
NULL, (GDestroyNotify) g_free);
|
||||||
|
|
||||||
|
load_initial_windows (self);
|
||||||
|
init_window_monitoring (self);
|
||||||
|
|
||||||
g_object_get (shell_global_get(), "configdir", &shell_config_dir, NULL),
|
g_object_get (shell_global_get(), "configdir", &shell_config_dir, NULL),
|
||||||
path = g_build_filename (shell_config_dir, DATA_FILENAME, NULL);
|
path = g_build_filename (shell_config_dir, DATA_FILENAME, NULL);
|
||||||
g_free (shell_config_dir);
|
g_free (shell_config_dir);
|
||||||
@ -299,16 +543,31 @@ shell_app_monitor_get_most_used_apps (ShellAppMonitor *monitor,
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find the active window in order to collect stats */
|
/**
|
||||||
void
|
* shell_app_monitor_get_running_app_ids:
|
||||||
get_active_app_properties (ShellAppMonitor *monitor,
|
*
|
||||||
char **wm_class,
|
* @monitor: An app monitor instance
|
||||||
char **title)
|
*
|
||||||
|
* Returns: (element-type utf8) (transfer container): List of application desktop
|
||||||
|
* identifiers
|
||||||
|
*/
|
||||||
|
GList *
|
||||||
|
shell_app_monitor_get_running_app_ids (ShellAppMonitor *monitor)
|
||||||
{
|
{
|
||||||
|
return g_hash_table_get_keys (monitor->running_appids);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
update_app_info (ShellAppMonitor *monitor)
|
||||||
|
{
|
||||||
|
char *wm_class;
|
||||||
ShellGlobal *global;
|
ShellGlobal *global;
|
||||||
|
GHashTable *app_active_times = NULL; /* last active time for an application */
|
||||||
MetaScreen *screen;
|
MetaScreen *screen;
|
||||||
MetaDisplay *display;
|
MetaDisplay *display;
|
||||||
MetaWindow *active;
|
MetaWindow *active;
|
||||||
|
int activity;
|
||||||
|
guint32 timestamp;
|
||||||
|
|
||||||
global = shell_global_get ();
|
global = shell_global_get ();
|
||||||
g_object_get (global, "screen", &screen, NULL);
|
g_object_get (global, "screen", &screen, NULL);
|
||||||
@ -317,60 +576,14 @@ get_active_app_properties (ShellAppMonitor *monitor,
|
|||||||
|
|
||||||
active = meta_display_get_focus_window (display);
|
active = meta_display_get_focus_window (display);
|
||||||
|
|
||||||
if (wm_class)
|
|
||||||
*wm_class = NULL;
|
|
||||||
if (title)
|
|
||||||
*title = NULL;
|
|
||||||
|
|
||||||
if (active == NULL)
|
if (active == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
*wm_class = g_strdup (meta_window_get_wm_class (active));
|
wm_class = get_cleaned_wmclass_for_window (active);
|
||||||
g_object_get (active, "title", title, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
update_app_info (ShellAppMonitor *monitor)
|
|
||||||
{
|
|
||||||
char *wm_class;
|
|
||||||
char *title;
|
|
||||||
GHashTable *app_active_times = NULL; /* GTime spent per activity */
|
|
||||||
static gboolean first_time = TRUE;
|
|
||||||
int activity;
|
|
||||||
guint32 timestamp;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (first_time) /* Generate match patterns once for all */
|
|
||||||
{
|
|
||||||
first_time = FALSE;
|
|
||||||
for (i = 0; title_patterns[i].app_id; i++)
|
|
||||||
{
|
|
||||||
title_patterns[i].regex = g_regex_new (title_patterns[i].pattern,
|
|
||||||
0, 0, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
get_active_app_properties (monitor, &wm_class, &title);
|
|
||||||
|
|
||||||
/* Match window title patterns to identifiers for non-standard apps */
|
|
||||||
if (title)
|
|
||||||
{
|
|
||||||
for (i = 0; title_patterns[i].app_id; i++)
|
|
||||||
{
|
|
||||||
if ( g_regex_match (title_patterns[i].regex, title, 0, NULL) )
|
|
||||||
{
|
|
||||||
/* Set a pseudo WM class, handled like true ones */
|
|
||||||
g_free (wm_class);
|
|
||||||
wm_class = g_strdup(title_patterns[i].app_id);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
g_free (title);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!wm_class)
|
if (!wm_class)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
app_active_times = g_hash_table_lookup (monitor->apps_by_wm_class, wm_class);
|
app_active_times = g_hash_table_lookup (monitor->apps_by_wm_class, wm_class);
|
||||||
if (!app_active_times)
|
if (!app_active_times)
|
||||||
{
|
{
|
||||||
|
@ -40,9 +40,10 @@ GSList *shell_app_monitor_get_most_used_apps (ShellAppMonitor *monitor,
|
|||||||
int activity,
|
int activity,
|
||||||
gint number);
|
gint number);
|
||||||
|
|
||||||
|
guint shell_app_monitor_get_window_count (ShellAppMonitor *monitor, const char *appid);
|
||||||
|
|
||||||
/* Get whatever's running right now */
|
/* Get whatever's running right now */
|
||||||
GSList *shell_app_monitor_get_running_apps (ShellAppMonitor *monitor,
|
GList *shell_app_monitor_get_running_app_ids (ShellAppMonitor *monitor);
|
||||||
int activity);
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
@ -1,19 +1,25 @@
|
|||||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
|
||||||
#include "shell-app-system.h"
|
#include "shell-app-system.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include <gio/gio.h>
|
#include <gio/gio.h>
|
||||||
|
#include <gconf/gconf.h>
|
||||||
|
#include <gconf/gconf-client.h>
|
||||||
|
|
||||||
#define GMENU_I_KNOW_THIS_IS_UNSTABLE
|
#define GMENU_I_KNOW_THIS_IS_UNSTABLE
|
||||||
#include <gmenu-tree.h>
|
#include <gmenu-tree.h>
|
||||||
|
|
||||||
|
#define SHELL_APP_FAVORITES_KEY "/desktop/gnome/shell/favorite_apps"
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
PROP_0,
|
PROP_0,
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
CHANGED,
|
INSTALLED_CHANGED,
|
||||||
|
FAVORITES_CHANGED,
|
||||||
LAST_SIGNAL
|
LAST_SIGNAL
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -26,11 +32,17 @@ struct _ShellAppSystemPrivate {
|
|||||||
GSList *cached_app_menus; /* ShellAppMenuEntry */
|
GSList *cached_app_menus; /* ShellAppMenuEntry */
|
||||||
|
|
||||||
GSList *cached_setting_ids; /* utf8 */
|
GSList *cached_setting_ids; /* utf8 */
|
||||||
|
|
||||||
|
GHashTable *cached_favorites; /* <utf8,integer> */
|
||||||
|
|
||||||
|
gint app_monitor_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void shell_app_system_finalize (GObject *object);
|
static void shell_app_system_finalize (GObject *object);
|
||||||
static void on_tree_changed (GMenuTree *tree, gpointer user_data);
|
static void on_tree_changed (GMenuTree *tree, gpointer user_data);
|
||||||
static void reread_menus (ShellAppSystem *self);
|
static void reread_menus (ShellAppSystem *self);
|
||||||
|
static void on_favorite_apps_changed (GConfClient *client, guint id, GConfEntry *entry, gpointer user_data);
|
||||||
|
static void reread_favorite_apps (ShellAppSystem *system);
|
||||||
|
|
||||||
G_DEFINE_TYPE(ShellAppSystem, shell_app_system, G_TYPE_OBJECT);
|
G_DEFINE_TYPE(ShellAppSystem, shell_app_system, G_TYPE_OBJECT);
|
||||||
|
|
||||||
@ -63,14 +75,22 @@ static void shell_app_system_class_init(ShellAppSystemClass *klass)
|
|||||||
|
|
||||||
gobject_class->finalize = shell_app_system_finalize;
|
gobject_class->finalize = shell_app_system_finalize;
|
||||||
|
|
||||||
signals[CHANGED] =
|
signals[INSTALLED_CHANGED] =
|
||||||
g_signal_new ("changed",
|
g_signal_new ("installed-changed",
|
||||||
SHELL_TYPE_APP_SYSTEM,
|
SHELL_TYPE_APP_SYSTEM,
|
||||||
G_SIGNAL_RUN_LAST,
|
G_SIGNAL_RUN_LAST,
|
||||||
G_STRUCT_OFFSET (ShellAppSystemClass, changed),
|
G_STRUCT_OFFSET (ShellAppSystemClass, installed_changed),
|
||||||
NULL, NULL,
|
NULL, NULL,
|
||||||
g_cclosure_marshal_VOID__VOID,
|
g_cclosure_marshal_VOID__VOID,
|
||||||
G_TYPE_NONE, 0);
|
G_TYPE_NONE, 0);
|
||||||
|
signals[FAVORITES_CHANGED] =
|
||||||
|
g_signal_new ("favorites-changed",
|
||||||
|
SHELL_TYPE_APP_SYSTEM,
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
G_STRUCT_OFFSET (ShellAppSystemClass, favorites_changed),
|
||||||
|
NULL, NULL,
|
||||||
|
g_cclosure_marshal_VOID__VOID,
|
||||||
|
G_TYPE_NONE, 0);
|
||||||
|
|
||||||
g_type_class_add_private (gobject_class, sizeof (ShellAppSystemPrivate));
|
g_type_class_add_private (gobject_class, sizeof (ShellAppSystemPrivate));
|
||||||
}
|
}
|
||||||
@ -79,10 +99,16 @@ static void
|
|||||||
shell_app_system_init (ShellAppSystem *self)
|
shell_app_system_init (ShellAppSystem *self)
|
||||||
{
|
{
|
||||||
ShellAppSystemPrivate *priv;
|
ShellAppSystemPrivate *priv;
|
||||||
|
GConfClient *client;
|
||||||
|
|
||||||
self->priv = priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
|
self->priv = priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
|
||||||
SHELL_TYPE_APP_SYSTEM,
|
SHELL_TYPE_APP_SYSTEM,
|
||||||
ShellAppSystemPrivate);
|
ShellAppSystemPrivate);
|
||||||
|
|
||||||
|
priv->cached_favorites = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||||
|
(GDestroyNotify)g_free,
|
||||||
|
NULL);
|
||||||
|
|
||||||
priv->apps_tree = gmenu_tree_lookup ("applications.menu", GMENU_TREE_FLAGS_NONE);
|
priv->apps_tree = gmenu_tree_lookup ("applications.menu", GMENU_TREE_FLAGS_NONE);
|
||||||
priv->settings_tree = gmenu_tree_lookup ("settings.menu", GMENU_TREE_FLAGS_NONE);
|
priv->settings_tree = gmenu_tree_lookup ("settings.menu", GMENU_TREE_FLAGS_NONE);
|
||||||
|
|
||||||
@ -90,6 +116,12 @@ shell_app_system_init (ShellAppSystem *self)
|
|||||||
gmenu_tree_add_monitor (priv->settings_tree, on_tree_changed, self);
|
gmenu_tree_add_monitor (priv->settings_tree, on_tree_changed, self);
|
||||||
|
|
||||||
reread_menus (self);
|
reread_menus (self);
|
||||||
|
|
||||||
|
client = gconf_client_get_default ();
|
||||||
|
|
||||||
|
self->priv->app_monitor_id = gconf_client_notify_add (client, SHELL_APP_FAVORITES_KEY,
|
||||||
|
on_favorite_apps_changed, self, NULL, NULL);
|
||||||
|
reread_favorite_apps (self);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -112,13 +144,16 @@ shell_app_system_finalize (GObject *object)
|
|||||||
g_slist_free (priv->cached_setting_ids);
|
g_slist_free (priv->cached_setting_ids);
|
||||||
priv->cached_setting_ids = NULL;
|
priv->cached_setting_ids = NULL;
|
||||||
|
|
||||||
|
g_hash_table_destroy (priv->cached_favorites);
|
||||||
|
|
||||||
|
gconf_client_notify_remove (gconf_client_get_default (), priv->app_monitor_id);
|
||||||
|
|
||||||
G_OBJECT_CLASS (shell_app_system_parent_class)->finalize(object);
|
G_OBJECT_CLASS (shell_app_system_parent_class)->finalize(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
reread_directories (ShellAppSystem *self, GSList **cache, GMenuTree *tree)
|
reread_directories (ShellAppSystem *self, GSList **cache, GMenuTree *tree)
|
||||||
{
|
{
|
||||||
ShellAppSystemPrivate *priv = self->priv;
|
|
||||||
GMenuTreeDirectory *trunk;
|
GMenuTreeDirectory *trunk;
|
||||||
GSList *entries;
|
GSList *entries;
|
||||||
GSList *iter;
|
GSList *iter;
|
||||||
@ -228,11 +263,58 @@ on_tree_changed (GMenuTree *monitor, gpointer user_data)
|
|||||||
{
|
{
|
||||||
ShellAppSystem *self = SHELL_APP_SYSTEM (user_data);
|
ShellAppSystem *self = SHELL_APP_SYSTEM (user_data);
|
||||||
|
|
||||||
g_signal_emit (self, signals[CHANGED], 0);
|
g_signal_emit (self, signals[INSTALLED_CHANGED], 0);
|
||||||
|
|
||||||
reread_menus (self);
|
reread_menus (self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
copy_gconf_value_string_list_to_hashset (GConfValue *value,
|
||||||
|
GHashTable *dest)
|
||||||
|
{
|
||||||
|
GSList *list;
|
||||||
|
GSList *tmp;
|
||||||
|
|
||||||
|
list = gconf_value_get_list (value);
|
||||||
|
|
||||||
|
for (tmp = list ; tmp; tmp = tmp->next)
|
||||||
|
{
|
||||||
|
GConfValue *value = tmp->data;
|
||||||
|
char *str = g_strdup (gconf_value_get_string (value));
|
||||||
|
if (!str)
|
||||||
|
continue;
|
||||||
|
g_hash_table_insert (dest, str, GUINT_TO_POINTER(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
reread_favorite_apps (ShellAppSystem *system)
|
||||||
|
{
|
||||||
|
GConfClient *client = gconf_client_get_default ();
|
||||||
|
GConfValue *val;
|
||||||
|
|
||||||
|
val = gconf_client_get (client, SHELL_APP_FAVORITES_KEY, NULL);
|
||||||
|
|
||||||
|
if (!(val && val->type == GCONF_VALUE_LIST && gconf_value_get_list_type (val) == GCONF_VALUE_STRING))
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_hash_table_remove_all (system->priv->cached_favorites);
|
||||||
|
copy_gconf_value_string_list_to_hashset (val, system->priv->cached_favorites);
|
||||||
|
|
||||||
|
gconf_value_free (val);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
on_favorite_apps_changed (GConfClient *client,
|
||||||
|
guint id,
|
||||||
|
GConfEntry *entry,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
ShellAppSystem *system = SHELL_APP_SYSTEM (user_data);
|
||||||
|
reread_favorite_apps (system);
|
||||||
|
g_signal_emit (G_OBJECT (system), signals[FAVORITES_CHANGED], 0);
|
||||||
|
}
|
||||||
|
|
||||||
GType
|
GType
|
||||||
shell_app_menu_entry_get_type (void)
|
shell_app_menu_entry_get_type (void)
|
||||||
{
|
{
|
||||||
@ -315,3 +397,160 @@ shell_app_system_get_default ()
|
|||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* shell_app_system_get_favorites:
|
||||||
|
*
|
||||||
|
* Return the list of applications which have been explicitly added to the
|
||||||
|
* favorites.
|
||||||
|
*
|
||||||
|
* Return value: (transfer container) (element-type utf8): List of favorite application ids
|
||||||
|
*/
|
||||||
|
GList *
|
||||||
|
shell_app_system_get_favorites (ShellAppSystem *system)
|
||||||
|
{
|
||||||
|
return g_hash_table_get_keys (system->priv->cached_favorites);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_gconf_value_string_list (GConfValue *val, GList *items)
|
||||||
|
{
|
||||||
|
GList *iter;
|
||||||
|
GSList *tmp = NULL;
|
||||||
|
|
||||||
|
for (iter = items; iter; iter = iter->next)
|
||||||
|
{
|
||||||
|
const char *str = iter->data;
|
||||||
|
GConfValue *strval = gconf_value_new (GCONF_VALUE_STRING);
|
||||||
|
gconf_value_set_string (strval, str);
|
||||||
|
tmp = g_slist_prepend (tmp, strval);
|
||||||
|
}
|
||||||
|
tmp = g_slist_reverse (tmp);
|
||||||
|
|
||||||
|
gconf_value_set_list (val, tmp);
|
||||||
|
g_slist_free (tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
shell_app_system_add_favorite (ShellAppSystem *system, const char *id)
|
||||||
|
{
|
||||||
|
GConfClient *client = gconf_client_get_default ();
|
||||||
|
GConfValue *val;
|
||||||
|
GList *favorites;
|
||||||
|
|
||||||
|
val = gconf_value_new (GCONF_VALUE_LIST);
|
||||||
|
gconf_value_set_list_type (val, GCONF_VALUE_STRING);
|
||||||
|
|
||||||
|
g_hash_table_insert (system->priv->cached_favorites, g_strdup (id), GUINT_TO_POINTER (1));
|
||||||
|
|
||||||
|
favorites = g_hash_table_get_keys (system->priv->cached_favorites);
|
||||||
|
set_gconf_value_string_list (val, favorites);
|
||||||
|
g_list_free (favorites);
|
||||||
|
|
||||||
|
gconf_client_set (client, SHELL_APP_FAVORITES_KEY, val, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
shell_app_system_remove_favorite (ShellAppSystem *system, const char *id)
|
||||||
|
{
|
||||||
|
GConfClient *client = gconf_client_get_default ();
|
||||||
|
GConfValue *val;
|
||||||
|
GList *favorites;
|
||||||
|
|
||||||
|
if (!g_hash_table_remove (system->priv->cached_favorites, id))
|
||||||
|
return;
|
||||||
|
|
||||||
|
val = gconf_value_new (GCONF_VALUE_LIST);
|
||||||
|
gconf_value_set_list_type (val, GCONF_VALUE_STRING);
|
||||||
|
|
||||||
|
favorites = g_hash_table_get_keys (system->priv->cached_favorites);
|
||||||
|
set_gconf_value_string_list (val, favorites);
|
||||||
|
g_list_free (favorites);
|
||||||
|
|
||||||
|
gconf_client_set (client, SHELL_APP_FAVORITES_KEY, val, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
desktop_id_exists (ShellAppSystem *system,
|
||||||
|
const char *target_id,
|
||||||
|
GMenuTreeDirectory *root)
|
||||||
|
{
|
||||||
|
gboolean found = FALSE;
|
||||||
|
GSList *contents, *iter;
|
||||||
|
|
||||||
|
contents = gmenu_tree_directory_get_contents (root);
|
||||||
|
|
||||||
|
for (iter = contents; iter; iter = iter->next)
|
||||||
|
{
|
||||||
|
GMenuTreeItem *item = iter->data;
|
||||||
|
|
||||||
|
if (found)
|
||||||
|
break;
|
||||||
|
|
||||||
|
switch (gmenu_tree_item_get_type (item))
|
||||||
|
{
|
||||||
|
case GMENU_TREE_ITEM_ENTRY:
|
||||||
|
{
|
||||||
|
GMenuTreeEntry *entry = (GMenuTreeEntry *)item;
|
||||||
|
const char *id = gmenu_tree_entry_get_desktop_file_id (entry);
|
||||||
|
if (strcmp (id, target_id) == 0)
|
||||||
|
found = TRUE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GMENU_TREE_ITEM_DIRECTORY:
|
||||||
|
{
|
||||||
|
GMenuTreeDirectory *dir = (GMenuTreeDirectory*)item;
|
||||||
|
found = desktop_id_exists (system, target_id, dir);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
gmenu_tree_item_unref (item);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_slist_free (contents);
|
||||||
|
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* shell_app_system_lookup_basename:
|
||||||
|
* @name: Probable application identifier
|
||||||
|
*
|
||||||
|
* Determine whether a valid .desktop file ID corresponding to a given
|
||||||
|
* heuristically determined application identifier
|
||||||
|
* string.
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
shell_app_system_lookup_basename (ShellAppSystem *system,
|
||||||
|
const char *name)
|
||||||
|
{
|
||||||
|
GMenuTreeDirectory *root;
|
||||||
|
char *result;
|
||||||
|
|
||||||
|
root = gmenu_tree_get_directory_from_path (system->priv->apps_tree, "/");
|
||||||
|
g_assert (root != NULL);
|
||||||
|
|
||||||
|
if (desktop_id_exists (system, name, root))
|
||||||
|
{
|
||||||
|
result = g_strdup (name);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* These are common "vendor prefixes". But using
|
||||||
|
* WM_CLASS as a source, we don't get the vendor
|
||||||
|
* prefix. So try stripping them.
|
||||||
|
*/
|
||||||
|
result = g_strjoin ("", "gnome-", name, NULL);
|
||||||
|
if (desktop_id_exists (system, result, root))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
result = g_strjoin ("", "fedora-", name, NULL);
|
||||||
|
if (desktop_id_exists (system, result, root))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
out:
|
||||||
|
gmenu_tree_item_unref (root);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
@ -25,7 +25,8 @@ struct _ShellAppSystemClass
|
|||||||
{
|
{
|
||||||
GObjectClass parent_class;
|
GObjectClass parent_class;
|
||||||
|
|
||||||
void (*changed)(ShellAppSystem *appsys, gpointer data);
|
void (*installed_changed)(ShellAppSystem *appsys, gpointer user_data);
|
||||||
|
void (*favorites_changed)(ShellAppSystem *appsys, gpointer user_data);
|
||||||
};
|
};
|
||||||
|
|
||||||
GType shell_app_system_get_type (void) G_GNUC_CONST;
|
GType shell_app_system_get_type (void) G_GNUC_CONST;
|
||||||
@ -43,8 +44,16 @@ struct _ShellAppMenuEntry {
|
|||||||
|
|
||||||
GType shell_app_menu_entry_get_type (void);
|
GType shell_app_menu_entry_get_type (void);
|
||||||
|
|
||||||
|
char * shell_app_system_lookup_basename (ShellAppSystem *system, const char *id);
|
||||||
|
|
||||||
GSList *shell_app_system_get_menus (ShellAppSystem *system);
|
GSList *shell_app_system_get_menus (ShellAppSystem *system);
|
||||||
|
|
||||||
GSList *shell_app_system_get_all_settings (ShellAppSystem *system);
|
GSList *shell_app_system_get_all_settings (ShellAppSystem *system);
|
||||||
|
|
||||||
|
GList *shell_app_system_get_favorites (ShellAppSystem *system);
|
||||||
|
|
||||||
|
void shell_app_system_add_favorite (ShellAppSystem *system, const char *id);
|
||||||
|
|
||||||
|
void shell_app_system_remove_favorite (ShellAppSystem *system, const char *id);
|
||||||
|
|
||||||
#endif /* __SHELL_APP_SYSTEM_H__ */
|
#endif /* __SHELL_APP_SYSTEM_H__ */
|
||||||
|
@ -101,7 +101,7 @@ shell_global_get_property(GObject *object,
|
|||||||
g_value_set_object (value, mutter_plugin_get_overlay_group (global->plugin));
|
g_value_set_object (value, mutter_plugin_get_overlay_group (global->plugin));
|
||||||
break;
|
break;
|
||||||
case PROP_SCREEN:
|
case PROP_SCREEN:
|
||||||
g_value_set_object (value, mutter_plugin_get_screen (global->plugin));
|
g_value_set_object (value, shell_global_get_screen (global));
|
||||||
break;
|
break;
|
||||||
case PROP_SCREEN_WIDTH:
|
case PROP_SCREEN_WIDTH:
|
||||||
{
|
{
|
||||||
@ -608,6 +608,17 @@ shell_global_set_stage_input_region (ShellGlobal *global,
|
|||||||
shell_global_set_stage_input_mode (global, global->input_mode);
|
shell_global_set_stage_input_mode (global, global->input_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* shell_global_get_screen:
|
||||||
|
*
|
||||||
|
* Return value: (transfer none): The default #MetaScreen
|
||||||
|
*/
|
||||||
|
MetaScreen *
|
||||||
|
shell_global_get_screen (ShellGlobal *global)
|
||||||
|
{
|
||||||
|
return mutter_plugin_get_screen (global->plugin);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* shell_global_get_windows:
|
* shell_global_get_windows:
|
||||||
*
|
*
|
||||||
@ -933,6 +944,55 @@ shell_global_create_vertical_gradient (ClutterColor *top,
|
|||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* shell_global_create_horizontal_gradient:
|
||||||
|
* @left: the color on the left
|
||||||
|
* @right: the color on the right
|
||||||
|
*
|
||||||
|
* Creates a horizontal gradient actor.
|
||||||
|
*
|
||||||
|
* Return value: (transfer none): a #ClutterCairoTexture actor with the
|
||||||
|
* gradient. The texture actor is floating, hence (transfer none).
|
||||||
|
*/
|
||||||
|
ClutterCairoTexture *
|
||||||
|
shell_global_create_horizontal_gradient (ClutterColor *left,
|
||||||
|
ClutterColor *right)
|
||||||
|
{
|
||||||
|
ClutterCairoTexture *texture;
|
||||||
|
cairo_t *cr;
|
||||||
|
cairo_pattern_t *pattern;
|
||||||
|
|
||||||
|
/* Draw the gradient on an 8x1 pixel texture. Because the gradient is drawn
|
||||||
|
* from the left to the right column, after stretching 1/16 of the
|
||||||
|
* texture width has the left side color and 1/16 has the right side color.
|
||||||
|
* There is no reason to use the 8 pixel height that would be similar to the
|
||||||
|
* reason we are using the 8 pixel width for the vertical gradient, so we
|
||||||
|
* are just using the 1 pixel height instead.
|
||||||
|
*/
|
||||||
|
texture = CLUTTER_CAIRO_TEXTURE (clutter_cairo_texture_new (8, 1));
|
||||||
|
cr = clutter_cairo_texture_create (texture);
|
||||||
|
|
||||||
|
pattern = cairo_pattern_create_linear (0, 0, 8, 0);
|
||||||
|
cairo_pattern_add_color_stop_rgba (pattern, 0,
|
||||||
|
left->red / 255.,
|
||||||
|
left->green / 255.,
|
||||||
|
left->blue / 255.,
|
||||||
|
left->alpha / 255.);
|
||||||
|
cairo_pattern_add_color_stop_rgba (pattern, 1,
|
||||||
|
right->red / 255.,
|
||||||
|
right->green / 255.,
|
||||||
|
right->blue / 255.,
|
||||||
|
right->alpha / 255.);
|
||||||
|
|
||||||
|
cairo_set_source (cr, pattern);
|
||||||
|
cairo_paint (cr);
|
||||||
|
|
||||||
|
cairo_pattern_destroy (pattern);
|
||||||
|
cairo_destroy (cr);
|
||||||
|
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Updates the global->root_pixmap actor with the root window's pixmap or fails
|
* Updates the global->root_pixmap actor with the root window's pixmap or fails
|
||||||
* with a warning.
|
* with a warning.
|
||||||
|
@ -48,6 +48,8 @@ ClutterActor *shell_get_event_related(ClutterEvent *event);
|
|||||||
|
|
||||||
ShellGlobal *shell_global_get (void);
|
ShellGlobal *shell_global_get (void);
|
||||||
|
|
||||||
|
MetaScreen *shell_global_get_screen (ShellGlobal *global);
|
||||||
|
|
||||||
void shell_global_grab_dbus_service (ShellGlobal *global);
|
void shell_global_grab_dbus_service (ShellGlobal *global);
|
||||||
|
|
||||||
void shell_global_start_task_panel (ShellGlobal *global);
|
void shell_global_start_task_panel (ShellGlobal *global);
|
||||||
@ -76,6 +78,9 @@ void shell_global_reexec_self (ShellGlobal *global);
|
|||||||
ClutterCairoTexture *shell_global_create_vertical_gradient (ClutterColor *top,
|
ClutterCairoTexture *shell_global_create_vertical_gradient (ClutterColor *top,
|
||||||
ClutterColor *bottom);
|
ClutterColor *bottom);
|
||||||
|
|
||||||
|
ClutterCairoTexture *shell_global_create_horizontal_gradient (ClutterColor *left,
|
||||||
|
ClutterColor *right);
|
||||||
|
|
||||||
ClutterActor *shell_global_create_root_pixmap_actor (ShellGlobal *global);
|
ClutterActor *shell_global_create_root_pixmap_actor (ShellGlobal *global);
|
||||||
|
|
||||||
void shell_global_clutter_cairo_texture_draw_clock (ClutterCairoTexture *texture,
|
void shell_global_clutter_cairo_texture_draw_clock (ClutterCairoTexture *texture,
|
||||||
|
Loading…
Reference in New Issue
Block a user