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