Compare commits
	
		
			48 Commits
		
	
	
		
			2.91.91
			...
			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>
 | 
			
		||||
      </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>
 | 
			
		||||
 | 
			
		||||
</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;
 | 
			
		||||
 | 
			
		||||
// 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) {
 | 
			
		||||
    this._init(appId);
 | 
			
		||||
}
 | 
			
		||||
@@ -41,8 +15,9 @@ AppInfo.prototype = {
 | 
			
		||||
    _init : function(appId) {
 | 
			
		||||
        this.appId = appId;
 | 
			
		||||
        this._gAppInfo = Gio.DesktopAppInfo.new(appId);
 | 
			
		||||
        if (!this._gAppInfo)
 | 
			
		||||
        if (!this._gAppInfo) {
 | 
			
		||||
            throw new Error('Unknown appId ' + appId);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.id = this._gAppInfo.get_id();
 | 
			
		||||
        this.name = this._gAppInfo.get_name();
 | 
			
		||||
@@ -52,7 +27,7 @@ AppInfo.prototype = {
 | 
			
		||||
        this._gicon = this._gAppInfo.get_icon();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getIcon : function(size) {
 | 
			
		||||
    createIcon : function(size) {
 | 
			
		||||
        if (this._gicon)
 | 
			
		||||
            return Shell.TextureCache.get_default().load_gicon(this._gicon, size);
 | 
			
		||||
        else
 | 
			
		||||
@@ -96,40 +71,64 @@ function getAppInfo(appId) {
 | 
			
		||||
    return info;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getMostUsedApps:
 | 
			
		||||
// getTopApps:
 | 
			
		||||
// @count: maximum number of apps to retrieve
 | 
			
		||||
//
 | 
			
		||||
// Gets a list of #AppInfos for the @count most-frequently-used
 | 
			
		||||
// applications
 | 
			
		||||
// applications, with explicitly-chosen favorites first.
 | 
			
		||||
//
 | 
			
		||||
// Return value: the list of #AppInfo
 | 
			
		||||
function getMostUsedApps(count) {
 | 
			
		||||
function getTopApps(count) {
 | 
			
		||||
    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
 | 
			
		||||
    // 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 matches = [], alreadyAdded = {};
 | 
			
		||||
 | 
			
		||||
    for (let i = 0; i < apps.length && matches.length <= count; i++) {
 | 
			
		||||
        let appId = apps[i] + ".desktop";
 | 
			
		||||
        if (alreadyAdded[appId])
 | 
			
		||||
            continue;
 | 
			
		||||
        alreadyAdded[appId] = true;
 | 
			
		||||
        let appInfo = getAppInfo(appId);
 | 
			
		||||
        if (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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getIcon : function(size) {
 | 
			
		||||
    createIcon : function(size) {
 | 
			
		||||
        let icon = new Clutter.Texture();
 | 
			
		||||
        let iconPixbuf;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -5,16 +5,21 @@ const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Pango = imports.gi.Pango;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const Gtk = imports.gi.Gtk;
 | 
			
		||||
const Tidy = imports.gi.Tidy;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
const Mainloop = imports.mainloop;
 | 
			
		||||
 | 
			
		||||
const AppInfo = imports.misc.appInfo;
 | 
			
		||||
const DND = imports.ui.dnd;
 | 
			
		||||
const GenericDisplay = imports.ui.genericDisplay;
 | 
			
		||||
 | 
			
		||||
const ENTERED_MENU_COLOR = new Clutter.Color();
 | 
			
		||||
ENTERED_MENU_COLOR.from_pixel(0x00ff0022);
 | 
			
		||||
 | 
			
		||||
const APP_ICON_SIZE = 48;
 | 
			
		||||
 | 
			
		||||
const MENU_ICON_SIZE = 24;
 | 
			
		||||
const MENU_SPACING = 15;
 | 
			
		||||
 | 
			
		||||
@@ -33,11 +38,10 @@ AppDisplayItem.prototype = {
 | 
			
		||||
    __proto__:  GenericDisplay.GenericDisplayItem.prototype,
 | 
			
		||||
 | 
			
		||||
    _init : function(appInfo, availableWidth) {
 | 
			
		||||
        GenericDisplay.GenericDisplayItem.prototype._init.call(this, availableWidth); 
 | 
			
		||||
        GenericDisplay.GenericDisplayItem.prototype._init.call(this, availableWidth);
 | 
			
		||||
        this._appInfo = appInfo;
 | 
			
		||||
 | 
			
		||||
        this._setItemInfo(appInfo.name, appInfo.description,
 | 
			
		||||
                          appInfo.getIcon(GenericDisplay.ITEM_DISPLAY_ICON_SIZE));
 | 
			
		||||
        this._setItemInfo(appInfo.name, appInfo.description);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    //// Public method overrides ////
 | 
			
		||||
@@ -49,15 +53,20 @@ AppDisplayItem.prototype = {
 | 
			
		||||
 | 
			
		||||
    //// 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.
 | 
			
		||||
    _ensurePreviewIconCreated : function() {
 | 
			
		||||
        if (!this._showPreview || this._previewIcon)
 | 
			
		||||
            return; 
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let previewIconPath = this._appInfo.getIconPath(GenericDisplay.PREVIEW_ICON_SIZE);
 | 
			
		||||
        if (previewIconPath) {
 | 
			
		||||
            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);
 | 
			
		||||
            } catch (e) {
 | 
			
		||||
                // 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);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* This class represents a display containing a collection of application items.
 | 
			
		||||
 * The applications are sorted based on their popularity by default, and based on
 | 
			
		||||
 * their name if some search filter is applied.
 | 
			
		||||
@@ -173,16 +183,15 @@ AppDisplay.prototype = {
 | 
			
		||||
        this._appMonitor = Shell.AppMonitor.get_default();
 | 
			
		||||
        this._appSystem = Shell.AppSystem.get_default();
 | 
			
		||||
        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;
 | 
			
		||||
            // 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._redisplayMenus();
 | 
			
		||||
        }));
 | 
			
		||||
        this._appSystem.connect('favorites-changed', Lang.bind(this, function(appSys) {
 | 
			
		||||
            this._redisplay(false);
 | 
			
		||||
        }));
 | 
			
		||||
        this._appMonitor.connect('changed', Lang.bind(this, function(monitor) {
 | 
			
		||||
            this._appsStale = true;
 | 
			
		||||
            this._redisplay(false);
 | 
			
		||||
        }));
 | 
			
		||||
 | 
			
		||||
@@ -308,8 +317,6 @@ AppDisplay.prototype = {
 | 
			
		||||
        this._appCategories[appId] = categories;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    //// Protected method overrides //// 
 | 
			
		||||
 | 
			
		||||
    // Gets information about all applications by calling Gio.app_info_get_all().
 | 
			
		||||
    _refreshCache : function() {
 | 
			
		||||
        let me = this;
 | 
			
		||||
@@ -339,21 +346,12 @@ AppDisplay.prototype = {
 | 
			
		||||
            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;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    // Sets the list of the displayed items based on the most used apps.
 | 
			
		||||
    _setDefaultList : function() {
 | 
			
		||||
        let matchedInfos = AppInfo.getMostUsedApps(MAX_ITEMS);
 | 
			
		||||
        let matchedInfos = AppInfo.getTopApps(MAX_ITEMS);
 | 
			
		||||
        this._matchedItems = matchedInfos.map(function(info) { return info.appId; });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -430,3 +428,197 @@ 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);     
 | 
			
		||||
        this._docInfo = docInfo;
 | 
			
		||||
    
 | 
			
		||||
        this._setItemInfo(docInfo.name, "",
 | 
			
		||||
                          docInfo.getIcon(GenericDisplay.ITEM_DISPLAY_ICON_SIZE));
 | 
			
		||||
        this._setItemInfo(docInfo.name, "");
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    //// Public methods ////
 | 
			
		||||
@@ -42,10 +41,15 @@ DocDisplayItem.prototype = {
 | 
			
		||||
 | 
			
		||||
    //// 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.
 | 
			
		||||
    _ensurePreviewIconCreated : function() {
 | 
			
		||||
        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
 | 
			
		||||
 
 | 
			
		||||
@@ -22,7 +22,7 @@ ITEM_DISPLAY_DESCRIPTION_COLOR.from_pixel(0xffffffbb);
 | 
			
		||||
const ITEM_DISPLAY_BACKGROUND_COLOR = new Clutter.Color();
 | 
			
		||||
ITEM_DISPLAY_BACKGROUND_COLOR.from_pixel(0x00000000);
 | 
			
		||||
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();
 | 
			
		||||
DISPLAY_CONTROL_SELECTED_COLOR.from_pixel(0x112288ff);
 | 
			
		||||
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_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 LABEL_HEIGHT = 16;
 | 
			
		||||
 | 
			
		||||
@@ -42,6 +43,8 @@ const PREVIEW_BOX_CORNER_RADIUS = 10;
 | 
			
		||||
const PREVIEW_PLACING = 3/4;
 | 
			
		||||
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
 | 
			
		||||
 * 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.
 | 
			
		||||
@@ -55,22 +58,17 @@ function GenericDisplayItem(availableWidth) {
 | 
			
		||||
GenericDisplayItem.prototype = {
 | 
			
		||||
    _init: function(availableWidth) {
 | 
			
		||||
        this._availableWidth = availableWidth;
 | 
			
		||||
        this._showPreview = false;
 | 
			
		||||
        this._havePointer = false; 
 | 
			
		||||
        this._previewEventSourceId = null;
 | 
			
		||||
 | 
			
		||||
        this.actor = new Clutter.Group({ reactive: true,
 | 
			
		||||
                                         width: availableWidth,
 | 
			
		||||
                                         height: ITEM_DISPLAY_HEIGHT });
 | 
			
		||||
        this.actor._delegate = this;
 | 
			
		||||
        this.actor.connect('button-press-event',
 | 
			
		||||
                           Lang.bind(this,
 | 
			
		||||
                                     function(actor, e) {
 | 
			
		||||
                                         let clickCount = Shell.get_button_event_click_count(e);
 | 
			
		||||
                                         if (clickCount == 1)
 | 
			
		||||
                                             this.select();
 | 
			
		||||
                                         else if (clickCount == 2)
 | 
			
		||||
                                             this.activate();
 | 
			
		||||
        this.actor.connect('button-release-event', 
 | 
			
		||||
                           Lang.bind(this, 
 | 
			
		||||
                                     function() {
 | 
			
		||||
                                         // Activates the item by launching it
 | 
			
		||||
                                         this.emit('activate');
 | 
			
		||||
                                         return true;  
 | 
			
		||||
                                     }));
 | 
			
		||||
 | 
			
		||||
        let draggable = DND.makeDraggable(this.actor);
 | 
			
		||||
@@ -81,11 +79,40 @@ GenericDisplayItem.prototype = {
 | 
			
		||||
                                 x: 0, y: 0,
 | 
			
		||||
                                 width: availableWidth, height: ITEM_DISPLAY_HEIGHT });
 | 
			
		||||
        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._description = null;
 | 
			
		||||
        this._icon = null;
 | 
			
		||||
        this._preview = null;
 | 
			
		||||
        this._previewIcon = 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 
 | 
			
		||||
    // is being dragged. 
 | 
			
		||||
    getDragActor: function(stageX, stageY) {
 | 
			
		||||
        this.dragActor = new Clutter.Clone({ source: this._icon });
 | 
			
		||||
        [this.dragActor.width, this.dragActor.height] = this._icon.get_transformed_size();
 | 
			
		||||
        this.dragActor = this._createIcon();
 | 
			
		||||
 | 
			
		||||
        // If the user dragged from the icon itself, then position
 | 
			
		||||
        // the dragActor over the original icon. Otherwise center it
 | 
			
		||||
@@ -115,58 +141,19 @@ GenericDisplayItem.prototype = {
 | 
			
		||||
        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.
 | 
			
		||||
    // Returns the item icon, a separate copy of which is used to
 | 
			
		||||
    // 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() {
 | 
			
		||||
        return this._icon;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    //// Public methods ////
 | 
			
		||||
 | 
			
		||||
    // Sets a boolean value that indicates whether the item should display a pop-up preview on mouse over.
 | 
			
		||||
    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.
 | 
			
		||||
    // Shows the information button when the item was drawn under the mouse pointer.
 | 
			
		||||
    onDrawnUnderPointer: function() {
 | 
			
		||||
        this._havePointer = true;
 | 
			
		||||
        // 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();  
 | 
			
		||||
        this._informationButton.show();  
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    // Highlights the item by setting a different background color than the default 
 | 
			
		||||
@@ -180,17 +167,6 @@ GenericDisplayItem.prototype = {
 | 
			
		||||
       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 
 | 
			
		||||
     * the preview pop-up has and be item-type specific.
 | 
			
		||||
@@ -199,7 +175,7 @@ GenericDisplayItem.prototype = {
 | 
			
		||||
     * availableHeight - height available for displaying details
 | 
			
		||||
     */ 
 | 
			
		||||
    createDetailsActor: function(availableWidth, availableHeight) {
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
        let details = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
 | 
			
		||||
                                    spacing: PREVIEW_BOX_SPACING,
 | 
			
		||||
                                    width: availableWidth });
 | 
			
		||||
@@ -241,28 +217,12 @@ GenericDisplayItem.prototype = {
 | 
			
		||||
            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;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    // Destoys the item, as well as a preview for the item if it exists.
 | 
			
		||||
    // Destoys the item.
 | 
			
		||||
    destroy: function() {
 | 
			
		||||
      this.actor.destroy();
 | 
			
		||||
      if (this._preview != null)
 | 
			
		||||
          this._preview.destroy();
 | 
			
		||||
    },
 | 
			
		||||
    
 | 
			
		||||
    //// Pure virtual public methods ////
 | 
			
		||||
@@ -279,9 +239,8 @@ GenericDisplayItem.prototype = {
 | 
			
		||||
     *
 | 
			
		||||
     * nameText - name 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) {
 | 
			
		||||
            // this also removes this._name from the parent container,
 | 
			
		||||
            // 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 = null;
 | 
			
		||||
        } 
 | 
			
		||||
        // This ensures we'll create a new preview and previewIcon next time we need a preview
 | 
			
		||||
        if (this._preview != null) {
 | 
			
		||||
            this._preview.destroy();
 | 
			
		||||
            this._preview = null;
 | 
			
		||||
        }
 | 
			
		||||
        // This ensures we'll create a new previewIcon next time we need it
 | 
			
		||||
        if (this._previewIcon != null) {
 | 
			
		||||
            this._previewIcon.destroy();
 | 
			
		||||
            this._previewIcon = null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._icon = iconActor;
 | 
			
		||||
        this._icon = this._createIcon();
 | 
			
		||||
        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,
 | 
			
		||||
                                        font_name: "Sans 14px",
 | 
			
		||||
                                        width: textWidth,
 | 
			
		||||
                                        ellipsize: Pango.EllipsizeMode.END,
 | 
			
		||||
                                        text: nameText,
 | 
			
		||||
                                        x: ITEM_DISPLAY_ICON_SIZE + 4,
 | 
			
		||||
                                        y: ITEM_DISPLAY_PADDING });
 | 
			
		||||
                                        y: ITEM_DISPLAY_PADDING_TOP });
 | 
			
		||||
        this.actor.add_actor(this._name);
 | 
			
		||||
        this._description = new Clutter.Text({ color: ITEM_DISPLAY_DESCRIPTION_COLOR,
 | 
			
		||||
                                               font_name: "Sans 12px",
 | 
			
		||||
@@ -339,6 +294,11 @@ GenericDisplayItem.prototype = {
 | 
			
		||||
 | 
			
		||||
    //// Pure virtual protected methods ////
 | 
			
		||||
 | 
			
		||||
    // Returns an icon for the item.
 | 
			
		||||
    _createIcon: function() {
 | 
			
		||||
        throw new Error("Not implemented");
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    // Ensures the preview icon is created.
 | 
			
		||||
    _ensurePreviewIconCreated: function() {
 | 
			
		||||
        throw new Error("Not implemented");
 | 
			
		||||
@@ -346,79 +306,21 @@ GenericDisplayItem.prototype = {
 | 
			
		||||
 | 
			
		||||
    //// Private methods ////
 | 
			
		||||
 | 
			
		||||
    // Ensures the preview actor is created.
 | 
			
		||||
    _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.
 | 
			
		||||
    // Performs actions on mouse enter event for the item. Currently, shows the information button for the item.
 | 
			
		||||
    _onEnter: function(actor, event) {
 | 
			
		||||
        this._havePointer = true;
 | 
			
		||||
        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;
 | 
			
		||||
                                                                    }));
 | 
			
		||||
        this._informationButton.show();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    // 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) {
 | 
			
		||||
        this._havePointer = false;
 | 
			
		||||
        this.hidePreview();
 | 
			
		||||
        this._informationButton.hide();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    // Hides the preview once the item starts being dragged.
 | 
			
		||||
    // Hides the information button once the item starts being dragged.
 | 
			
		||||
    _onDragBegin : function (draggable, time) {
 | 
			
		||||
        // 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  
 | 
			
		||||
        // the preview as soon as the item starts being dragged anyway.
 | 
			
		||||
        this._havePointer = false;  
 | 
			
		||||
        this.hidePreview();
 | 
			
		||||
        // so we should remove the link manually.
 | 
			
		||||
        this._informationButton.hide();
 | 
			
		||||
    } 
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -469,8 +371,6 @@ GenericDisplay.prototype = {
 | 
			
		||||
        // See also getSideArea.
 | 
			
		||||
        this.actor = this._grid;
 | 
			
		||||
        this.displayControl = new Big.Box({ background_color: ITEM_DISPLAY_BACKGROUND_COLOR,
 | 
			
		||||
                                            corner_radius: 4,
 | 
			
		||||
                                            height: 24,
 | 
			
		||||
                                            spacing: 12,
 | 
			
		||||
                                            orientation: Big.BoxOrientation.HORIZONTAL});
 | 
			
		||||
 | 
			
		||||
@@ -557,14 +457,6 @@ GenericDisplay.prototype = {
 | 
			
		||||
        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.
 | 
			
		||||
    hasItems: function() {
 | 
			
		||||
        return this._displayedItemsCount > 0;
 | 
			
		||||
@@ -645,13 +537,13 @@ GenericDisplay.prototype = {
 | 
			
		||||
        Mainloop.timeout_add(5, 
 | 
			
		||||
                             Lang.bind(this,
 | 
			
		||||
                                       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 global = Shell.Global.get();
 | 
			
		||||
                                           let actor = global.stage.get_actor_at_pos(Clutter.PickMode.REACTIVE,
 | 
			
		||||
                                                                                     x, y);
 | 
			
		||||
                                           if (actor != null) {
 | 
			
		||||
                                               let item = this._findDisplayedByActor(actor.get_parent());
 | 
			
		||||
                                               let item = this._findDisplayedByActor(actor);
 | 
			
		||||
                                               if (item != null) {
 | 
			
		||||
                                                   item.onDrawnUnderPointer();
 | 
			
		||||
                                               }
 | 
			
		||||
@@ -670,7 +562,6 @@ GenericDisplay.prototype = {
 | 
			
		||||
 | 
			
		||||
        let itemInfo = this._allItems[itemId];
 | 
			
		||||
        let displayItem = this._createDisplayItem(itemInfo);
 | 
			
		||||
        displayItem.setShowPreview(true);
 | 
			
		||||
 | 
			
		||||
        displayItem.connect('activate', 
 | 
			
		||||
                            Lang.bind(this,
 | 
			
		||||
@@ -702,32 +593,8 @@ GenericDisplay.prototype = {
 | 
			
		||||
            this.selectUp();
 | 
			
		||||
        } 
 | 
			
		||||
 | 
			
		||||
        if (displayItem.dragActor) {
 | 
			
		||||
            // 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();
 | 
			
		||||
        }
 | 
			
		||||
        displayItem.destroy();
 | 
			
		||||
 | 
			
		||||
        delete this._displayedItems[itemId];
 | 
			
		||||
        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,
 | 
			
		||||
                                 reactive: true });
 | 
			
		||||
        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,
 | 
			
		||||
                                       font_name: "Sans 14px",
 | 
			
		||||
                                       ellipsize: Pango.EllipsizeMode.END,
 | 
			
		||||
@@ -203,7 +203,7 @@ LauncherWidget.prototype = {
 | 
			
		||||
                             padding: ITEM_PADDING,
 | 
			
		||||
                             reactive: true });
 | 
			
		||||
        item._info = info;
 | 
			
		||||
        item.append(info.getIcon(COLLAPSED_WIDTH - 2 * ITEM_PADDING),
 | 
			
		||||
        item.append(info.createIcon(COLLAPSED_WIDTH - 2 * ITEM_PADDING),
 | 
			
		||||
                    Big.BoxPackFlags.NONE);
 | 
			
		||||
 | 
			
		||||
        this.collapsedActor.append(item, Big.BoxPackFlags.NONE);
 | 
			
		||||
@@ -284,7 +284,7 @@ AppsWidget.prototype = {
 | 
			
		||||
        this.actor = 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++)
 | 
			
		||||
            this.addItem(apps[i]);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -11,6 +11,7 @@ const Pango = imports.gi.Pango;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
 | 
			
		||||
const AppDisplay = imports.ui.appDisplay;
 | 
			
		||||
const DND = imports.ui.dnd;
 | 
			
		||||
const GenericDisplay = imports.ui.genericDisplay;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
@@ -752,7 +753,7 @@ Workspace.prototype = {
 | 
			
		||||
                                                 false, // don't create workspace
 | 
			
		||||
                                                 time);
 | 
			
		||||
            return true;
 | 
			
		||||
        } else if (source instanceof GenericDisplay.GenericDisplayItem) {
 | 
			
		||||
        } else if (source instanceof GenericDisplay.GenericDisplayItem || source instanceof AppDisplay.WellDisplayItem) {
 | 
			
		||||
            this._metaWorkspace.activate(time);
 | 
			
		||||
            source.launch();
 | 
			
		||||
            return true;
 | 
			
		||||
 
 | 
			
		||||
@@ -13,9 +13,11 @@
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include "shell-app-monitor.h"
 | 
			
		||||
#include "shell-app-system.h"
 | 
			
		||||
#include "shell-global.h"
 | 
			
		||||
 | 
			
		||||
#include "display.h"
 | 
			
		||||
#include "window.h"
 | 
			
		||||
 | 
			
		||||
/* This file includes modified code from
 | 
			
		||||
 * desktop-data-engine/engine-dbus/hippo-application-monitor.c
 | 
			
		||||
@@ -63,6 +65,7 @@ static struct
 | 
			
		||||
  const char *pattern;
 | 
			
		||||
  GRegex *regex;
 | 
			
		||||
} title_patterns[] =  {
 | 
			
		||||
    {"mozilla-firefox", ".* - Mozilla Firefox", NULL}, \
 | 
			
		||||
    {"openoffice.org-writer", ".* - OpenOffice.org Writer$", NULL}, \
 | 
			
		||||
    {"openoffice.org-calc", ".* - OpenOffice.org Calc$", NULL}, \
 | 
			
		||||
    {"openoffice.org-impress", ".* - OpenOffice.org Impress$", NULL}, \
 | 
			
		||||
@@ -93,6 +96,12 @@ struct _ShellAppMonitor
 | 
			
		||||
  gboolean currently_idle;
 | 
			
		||||
  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 *popularities; /* One AppPopularity struct list per activity */
 | 
			
		||||
  int upload_apps_burst_count;
 | 
			
		||||
@@ -191,6 +200,232 @@ destroy_popularity (gpointer key,
 | 
			
		||||
  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
 | 
			
		||||
shell_app_monitor_init (ShellAppMonitor *self)
 | 
			
		||||
{
 | 
			
		||||
@@ -223,6 +458,15 @@ shell_app_monitor_init (ShellAppMonitor *self)
 | 
			
		||||
                                                  (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),
 | 
			
		||||
  path = g_build_filename (shell_config_dir, DATA_FILENAME, NULL);
 | 
			
		||||
  g_free (shell_config_dir);
 | 
			
		||||
@@ -299,16 +543,31 @@ shell_app_monitor_get_most_used_apps (ShellAppMonitor *monitor,
 | 
			
		||||
  return list;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Find the active window in order to collect stats */
 | 
			
		||||
void
 | 
			
		||||
get_active_app_properties (ShellAppMonitor *monitor,
 | 
			
		||||
                           char           **wm_class,
 | 
			
		||||
                           char           **title)
 | 
			
		||||
/**
 | 
			
		||||
 * shell_app_monitor_get_running_app_ids:
 | 
			
		||||
 *
 | 
			
		||||
 * @monitor: An app monitor instance
 | 
			
		||||
 *
 | 
			
		||||
 * 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;
 | 
			
		||||
  GHashTable *app_active_times = NULL; /* last active time for an application */
 | 
			
		||||
  MetaScreen *screen;
 | 
			
		||||
  MetaDisplay *display;
 | 
			
		||||
  MetaWindow *active;
 | 
			
		||||
  int activity;
 | 
			
		||||
  guint32 timestamp;
 | 
			
		||||
 | 
			
		||||
  global = shell_global_get ();
 | 
			
		||||
  g_object_get (global, "screen", &screen, NULL);
 | 
			
		||||
@@ -317,60 +576,14 @@ get_active_app_properties (ShellAppMonitor *monitor,
 | 
			
		||||
 | 
			
		||||
  active = meta_display_get_focus_window (display);
 | 
			
		||||
 | 
			
		||||
  if (wm_class)
 | 
			
		||||
    *wm_class = NULL;
 | 
			
		||||
  if (title)
 | 
			
		||||
    *title = NULL;
 | 
			
		||||
 | 
			
		||||
  if (active == NULL)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  *wm_class = g_strdup (meta_window_get_wm_class (active));
 | 
			
		||||
  g_object_get (active, "title", title, NULL);
 | 
			
		||||
}
 | 
			
		||||
  wm_class = get_cleaned_wmclass_for_window (active);
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
    return;
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
  app_active_times = g_hash_table_lookup (monitor->apps_by_wm_class, wm_class);
 | 
			
		||||
  if (!app_active_times)
 | 
			
		||||
    {
 | 
			
		||||
 
 | 
			
		||||
@@ -40,9 +40,10 @@ GSList *shell_app_monitor_get_most_used_apps (ShellAppMonitor *monitor,
 | 
			
		||||
                                              int              activity,
 | 
			
		||||
                                              gint             number);
 | 
			
		||||
 | 
			
		||||
guint shell_app_monitor_get_window_count (ShellAppMonitor *monitor, const char *appid);
 | 
			
		||||
 | 
			
		||||
/* Get whatever's running right now */
 | 
			
		||||
GSList *shell_app_monitor_get_running_apps (ShellAppMonitor *monitor,
 | 
			
		||||
                                            int              activity);
 | 
			
		||||
GList *shell_app_monitor_get_running_app_ids (ShellAppMonitor *monitor);
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,19 +1,25 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
 | 
			
		||||
#include "shell-app-system.h"
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include <gio/gio.h>
 | 
			
		||||
#include <gconf/gconf.h>
 | 
			
		||||
#include <gconf/gconf-client.h>
 | 
			
		||||
 | 
			
		||||
#define GMENU_I_KNOW_THIS_IS_UNSTABLE
 | 
			
		||||
#include <gmenu-tree.h>
 | 
			
		||||
 | 
			
		||||
#define SHELL_APP_FAVORITES_KEY "/desktop/gnome/shell/favorite_apps"
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
   PROP_0,
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
  CHANGED,
 | 
			
		||||
  INSTALLED_CHANGED,
 | 
			
		||||
  FAVORITES_CHANGED,
 | 
			
		||||
  LAST_SIGNAL
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -26,11 +32,17 @@ struct _ShellAppSystemPrivate {
 | 
			
		||||
  GSList *cached_app_menus; /* ShellAppMenuEntry */
 | 
			
		||||
 | 
			
		||||
  GSList *cached_setting_ids; /* utf8 */
 | 
			
		||||
 | 
			
		||||
  GHashTable *cached_favorites; /* <utf8,integer> */
 | 
			
		||||
 | 
			
		||||
  gint app_monitor_id;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void shell_app_system_finalize (GObject *object);
 | 
			
		||||
static void on_tree_changed (GMenuTree *tree, gpointer user_data);
 | 
			
		||||
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);
 | 
			
		||||
 | 
			
		||||
@@ -63,14 +75,22 @@ static void shell_app_system_class_init(ShellAppSystemClass *klass)
 | 
			
		||||
 | 
			
		||||
  gobject_class->finalize = shell_app_system_finalize;
 | 
			
		||||
 | 
			
		||||
  signals[CHANGED] =
 | 
			
		||||
    g_signal_new ("changed",
 | 
			
		||||
  signals[INSTALLED_CHANGED] =
 | 
			
		||||
    g_signal_new ("installed-changed",
 | 
			
		||||
		  SHELL_TYPE_APP_SYSTEM,
 | 
			
		||||
		  G_SIGNAL_RUN_LAST,
 | 
			
		||||
		  G_STRUCT_OFFSET (ShellAppSystemClass, changed),
 | 
			
		||||
		  G_STRUCT_OFFSET (ShellAppSystemClass, installed_changed),
 | 
			
		||||
		  NULL, NULL,
 | 
			
		||||
		  g_cclosure_marshal_VOID__VOID,
 | 
			
		||||
		  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));
 | 
			
		||||
}
 | 
			
		||||
@@ -79,10 +99,16 @@ static void
 | 
			
		||||
shell_app_system_init (ShellAppSystem *self)
 | 
			
		||||
{
 | 
			
		||||
  ShellAppSystemPrivate *priv;
 | 
			
		||||
  GConfClient *client;
 | 
			
		||||
 | 
			
		||||
  self->priv = priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
 | 
			
		||||
                                                   SHELL_TYPE_APP_SYSTEM,
 | 
			
		||||
                                                   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->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);
 | 
			
		||||
 | 
			
		||||
  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
 | 
			
		||||
@@ -112,13 +144,16 @@ shell_app_system_finalize (GObject *object)
 | 
			
		||||
  g_slist_free (priv->cached_setting_ids);
 | 
			
		||||
  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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
reread_directories (ShellAppSystem *self, GSList **cache, GMenuTree *tree)
 | 
			
		||||
{
 | 
			
		||||
  ShellAppSystemPrivate *priv = self->priv;
 | 
			
		||||
  GMenuTreeDirectory *trunk;
 | 
			
		||||
  GSList *entries;
 | 
			
		||||
  GSList *iter;
 | 
			
		||||
@@ -228,11 +263,58 @@ on_tree_changed (GMenuTree *monitor, gpointer 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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
shell_app_menu_entry_get_type (void)
 | 
			
		||||
{
 | 
			
		||||
@@ -315,3 +397,160 @@ shell_app_system_get_default ()
 | 
			
		||||
 | 
			
		||||
  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;
 | 
			
		||||
 | 
			
		||||
  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;
 | 
			
		||||
@@ -43,8 +44,16 @@ struct _ShellAppMenuEntry {
 | 
			
		||||
 | 
			
		||||
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_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__ */
 | 
			
		||||
 
 | 
			
		||||
@@ -101,7 +101,7 @@ shell_global_get_property(GObject         *object,
 | 
			
		||||
      g_value_set_object (value, mutter_plugin_get_overlay_group (global->plugin));
 | 
			
		||||
      break;
 | 
			
		||||
    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;
 | 
			
		||||
    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_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:
 | 
			
		||||
 *
 | 
			
		||||
@@ -933,6 +944,55 @@ shell_global_create_vertical_gradient (ClutterColor *top,
 | 
			
		||||
  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
 | 
			
		||||
 * with a warning.
 | 
			
		||||
 
 | 
			
		||||
@@ -48,6 +48,8 @@ ClutterActor *shell_get_event_related(ClutterEvent *event);
 | 
			
		||||
 | 
			
		||||
ShellGlobal *shell_global_get (void);
 | 
			
		||||
 | 
			
		||||
MetaScreen *shell_global_get_screen (ShellGlobal  *global);
 | 
			
		||||
 | 
			
		||||
void shell_global_grab_dbus_service (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,
 | 
			
		||||
							    ClutterColor *bottom);
 | 
			
		||||
 | 
			
		||||
ClutterCairoTexture *shell_global_create_horizontal_gradient (ClutterColor *left,
 | 
			
		||||
							      ClutterColor *right);
 | 
			
		||||
 | 
			
		||||
ClutterActor *shell_global_create_root_pixmap_actor (ShellGlobal *global);
 | 
			
		||||
 | 
			
		||||
void shell_global_clutter_cairo_texture_draw_clock (ClutterCairoTexture *texture,
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user