Compare commits
	
		
			116 Commits
		
	
	
		
			issue267
			...
			wip/cherge
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					7f7965d622 | ||
| 
						 | 
					92cfb9ab1b | ||
| 
						 | 
					f3082a3683 | ||
| 
						 | 
					24f400d28a | ||
| 
						 | 
					4cac5b4b28 | ||
| 
						 | 
					b48e95cba2 | ||
| 
						 | 
					5ccf92e804 | ||
| 
						 | 
					2040c380bd | ||
| 
						 | 
					4e22989f07 | ||
| 
						 | 
					cfb92ad392 | ||
| 
						 | 
					f87b9f374a | ||
| 
						 | 
					2c549bfbbe | ||
| 
						 | 
					f597a0a11c | ||
| 
						 | 
					3f35ad0cbf | ||
| 
						 | 
					bd3227e23f | ||
| 
						 | 
					04f847a3c2 | ||
| 
						 | 
					41fe2d2c01 | ||
| 
						 | 
					161beb71eb | ||
| 
						 | 
					13ec3169a6 | ||
| 
						 | 
					8702d6647b | ||
| 
						 | 
					5703a25e2b | ||
| 
						 | 
					09fbb4a127 | ||
| 
						 | 
					4c7b20e584 | ||
| 
						 | 
					b3045cb964 | ||
| 
						 | 
					c41175af45 | ||
| 
						 | 
					7b1544a7a2 | ||
| 
						 | 
					a0f1ac87e9 | ||
| 
						 | 
					1045b35c8b | ||
| 
						 | 
					24cdcc56da | ||
| 
						 | 
					1b28cdfbf4 | ||
| 
						 | 
					a73294312f | ||
| 
						 | 
					5e7a7e31a1 | ||
| 
						 | 
					8111286463 | ||
| 
						 | 
					06c6ecc15b | ||
| 
						 | 
					36f9dcd2bd | ||
| 
						 | 
					219118e633 | ||
| 
						 | 
					1e929357e0 | ||
| 
						 | 
					e7463e38ca | ||
| 
						 | 
					420c1cbfd1 | ||
| 
						 | 
					d53bd98532 | ||
| 
						 | 
					128a501b9a | ||
| 
						 | 
					b29e243fec | ||
| 
						 | 
					fa2ddcc52f | ||
| 
						 | 
					fbf194f6a1 | ||
| 
						 | 
					5610a2435d | ||
| 
						 | 
					a5b36fc7f4 | ||
| 
						 | 
					923d80bba8 | ||
| 
						 | 
					9e196d2765 | ||
| 
						 | 
					94897492be | ||
| 
						 | 
					6baf82eb83 | ||
| 
						 | 
					65d27aaa43 | ||
| 
						 | 
					176aaa4a97 | ||
| 
						 | 
					5ae5811155 | ||
| 
						 | 
					e027af9548 | ||
| 
						 | 
					73649a0d6a | ||
| 
						 | 
					7dbcd26619 | ||
| 
						 | 
					f30ec4a4c8 | ||
| 
						 | 
					c04289853f | ||
| 
						 | 
					b72b773d87 | ||
| 
						 | 
					da7cd2807f | ||
| 
						 | 
					20373ba64e | ||
| 
						 | 
					025f6eb68e | ||
| 
						 | 
					dc5df5c4c9 | ||
| 
						 | 
					81db908339 | ||
| 
						 | 
					706a2259b8 | ||
| 
						 | 
					e94af71430 | ||
| 
						 | 
					a662e7bb87 | ||
| 
						 | 
					0b82388c49 | ||
| 
						 | 
					b359b937e9 | ||
| 
						 | 
					98fb7c33f2 | ||
| 
						 | 
					4dfc2e0fd1 | ||
| 
						 | 
					9152d3a286 | ||
| 
						 | 
					ba33a05dd2 | ||
| 
						 | 
					ddb309815c | ||
| 
						 | 
					6a796675bd | ||
| 
						 | 
					d08497414f | ||
| 
						 | 
					82886b7ee8 | ||
| 
						 | 
					dca43c7b24 | ||
| 
						 | 
					af50a7829f | ||
| 
						 | 
					67cb02d46a | ||
| 
						 | 
					721ce54037 | ||
| 
						 | 
					445eed40a7 | ||
| 
						 | 
					fddd122956 | ||
| 
						 | 
					df1b46eee2 | ||
| 
						 | 
					bf318df7f3 | ||
| 
						 | 
					2a2f3c981e | ||
| 
						 | 
					8e5eab0498 | ||
| 
						 | 
					6ed21e1ce0 | ||
| 
						 | 
					9c51c87d8c | ||
| 
						 | 
					db2245d60b | ||
| 
						 | 
					f26cc3ac23 | ||
| 
						 | 
					02c5b4b947 | ||
| 
						 | 
					df57829ea1 | ||
| 
						 | 
					da96408098 | ||
| 
						 | 
					4b2e0247af | ||
| 
						 | 
					2c617e5a3a | ||
| 
						 | 
					4ff7e84c51 | ||
| 
						 | 
					9f76b6e4a2 | ||
| 
						 | 
					0ac0f7e85b | ||
| 
						 | 
					73b00ff1a7 | ||
| 
						 | 
					a52597ac5b | ||
| 
						 | 
					9a2597f80b | ||
| 
						 | 
					e1ed4b25e1 | ||
| 
						 | 
					c70b18764b | ||
| 
						 | 
					4398516520 | ||
| 
						 | 
					220514d10e | ||
| 
						 | 
					18312d9ccd | ||
| 
						 | 
					234b1441e4 | ||
| 
						 | 
					e909db5848 | ||
| 
						 | 
					702338bc7d | ||
| 
						 | 
					7c9dbc66d9 | ||
| 
						 | 
					0d031dc20f | ||
| 
						 | 
					b476e851b7 | ||
| 
						 | 
					a27be6a540 | ||
| 
						 | 
					4b6a57fabe | ||
| 
						 | 
					92758890bb | 
							
								
								
									
										2
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							@@ -1,3 +1,3 @@
 | 
			
		||||
[submodule "subprojects/gvc"]
 | 
			
		||||
	path = subprojects/gvc
 | 
			
		||||
	url = https://git.gnome.org/browse/libgnome-volume-control
 | 
			
		||||
	url = https://gitlab.gnome.org/GNOME/libgnome-volume-control.git
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										57
									
								
								NEWS
									
									
									
									
									
								
							
							
						
						
									
										57
									
								
								NEWS
									
									
									
									
									
								
							@@ -1,16 +1,57 @@
 | 
			
		||||
3.29.1
 | 
			
		||||
3.28.4
 | 
			
		||||
======
 | 
			
		||||
* Support icons in app-menu [Florian; #760985]
 | 
			
		||||
* Misc. bug fixes [Marco, Florian, Lubomir; #792687, #221, !63]
 | 
			
		||||
* Fix wrong window positions in overview on wayland [Marco; #776588]
 | 
			
		||||
* overview: Fix handling of confirmation dialogs on wayland [verdre; !180]
 | 
			
		||||
* Avoid some full relayout/redraws [Carlos; !197]
 | 
			
		||||
* Keep workspace switcher slid out when workspaces are in use [Florian; !161]
 | 
			
		||||
* Cancel search on overview hiding [Marco; !205]
 | 
			
		||||
* Fix disappearing network icon [Iain; #140]
 | 
			
		||||
* Improve performance of app icon animations [Daniel; !253]
 | 
			
		||||
* notifications: Support icon theme names in 'image-path' hint [Marco; !285]
 | 
			
		||||
* Avoid focus changes when updating keyboard options [Takao; #391]
 | 
			
		||||
* Fix unresponsive-app dialog blocking input in other windows [Florian; #273]
 | 
			
		||||
* Fix ellipsization in dialog subtitles/bodies [Marco; !531]
 | 
			
		||||
* Misc. bug fixes [Marco, Andrea, Florian, Jasper, Sam, verdre, Jonas,
 | 
			
		||||
  Cosimo, Carlos; #792681, #372, !112, !162, #414, #663461, #788882, #787260,
 | 
			
		||||
  !188, #791233, #602, #632, !305, !286, !314, #781, #693, #618, #430, #799,
 | 
			
		||||
  #783, !293, #298, #1015, #539, #1270]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
  Piotr Drąg, Takao Fujiwara, Christian Kellner, Florian Müllner,
 | 
			
		||||
  Mario Sanchez Prada, Lubomir Rintel, Didier Roche, Marco Trevisan (Treviño),
 | 
			
		||||
  verdre
 | 
			
		||||
  Jonas Ådahl, Andrea Azzarone, Cosimo Cecchi, Takao Fujiwara, Carlos Garnacho,
 | 
			
		||||
  Iain Lane, Florian Müllner, Georges Basile Stavracas Neto, Jasper St. Pierre,
 | 
			
		||||
  Sam Spilsbury, Ray Strode, Will Thompson, Marco Trevisan (Treviño), verdre,
 | 
			
		||||
  Daniel van Vugt
 | 
			
		||||
 | 
			
		||||
Translators:
 | 
			
		||||
  gogo [hr], Stas Solovey [ru], Matej Urbančič [sl], Daniel Șerbănescu [ro],
 | 
			
		||||
  Fabio Tomat [fur], Marek Cernocky [cs], Daniel Mustieles [es]
 | 
			
		||||
  Marek Černocký [cs]
 | 
			
		||||
 | 
			
		||||
3.28.3
 | 
			
		||||
======
 | 
			
		||||
* Fix lagging pointer when zoomed [Daniel; #682013]
 | 
			
		||||
* Fix "Clear All" for calendar events [Florian; #325]
 | 
			
		||||
* Misc. bug fixes [Florian, Mario, Marco; #136, #214, #788931, #791233]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
  Carlos Garnacho, Florian Müllner, Mario Sanchez Prada, Joe Rabinoff,
 | 
			
		||||
  Didier Roche, Marco Trevisan (Treviño), Daniel van Vugt
 | 
			
		||||
 | 
			
		||||
Translators:
 | 
			
		||||
  Pieter Schalk Schoeman [af], Gun Chleoc [gd]
 | 
			
		||||
 | 
			
		||||
3.28.2
 | 
			
		||||
======
 | 
			
		||||
* Fix lock-up on cancelling polkit dialog [Florian; #221]
 | 
			
		||||
* Guard against untimely keyboard map changes [Carlos; #240]
 | 
			
		||||
* Fix blurriness of OSD under some resolutions [Silvère; #782011]
 | 
			
		||||
* Fix icons in search provider results [Florian; #249]
 | 
			
		||||
* Misc. bug fixes [Marco, Florian; #792687, #781471]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
  Carlos Garnacho, Silvère Latchurié, Florian Müllner, Mario Sanchez Prada,
 | 
			
		||||
  Ray Strode, Marco Trevisan (Treviño)
 | 
			
		||||
 | 
			
		||||
Translators:
 | 
			
		||||
  Stas Solovey [ru], Rafael Fontenelle [pt_BR]
 | 
			
		||||
 | 
			
		||||
3.28.1
 | 
			
		||||
======
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,7 @@
 | 
			
		||||
    <file>be.json</file>
 | 
			
		||||
    <file>bg.json</file>
 | 
			
		||||
    <file>by.json</file>
 | 
			
		||||
    <file>ca.json</file>
 | 
			
		||||
    <file>cz.json</file>
 | 
			
		||||
    <file>de.json</file>
 | 
			
		||||
    <file>dk.json</file>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										599
									
								
								data/osk-layouts/ca.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										599
									
								
								data/osk-layouts/ca.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,599 @@
 | 
			
		||||
{
 | 
			
		||||
  "levels": [
 | 
			
		||||
    {
 | 
			
		||||
      "level": "",
 | 
			
		||||
      "mode": "default",
 | 
			
		||||
      "rows": [
 | 
			
		||||
        [
 | 
			
		||||
          [
 | 
			
		||||
            "q"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "w"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "e",
 | 
			
		||||
            "é",
 | 
			
		||||
            "è",
 | 
			
		||||
            "ê",
 | 
			
		||||
            "ë",
 | 
			
		||||
            "%",
 | 
			
		||||
            "ę",
 | 
			
		||||
            "ė",
 | 
			
		||||
            "ē"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "r"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "t"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "y",
 | 
			
		||||
            "%",
 | 
			
		||||
            "ÿ"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "u",
 | 
			
		||||
            "ù",
 | 
			
		||||
            "û",
 | 
			
		||||
            "%",
 | 
			
		||||
            "ü",
 | 
			
		||||
            "ú",
 | 
			
		||||
            "ū"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "i",
 | 
			
		||||
            "î",
 | 
			
		||||
            "%",
 | 
			
		||||
            "ï",
 | 
			
		||||
            "ì",
 | 
			
		||||
            "í",
 | 
			
		||||
            "į",
 | 
			
		||||
            "ī"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "o",
 | 
			
		||||
            "ô",
 | 
			
		||||
            "œ",
 | 
			
		||||
            "%",
 | 
			
		||||
            "ö",
 | 
			
		||||
            "ò",
 | 
			
		||||
            "ó",
 | 
			
		||||
            "õ",
 | 
			
		||||
            "ø",
 | 
			
		||||
            "ō",
 | 
			
		||||
            "º"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "p"
 | 
			
		||||
          ]
 | 
			
		||||
        ],
 | 
			
		||||
        [
 | 
			
		||||
          [
 | 
			
		||||
            "a",
 | 
			
		||||
            "à",
 | 
			
		||||
            "â",
 | 
			
		||||
            "%",
 | 
			
		||||
            "æ",
 | 
			
		||||
            "á",
 | 
			
		||||
            "ä",
 | 
			
		||||
            "ã",
 | 
			
		||||
            "å",
 | 
			
		||||
            "ā",
 | 
			
		||||
            "ª"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "s"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "d"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "f"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "g"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "h"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "j"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "k"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "l"
 | 
			
		||||
          ]
 | 
			
		||||
        ],
 | 
			
		||||
        [
 | 
			
		||||
          [
 | 
			
		||||
            "z"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "x"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "c",
 | 
			
		||||
            "ç",
 | 
			
		||||
            "ć",
 | 
			
		||||
            "č"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "v"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "b"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "n"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "m"
 | 
			
		||||
          ]
 | 
			
		||||
        ],
 | 
			
		||||
        [
 | 
			
		||||
          [
 | 
			
		||||
            ","
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            " "
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            ".",
 | 
			
		||||
            "#",
 | 
			
		||||
            "!",
 | 
			
		||||
            ",",
 | 
			
		||||
            "?",
 | 
			
		||||
            "-",
 | 
			
		||||
            ":",
 | 
			
		||||
            "'",
 | 
			
		||||
            "@"
 | 
			
		||||
          ]
 | 
			
		||||
        ]
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "level": "shift",
 | 
			
		||||
      "mode": "latched",
 | 
			
		||||
      "rows": [
 | 
			
		||||
        [
 | 
			
		||||
          [
 | 
			
		||||
            "Q"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "W"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "E",
 | 
			
		||||
            "É",
 | 
			
		||||
            "È",
 | 
			
		||||
            "Ê",
 | 
			
		||||
            "Ë",
 | 
			
		||||
            "%",
 | 
			
		||||
            "Ę",
 | 
			
		||||
            "Ė",
 | 
			
		||||
            "Ē"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "R"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "T"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "Y",
 | 
			
		||||
            "%",
 | 
			
		||||
            "Ÿ"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "U",
 | 
			
		||||
            "Ù",
 | 
			
		||||
            "Û",
 | 
			
		||||
            "%",
 | 
			
		||||
            "Ü",
 | 
			
		||||
            "Ú",
 | 
			
		||||
            "Ū"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "I",
 | 
			
		||||
            "Î",
 | 
			
		||||
            "%",
 | 
			
		||||
            "Ï",
 | 
			
		||||
            "Ì",
 | 
			
		||||
            "Í",
 | 
			
		||||
            "Į",
 | 
			
		||||
            "Ī"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "O",
 | 
			
		||||
            "Ô",
 | 
			
		||||
            "Œ",
 | 
			
		||||
            "%",
 | 
			
		||||
            "Ö",
 | 
			
		||||
            "Ò",
 | 
			
		||||
            "Ó",
 | 
			
		||||
            "Õ",
 | 
			
		||||
            "Ø",
 | 
			
		||||
            "Ō",
 | 
			
		||||
            "º"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "P"
 | 
			
		||||
          ]
 | 
			
		||||
        ],
 | 
			
		||||
        [
 | 
			
		||||
          [
 | 
			
		||||
            "A",
 | 
			
		||||
            "À",
 | 
			
		||||
            "Â",
 | 
			
		||||
            "%",
 | 
			
		||||
            "Æ",
 | 
			
		||||
            "Á",
 | 
			
		||||
            "Ä",
 | 
			
		||||
            "Ã",
 | 
			
		||||
            "Å",
 | 
			
		||||
            "Ā",
 | 
			
		||||
            "ª"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "S"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "D"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "F"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "G"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "H"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "J"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "K"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "L"
 | 
			
		||||
          ]
 | 
			
		||||
        ],
 | 
			
		||||
        [
 | 
			
		||||
          [
 | 
			
		||||
            "Z"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "X"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "C",
 | 
			
		||||
            "Ç",
 | 
			
		||||
            "Ć",
 | 
			
		||||
            "Č"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "V"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "B"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "N"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "M"
 | 
			
		||||
          ]
 | 
			
		||||
        ],
 | 
			
		||||
        [
 | 
			
		||||
          [
 | 
			
		||||
            ","
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            " "
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            ".",
 | 
			
		||||
            "#",
 | 
			
		||||
            "!",
 | 
			
		||||
            ",",
 | 
			
		||||
            "?",
 | 
			
		||||
            "-",
 | 
			
		||||
            ":",
 | 
			
		||||
            "'",
 | 
			
		||||
            "@"
 | 
			
		||||
          ]
 | 
			
		||||
        ]
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "level": "opt",
 | 
			
		||||
      "mode": "locked",
 | 
			
		||||
      "rows": [
 | 
			
		||||
        [
 | 
			
		||||
          [
 | 
			
		||||
            "1",
 | 
			
		||||
            "¹",
 | 
			
		||||
            "½",
 | 
			
		||||
            "⅓",
 | 
			
		||||
            "¼",
 | 
			
		||||
            "⅛"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "2",
 | 
			
		||||
            "²",
 | 
			
		||||
            "⅔"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "3",
 | 
			
		||||
            "³",
 | 
			
		||||
            "¾",
 | 
			
		||||
            "⅜"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "4",
 | 
			
		||||
            "⁴"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "5",
 | 
			
		||||
            "⅝"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "6"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "7",
 | 
			
		||||
            "⅞"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "8"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "9"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "0",
 | 
			
		||||
            "ⁿ",
 | 
			
		||||
            "∅"
 | 
			
		||||
          ]
 | 
			
		||||
        ],
 | 
			
		||||
        [
 | 
			
		||||
          [
 | 
			
		||||
            "@"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "#"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "$",
 | 
			
		||||
            "¢",
 | 
			
		||||
            "£",
 | 
			
		||||
            "€",
 | 
			
		||||
            "¥",
 | 
			
		||||
            "₱"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "%",
 | 
			
		||||
            "‰"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "&"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "-",
 | 
			
		||||
            "_",
 | 
			
		||||
            "–",
 | 
			
		||||
            "—",
 | 
			
		||||
            "·"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "+",
 | 
			
		||||
            "±"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "(",
 | 
			
		||||
            "<",
 | 
			
		||||
            "{",
 | 
			
		||||
            "["
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            ")",
 | 
			
		||||
            ">",
 | 
			
		||||
            "}",
 | 
			
		||||
            "]"
 | 
			
		||||
          ]
 | 
			
		||||
        ],
 | 
			
		||||
        [
 | 
			
		||||
          [
 | 
			
		||||
            "*",
 | 
			
		||||
            "†",
 | 
			
		||||
            "‡",
 | 
			
		||||
            "★"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "\"",
 | 
			
		||||
            "“",
 | 
			
		||||
            "”",
 | 
			
		||||
            "«",
 | 
			
		||||
            "»"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "'",
 | 
			
		||||
            "‘",
 | 
			
		||||
            "’",
 | 
			
		||||
            "‹",
 | 
			
		||||
            "›"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            ":"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            ";"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "!",
 | 
			
		||||
            "¡"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "?",
 | 
			
		||||
            "¿"
 | 
			
		||||
          ]
 | 
			
		||||
        ],
 | 
			
		||||
        [
 | 
			
		||||
          [
 | 
			
		||||
            "_"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "/"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            " "
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            ","
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            ".",
 | 
			
		||||
            "…"
 | 
			
		||||
          ]
 | 
			
		||||
        ]
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "level": "opt+shift",
 | 
			
		||||
      "mode": "locked",
 | 
			
		||||
      "rows": [
 | 
			
		||||
        [
 | 
			
		||||
          [
 | 
			
		||||
            "~"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "`"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "|"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "•",
 | 
			
		||||
            "♪",
 | 
			
		||||
            "♥",
 | 
			
		||||
            "♠",
 | 
			
		||||
            "♦",
 | 
			
		||||
            "♣"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "√"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "Π",
 | 
			
		||||
            "π"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "÷"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "×"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "¶",
 | 
			
		||||
            "§"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "∆"
 | 
			
		||||
          ]
 | 
			
		||||
        ],
 | 
			
		||||
        [
 | 
			
		||||
          [
 | 
			
		||||
            "£"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "¢"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "€"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "¥"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "^",
 | 
			
		||||
            "↑",
 | 
			
		||||
            "↓",
 | 
			
		||||
            "←",
 | 
			
		||||
            "→"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "°",
 | 
			
		||||
            "′",
 | 
			
		||||
            "″"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "=",
 | 
			
		||||
            "≠",
 | 
			
		||||
            "≈",
 | 
			
		||||
            "∞"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "{"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "}"
 | 
			
		||||
          ]
 | 
			
		||||
        ],
 | 
			
		||||
        [
 | 
			
		||||
          [
 | 
			
		||||
            "\\"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "©"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "®"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "™"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "℅"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "["
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "]"
 | 
			
		||||
          ]
 | 
			
		||||
        ],
 | 
			
		||||
        [
 | 
			
		||||
          [
 | 
			
		||||
            "<",
 | 
			
		||||
            "‹",
 | 
			
		||||
            "≤",
 | 
			
		||||
            "«"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            ">",
 | 
			
		||||
            "›",
 | 
			
		||||
            "≥",
 | 
			
		||||
            "»"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            " "
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            ","
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            ".",
 | 
			
		||||
            "…"
 | 
			
		||||
          ]
 | 
			
		||||
        ]
 | 
			
		||||
      ]
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
  "locale": "fr-CA",
 | 
			
		||||
  "name": "French Canada"
 | 
			
		||||
}
 | 
			
		||||
@@ -6,10 +6,20 @@
 | 
			
		||||
      "rows": [
 | 
			
		||||
        [
 | 
			
		||||
          [
 | 
			
		||||
            "q"
 | 
			
		||||
            "a",
 | 
			
		||||
            "à",
 | 
			
		||||
            "â",
 | 
			
		||||
            "%",
 | 
			
		||||
            "æ",
 | 
			
		||||
            "á",
 | 
			
		||||
            "ä",
 | 
			
		||||
            "ã",
 | 
			
		||||
            "å",
 | 
			
		||||
            "ā",
 | 
			
		||||
            "ª"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "w"
 | 
			
		||||
            "z"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "e",
 | 
			
		||||
@@ -71,17 +81,7 @@
 | 
			
		||||
        ],
 | 
			
		||||
        [
 | 
			
		||||
          [
 | 
			
		||||
            "a",
 | 
			
		||||
            "à",
 | 
			
		||||
            "â",
 | 
			
		||||
            "%",
 | 
			
		||||
            "æ",
 | 
			
		||||
            "á",
 | 
			
		||||
            "ä",
 | 
			
		||||
            "ã",
 | 
			
		||||
            "å",
 | 
			
		||||
            "ā",
 | 
			
		||||
            "ª"
 | 
			
		||||
            "q"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "s"
 | 
			
		||||
@@ -106,11 +106,14 @@
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "l"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "m"
 | 
			
		||||
          ]
 | 
			
		||||
        ],
 | 
			
		||||
        [
 | 
			
		||||
          [
 | 
			
		||||
            "z"
 | 
			
		||||
            "w"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "x"
 | 
			
		||||
@@ -131,7 +134,11 @@
 | 
			
		||||
            "n"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "m"
 | 
			
		||||
            "'",
 | 
			
		||||
            "‘",
 | 
			
		||||
            "’",
 | 
			
		||||
            "‹",
 | 
			
		||||
            "›"
 | 
			
		||||
          ]
 | 
			
		||||
        ],
 | 
			
		||||
        [
 | 
			
		||||
@@ -161,10 +168,20 @@
 | 
			
		||||
      "rows": [
 | 
			
		||||
        [
 | 
			
		||||
          [
 | 
			
		||||
            "Q"
 | 
			
		||||
            "A",
 | 
			
		||||
            "À",
 | 
			
		||||
            "Â",
 | 
			
		||||
            "%",
 | 
			
		||||
            "Æ",
 | 
			
		||||
            "Á",
 | 
			
		||||
            "Ä",
 | 
			
		||||
            "Ã",
 | 
			
		||||
            "Å",
 | 
			
		||||
            "Ā",
 | 
			
		||||
            "ª"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "W"
 | 
			
		||||
            "Z"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "E",
 | 
			
		||||
@@ -226,17 +243,7 @@
 | 
			
		||||
        ],
 | 
			
		||||
        [
 | 
			
		||||
          [
 | 
			
		||||
            "A",
 | 
			
		||||
            "À",
 | 
			
		||||
            "Â",
 | 
			
		||||
            "%",
 | 
			
		||||
            "Æ",
 | 
			
		||||
            "Á",
 | 
			
		||||
            "Ä",
 | 
			
		||||
            "Ã",
 | 
			
		||||
            "Å",
 | 
			
		||||
            "Ā",
 | 
			
		||||
            "ª"
 | 
			
		||||
            "Q"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "S"
 | 
			
		||||
@@ -261,11 +268,14 @@
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "L"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "M"
 | 
			
		||||
          ]
 | 
			
		||||
        ],
 | 
			
		||||
        [
 | 
			
		||||
          [
 | 
			
		||||
            "Z"
 | 
			
		||||
            "W"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "X"
 | 
			
		||||
@@ -286,7 +296,11 @@
 | 
			
		||||
            "N"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "M"
 | 
			
		||||
            "'",
 | 
			
		||||
            "‘",
 | 
			
		||||
            "’",
 | 
			
		||||
            "‹",
 | 
			
		||||
            "›"
 | 
			
		||||
          ]
 | 
			
		||||
        ],
 | 
			
		||||
        [
 | 
			
		||||
@@ -369,10 +383,10 @@
 | 
			
		||||
            "#"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "$",
 | 
			
		||||
            "€",
 | 
			
		||||
            "¢",
 | 
			
		||||
            "£",
 | 
			
		||||
            "€",
 | 
			
		||||
            "$",
 | 
			
		||||
            "¥",
 | 
			
		||||
            "₱"
 | 
			
		||||
          ],
 | 
			
		||||
@@ -511,13 +525,14 @@
 | 
			
		||||
            "£"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "¥"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "$",
 | 
			
		||||
            "¢"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "€"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "¥"
 | 
			
		||||
            "¢"
 | 
			
		||||
          ],
 | 
			
		||||
          [
 | 
			
		||||
            "^",
 | 
			
		||||
@@ -594,6 +609,6 @@
 | 
			
		||||
      ]
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
  "locale": "fr-CA",
 | 
			
		||||
  "name": "French Canada"
 | 
			
		||||
  "locale": "fr",
 | 
			
		||||
  "name": "French"
 | 
			
		||||
}
 | 
			
		||||
@@ -1788,19 +1788,20 @@ StScrollBar {
 | 
			
		||||
  .login-dialog-user-list-view { -st-vfade-offset: 1em; }
 | 
			
		||||
  .login-dialog-user-list {
 | 
			
		||||
    spacing: 12px;
 | 
			
		||||
    padding: .2em;
 | 
			
		||||
    width: 23em;
 | 
			
		||||
    &:expanded .login-dialog-user-list-item:selected { background-color: $selected_bg_color; color: $selected_fg_color; }
 | 
			
		||||
    &:expanded .login-dialog-user-list-item:logged-in { border-right: 2px solid $selected_bg_color; }
 | 
			
		||||
  }
 | 
			
		||||
  .login-dialog-user-list-item {
 | 
			
		||||
    border-radius: 5px;
 | 
			
		||||
    padding: 6px;
 | 
			
		||||
    padding: .2em;
 | 
			
		||||
    color: darken($osd_fg_color,30%);
 | 
			
		||||
    &:ltr .user-widget { padding-right: 1em; }
 | 
			
		||||
    &:rtl .user-widget { padding-left: 1em; }
 | 
			
		||||
    &:ltr { padding-right: 1em; }
 | 
			
		||||
    &:rtl { padding-left: 1em; }
 | 
			
		||||
    .login-dialog-timed-login-indicator {
 | 
			
		||||
      height: 2px;
 | 
			
		||||
      margin-top: 6px;
 | 
			
		||||
      margin: 2px 0 0 0;
 | 
			
		||||
      background-color: $osd_fg_color;
 | 
			
		||||
    }
 | 
			
		||||
    &:focus .login-dialog-timed-login-indicator { background-color: $selected_fg_color; }
 | 
			
		||||
@@ -1815,8 +1816,8 @@ StScrollBar {
 | 
			
		||||
    padding-left: 15px;
 | 
			
		||||
  }
 | 
			
		||||
    .user-widget-label {
 | 
			
		||||
      &:ltr { padding-left: 14px; }
 | 
			
		||||
      &:rtl { padding-right: 14px; }
 | 
			
		||||
      &:ltr { padding-left: 18px; }
 | 
			
		||||
      &:rtl { padding-right: 18px; }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  .login-dialog-prompt-layout {
 | 
			
		||||
 
 | 
			
		||||
@@ -242,11 +242,11 @@ var AuthPrompt = new Lang.Class({
 | 
			
		||||
        this.emit('prompted');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onVerificationFailed() {
 | 
			
		||||
    _onVerificationFailed(userVerifier, canRetry) {
 | 
			
		||||
        this._queryingService = null;
 | 
			
		||||
        this.clear();
 | 
			
		||||
 | 
			
		||||
        this.updateSensitivity(true);
 | 
			
		||||
        this.updateSensitivity(canRetry);
 | 
			
		||||
        this.setActorInDefaultButtonWell(null);
 | 
			
		||||
        this.verificationStatus = AuthPromptStatus.VERIFICATION_FAILED;
 | 
			
		||||
    },
 | 
			
		||||
@@ -439,6 +439,7 @@ var AuthPrompt = new Lang.Class({
 | 
			
		||||
        this.verificationStatus = AuthPromptStatus.NOT_VERIFYING;
 | 
			
		||||
        this.cancelButton.reactive = true;
 | 
			
		||||
        this.nextButton.label = _("Next");
 | 
			
		||||
        this._preemptiveAnswer = null;
 | 
			
		||||
 | 
			
		||||
        if (this._userVerifier)
 | 
			
		||||
            this._userVerifier.cancel();
 | 
			
		||||
 
 | 
			
		||||
@@ -25,6 +25,7 @@ const GLib = imports.gi.GLib;
 | 
			
		||||
const GObject = imports.gi.GObject;
 | 
			
		||||
const Gtk = imports.gi.Gtk;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Mainloop = imports.mainloop;
 | 
			
		||||
const Meta = imports.gi.Meta;
 | 
			
		||||
const Pango = imports.gi.Pango;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
@@ -85,8 +86,7 @@ var UserListItem = new Lang.Class({
 | 
			
		||||
                                             GObject.BindingFlags.SYNC_CREATE);
 | 
			
		||||
 | 
			
		||||
        this._timedLoginIndicator = new St.Bin({ style_class: 'login-dialog-timed-login-indicator',
 | 
			
		||||
                                                 scale_x: 0,
 | 
			
		||||
                                                 visible: false });
 | 
			
		||||
                                                 scale_x: 0 });
 | 
			
		||||
        layout.add(this._timedLoginIndicator);
 | 
			
		||||
 | 
			
		||||
        this.actor.connect('clicked', this._onClicked.bind(this));
 | 
			
		||||
@@ -126,8 +126,6 @@ var UserListItem = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        this.hideTimedLoginIndicator();
 | 
			
		||||
 | 
			
		||||
        this._timedLoginIndicator.visible = true;
 | 
			
		||||
 | 
			
		||||
        let startTime = GLib.get_monotonic_time();
 | 
			
		||||
 | 
			
		||||
        this._timedLoginTimeoutId = GLib.timeout_add (GLib.PRIORITY_DEFAULT, 33,
 | 
			
		||||
@@ -154,8 +152,6 @@ var UserListItem = new Lang.Class({
 | 
			
		||||
            GLib.source_remove(this._timedLoginTimeoutId);
 | 
			
		||||
            this._timedLoginTimeoutId = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._timedLoginIndicator.visible = false;
 | 
			
		||||
        this._timedLoginIndicator.scale_x = 0.;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
@@ -995,81 +991,59 @@ var LoginDialog = new Lang.Class({
 | 
			
		||||
        return hold;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _showTimedLoginAnimation() {
 | 
			
		||||
        this._timedLoginItem.actor.grab_key_focus();
 | 
			
		||||
        return this._timedLoginItem.showTimedLoginIndicator(this._timedLoginAnimationTime);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _blockTimedLoginUntilIdle() {
 | 
			
		||||
        // This blocks timed login from starting until a few
 | 
			
		||||
        // seconds after the user stops interacting with the
 | 
			
		||||
        // login screen.
 | 
			
		||||
        //
 | 
			
		||||
        // We skip this step if the timed login delay is very
 | 
			
		||||
        // short.
 | 
			
		||||
        if ((this._timedLoginDelay - _TIMED_LOGIN_IDLE_THRESHOLD) <= 0)
 | 
			
		||||
          return null;
 | 
			
		||||
 | 
			
		||||
        let hold = new Batch.Hold();
 | 
			
		||||
 | 
			
		||||
        this._timedLoginIdleTimeOutId = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, _TIMED_LOGIN_IDLE_THRESHOLD,
 | 
			
		||||
        this._timedLoginIdleTimeOutId = Mainloop.timeout_add_seconds(_TIMED_LOGIN_IDLE_THRESHOLD,
 | 
			
		||||
            () => {
 | 
			
		||||
                this._timedLoginIdleTimeOutId = 0;
 | 
			
		||||
                this._timedLoginAnimationTime -= _TIMED_LOGIN_IDLE_THRESHOLD;
 | 
			
		||||
                hold.release();
 | 
			
		||||
                return GLib.SOURCE_REMOVE;
 | 
			
		||||
            });
 | 
			
		||||
        GLib.Source.set_name_by_id(this._timedLoginIdleTimeOutId, '[gnome-shell] this._timedLoginIdleTimeOutId');
 | 
			
		||||
        GLib.Source.set_name_by_id(this._timedLoginIdleTimeOutId, '[gnome-shell] this._timedLoginAnimationTime');
 | 
			
		||||
        return hold;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _startTimedLogin(userName, delay) {
 | 
			
		||||
        let firstRun = true;
 | 
			
		||||
 | 
			
		||||
        // Cancel execution of old batch
 | 
			
		||||
        if (this._timedLoginBatch) {
 | 
			
		||||
            this._timedLoginBatch.cancel();
 | 
			
		||||
            this._timedLoginBatch = null;
 | 
			
		||||
            firstRun = false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Reset previous idle-timeout
 | 
			
		||||
        if (this._timedLoginIdleTimeOutId) {
 | 
			
		||||
            GLib.source_remove(this._timedLoginIdleTimeOutId);
 | 
			
		||||
            this._timedLoginIdleTimeOutId = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let loginItem = null;
 | 
			
		||||
        let animationTime;
 | 
			
		||||
        this._timedLoginItem = null;
 | 
			
		||||
        this._timedLoginDelay = delay;
 | 
			
		||||
        this._timedLoginAnimationTime = delay;
 | 
			
		||||
 | 
			
		||||
        let tasks = [() => this._waitForItemForUser(userName),
 | 
			
		||||
 | 
			
		||||
                     () => {
 | 
			
		||||
                         loginItem = this._userList.getItemFromUserName(userName);
 | 
			
		||||
 | 
			
		||||
                         // If there is an animation running on the item, reset it.
 | 
			
		||||
                         loginItem.hideTimedLoginIndicator();
 | 
			
		||||
                         this._timedLoginItem = this._userList.getItemFromUserName(userName);
 | 
			
		||||
                     },
 | 
			
		||||
 | 
			
		||||
                     () => {
 | 
			
		||||
                         // If we're just starting out, start on the right item.
 | 
			
		||||
                         // If we're just starting out, start on the right
 | 
			
		||||
                         // item.
 | 
			
		||||
                         if (!this._userManager.is_loaded) {
 | 
			
		||||
                             this._userList.jumpToItem(loginItem);
 | 
			
		||||
                             this._userList.jumpToItem(this._timedLoginItem);
 | 
			
		||||
                         }
 | 
			
		||||
                     },
 | 
			
		||||
 | 
			
		||||
                     this._blockTimedLoginUntilIdle,
 | 
			
		||||
 | 
			
		||||
                     () => {
 | 
			
		||||
                         // This blocks the timed login animation until a few
 | 
			
		||||
                         // seconds after the user stops interacting with the
 | 
			
		||||
                         // login screen.
 | 
			
		||||
 | 
			
		||||
                         // We skip this step if the timed login delay is very short.
 | 
			
		||||
                         if (delay > _TIMED_LOGIN_IDLE_THRESHOLD) {
 | 
			
		||||
                             animationTime = delay - _TIMED_LOGIN_IDLE_THRESHOLD;
 | 
			
		||||
                             return this._blockTimedLoginUntilIdle();
 | 
			
		||||
                         } else {
 | 
			
		||||
                             animationTime = delay;
 | 
			
		||||
                         }
 | 
			
		||||
                         this._userList.scrollToItem(this._timedLoginItem);
 | 
			
		||||
                     },
 | 
			
		||||
 | 
			
		||||
                     () => {
 | 
			
		||||
                         // If idle timeout is done, make sure the timed login indicator is shown
 | 
			
		||||
                         if (delay > _TIMED_LOGIN_IDLE_THRESHOLD &&
 | 
			
		||||
                             this._authPrompt.actor.visible)
 | 
			
		||||
                             this._authPrompt.cancel();
 | 
			
		||||
 | 
			
		||||
                         if (delay > _TIMED_LOGIN_IDLE_THRESHOLD || firstRun) {
 | 
			
		||||
                             this._userList.scrollToItem(loginItem);
 | 
			
		||||
                             loginItem.actor.grab_key_focus();
 | 
			
		||||
                         }
 | 
			
		||||
                     },
 | 
			
		||||
 | 
			
		||||
                     () => loginItem.showTimedLoginIndicator(animationTime),
 | 
			
		||||
                     this._showTimedLoginAnimation,
 | 
			
		||||
 | 
			
		||||
                     () => {
 | 
			
		||||
                         this._timedLoginBatch = null;
 | 
			
		||||
@@ -1081,17 +1055,37 @@ var LoginDialog = new Lang.Class({
 | 
			
		||||
        return this._timedLoginBatch.run();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onTimedLoginRequested(client, userName, seconds) {
 | 
			
		||||
        if (this._timedLoginBatch)
 | 
			
		||||
            return;
 | 
			
		||||
    _resetTimedLogin() {
 | 
			
		||||
        if (this._timedLoginBatch) {
 | 
			
		||||
            this._timedLoginBatch.cancel();
 | 
			
		||||
            this._timedLoginBatch = null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this._timedLoginItem)
 | 
			
		||||
            this._timedLoginItem.hideTimedLoginIndicator();
 | 
			
		||||
 | 
			
		||||
        let userName = this._timedLoginItem.user.get_user_name();
 | 
			
		||||
 | 
			
		||||
        if (userName)
 | 
			
		||||
            this._startTimedLogin(userName, this._timedLoginDelay);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onTimedLoginRequested(client, userName, seconds) {
 | 
			
		||||
        this._startTimedLogin(userName, seconds);
 | 
			
		||||
 | 
			
		||||
        // Restart timed login on user interaction
 | 
			
		||||
        global.stage.connect('captured-event', (actor, event) => {
 | 
			
		||||
           if (this._timedLoginDelay == undefined)
 | 
			
		||||
               return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
 | 
			
		||||
           if (event.type() == Clutter.EventType.KEY_PRESS ||
 | 
			
		||||
               event.type() == Clutter.EventType.BUTTON_PRESS) {
 | 
			
		||||
               this._startTimedLogin(userName, seconds);
 | 
			
		||||
               if (this._timedLoginBatch) {
 | 
			
		||||
                   this._timedLoginBatch.cancel();
 | 
			
		||||
                   this._timedLoginBatch = null;
 | 
			
		||||
               }
 | 
			
		||||
           } else if (event.type() == Clutter.EventType.KEY_RELEASE ||
 | 
			
		||||
                      event.type() == Clutter.EventType.BUTTON_RELEASE) {
 | 
			
		||||
               this._resetTimedLogin();
 | 
			
		||||
           }
 | 
			
		||||
 | 
			
		||||
           return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
 
 | 
			
		||||
@@ -534,12 +534,13 @@ var ShellUserVerifier = new Lang.Class({
 | 
			
		||||
    _verificationFailed(retry) {
 | 
			
		||||
        // For Not Listed / enterprise logins, immediately reset
 | 
			
		||||
        // the dialog
 | 
			
		||||
        // Otherwise, we allow ALLOWED_FAILURES attempts. After that, we
 | 
			
		||||
        // go back to the welcome screen.
 | 
			
		||||
        // Otherwise, when in login mode we allow ALLOWED_FAILURES attempts.
 | 
			
		||||
        // After that, we go back to the welcome screen.
 | 
			
		||||
 | 
			
		||||
        this._failCounter++;
 | 
			
		||||
        let canRetry = retry && this._userName &&
 | 
			
		||||
            this._failCounter < this._settings.get_int(ALLOWED_FAILURES_KEY);
 | 
			
		||||
            (this._reauthOnly ||
 | 
			
		||||
             this._failCounter < this._settings.get_int(ALLOWED_FAILURES_KEY));
 | 
			
		||||
 | 
			
		||||
        if (canRetry) {
 | 
			
		||||
            if (!this.hasPendingMessages) {
 | 
			
		||||
@@ -562,7 +563,7 @@ var ShellUserVerifier = new Lang.Class({
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.emit('verification-failed');
 | 
			
		||||
        this.emit('verification-failed', canRetry);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onConversationStopped(client, serviceName) {
 | 
			
		||||
 
 | 
			
		||||
@@ -115,6 +115,11 @@ var IBusManager = new Lang.Class({
 | 
			
		||||
                                                         object_path: IBus.PATH_PANEL });
 | 
			
		||||
            this._candidatePopup.setPanelService(this._panelService);
 | 
			
		||||
            this._panelService.connect('update-property', this._updateProperty.bind(this));
 | 
			
		||||
            this._panelService.connect('set-cursor-location', (ps, x, y, w, h) => {
 | 
			
		||||
                let cursorLocation = { x, y, width: w, height: h };
 | 
			
		||||
                this.emit('set-cursor-location', cursorLocation);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            try {
 | 
			
		||||
                // IBus versions older than 1.5.10 have a bug which
 | 
			
		||||
                // causes spurious set-content-type emissions when
 | 
			
		||||
@@ -200,7 +205,7 @@ var IBusManager = new Lang.Class({
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._ibus.set_global_engine_async(id, this._MAX_INPUT_SOURCE_ACTIVATION_TIME,
 | 
			
		||||
                                           null, callback);
 | 
			
		||||
                                           null, callback || null);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    preloadEngines(ids) {
 | 
			
		||||
 
 | 
			
		||||
@@ -236,11 +236,12 @@ var ObjectManager = new Lang.Class({
 | 
			
		||||
    _onNameVanished() {
 | 
			
		||||
        let objectPaths = Object.keys(this._objects);
 | 
			
		||||
        for (let i = 0; i < objectPaths.length; i++) {
 | 
			
		||||
            let object = this._objects[objectPaths];
 | 
			
		||||
            let objectPath = objectPaths[i];
 | 
			
		||||
            let object = this._objects[objectPath];
 | 
			
		||||
 | 
			
		||||
            let interfaceNames = Object.keys(object);
 | 
			
		||||
            for (let j = 0; i < interfaceNames.length; i++) {
 | 
			
		||||
                let interfaceName = interfaceNames[i];
 | 
			
		||||
            for (let j = 0; j < interfaceNames.length; j++) {
 | 
			
		||||
                let interfaceName = interfaceNames[j];
 | 
			
		||||
 | 
			
		||||
                if (object[interfaceName])
 | 
			
		||||
                    this._removeInterface(objectPath, interfaceName);
 | 
			
		||||
 
 | 
			
		||||
@@ -136,7 +136,8 @@ function run() {
 | 
			
		||||
    global.frame_finish_timestamp = true;
 | 
			
		||||
 | 
			
		||||
    for (let k = 0; k < 5; k++)
 | 
			
		||||
        yield Scripting.createTestWindow({ maximized: true });
 | 
			
		||||
        yield Scripting.createTestWindow(640, 480,
 | 
			
		||||
                                         { maximized: true });
 | 
			
		||||
    yield Scripting.waitTestWindows();
 | 
			
		||||
 | 
			
		||||
    yield Scripting.sleep(1000);
 | 
			
		||||
@@ -157,7 +158,8 @@ function run() {
 | 
			
		||||
    yield Scripting.destroyTestWindows();
 | 
			
		||||
    Main.overview.hide();
 | 
			
		||||
 | 
			
		||||
    yield Scripting.createTestWindow({ maximized: true,
 | 
			
		||||
    yield Scripting.createTestWindow(640, 480,
 | 
			
		||||
                                     { maximized: true,
 | 
			
		||||
                                       redraws: true});
 | 
			
		||||
    yield Scripting.waitTestWindows();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -92,17 +92,8 @@ function _listsIntersect(a, b) {
 | 
			
		||||
function _getFolderName(folder) {
 | 
			
		||||
    let name = folder.get_string('name');
 | 
			
		||||
 | 
			
		||||
    if (folder.get_boolean('translate')) {
 | 
			
		||||
        let keyfile = new GLib.KeyFile();
 | 
			
		||||
        let path = 'desktop-directories/' + name;
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            keyfile.load_from_data_dirs(path, GLib.KeyFileFlags.NONE);
 | 
			
		||||
            name = keyfile.get_locale_string('Desktop Entry', 'Name', null);
 | 
			
		||||
        } catch(e) {
 | 
			
		||||
            return name;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (folder.get_boolean('translate'))
 | 
			
		||||
        return Shell.AppCache.get_default().translate_folder(name);
 | 
			
		||||
 | 
			
		||||
    return name;
 | 
			
		||||
}
 | 
			
		||||
@@ -499,7 +490,7 @@ var AllView = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _loadApps() {
 | 
			
		||||
        let apps = Gio.AppInfo.get_all().filter(appInfo => {
 | 
			
		||||
        let apps = Shell.AppCache.get_default().get_all().filter(appInfo => {
 | 
			
		||||
            try {
 | 
			
		||||
                let id = appInfo.get_id(); // catch invalid file encodings
 | 
			
		||||
            } catch(e) {
 | 
			
		||||
@@ -1329,7 +1320,7 @@ var FolderIcon = new Lang.Class({
 | 
			
		||||
        folderApps.forEach(addAppId);
 | 
			
		||||
 | 
			
		||||
        let folderCategories = this._folder.get_strv('categories');
 | 
			
		||||
        Gio.AppInfo.get_all().forEach(appInfo => {
 | 
			
		||||
        Shell.AppCache.get_default().get_all().forEach(appInfo => {
 | 
			
		||||
            let appCategories = _getCategories(appInfo);
 | 
			
		||||
            if (!_listsIntersect(folderCategories, appCategories))
 | 
			
		||||
                return;
 | 
			
		||||
 
 | 
			
		||||
@@ -802,6 +802,8 @@ var NotificationMessage = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onDestroy() {
 | 
			
		||||
        this.parent();
 | 
			
		||||
 | 
			
		||||
        if (this._updatedId)
 | 
			
		||||
            this.notification.disconnect(this._updatedId);
 | 
			
		||||
        this._updatedId = 0;
 | 
			
		||||
@@ -821,6 +823,8 @@ var EventsSection = new Lang.Class({
 | 
			
		||||
        this._desktopSettings.connect('changed', this._reloadEvents.bind(this));
 | 
			
		||||
        this._eventSource = new EmptyEventSource();
 | 
			
		||||
 | 
			
		||||
        this._messageById = new Map();
 | 
			
		||||
 | 
			
		||||
        this.parent();
 | 
			
		||||
 | 
			
		||||
        this._title = new St.Button({ style_class: 'events-section-title',
 | 
			
		||||
@@ -875,20 +879,32 @@ var EventsSection = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        this._reloading = true;
 | 
			
		||||
 | 
			
		||||
        this._list.destroy_all_children();
 | 
			
		||||
 | 
			
		||||
        let periodBegin = _getBeginningOfDay(this._date);
 | 
			
		||||
        let periodEnd = _getEndOfDay(this._date);
 | 
			
		||||
        let events = this._eventSource.getEvents(periodBegin, periodEnd);
 | 
			
		||||
 | 
			
		||||
        let ids = events.map(e => e.id);
 | 
			
		||||
        this._messageById.forEach((message, id) => {
 | 
			
		||||
            if (ids.includes(id))
 | 
			
		||||
                return;
 | 
			
		||||
            this._messageById.delete(id);
 | 
			
		||||
            this.removeMessage(message);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < events.length; i++) {
 | 
			
		||||
            let event = events[i];
 | 
			
		||||
 | 
			
		||||
            let message = new EventMessage(event, this._date);
 | 
			
		||||
            message.connect('close', () => {
 | 
			
		||||
                this._ignoreEvent(event);
 | 
			
		||||
            });
 | 
			
		||||
            this.addMessage(message, false);
 | 
			
		||||
            let message = this._messageById.get(event.id);
 | 
			
		||||
            if (!message) {
 | 
			
		||||
                message = new EventMessage(event, this._date);
 | 
			
		||||
                message.connect('close', () => {
 | 
			
		||||
                    this._ignoreEvent(event);
 | 
			
		||||
                });
 | 
			
		||||
                this._messageById.set(event.id, message);
 | 
			
		||||
                this.addMessage(message, false);
 | 
			
		||||
            } else {
 | 
			
		||||
                this.moveMessage(message, i, false);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._reloading = false;
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,7 @@
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const GObject = imports.gi.GObject;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Meta = imports.gi.Meta;
 | 
			
		||||
@@ -13,6 +14,7 @@ const Tweener = imports.ui.tweener;
 | 
			
		||||
 | 
			
		||||
var FROZEN_WINDOW_BRIGHTNESS = -0.3
 | 
			
		||||
var DIALOG_TRANSITION_TIME = 0.15
 | 
			
		||||
var ALIVE_TIMEOUT = 5000;
 | 
			
		||||
 | 
			
		||||
var CloseDialog = new Lang.Class({
 | 
			
		||||
    Name: 'CloseDialog',
 | 
			
		||||
@@ -26,6 +28,10 @@ var CloseDialog = new Lang.Class({
 | 
			
		||||
        this.parent();
 | 
			
		||||
        this._window = window;
 | 
			
		||||
        this._dialog = null;
 | 
			
		||||
        this._tracked = undefined;
 | 
			
		||||
        this._timeoutId = 0;
 | 
			
		||||
        this._windowFocusChangedId = 0;
 | 
			
		||||
        this._keyFocusChangedId = 0;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    get window() {
 | 
			
		||||
@@ -93,10 +99,57 @@ var CloseDialog = new Lang.Class({
 | 
			
		||||
        this.response(Meta.CloseDialogResponse.FORCE_CLOSE);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onFocusChanged() {
 | 
			
		||||
        if (Meta.is_wayland_compositor())
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let focusWindow = global.display.focus_window;
 | 
			
		||||
        let keyFocus = global.stage.key_focus;
 | 
			
		||||
 | 
			
		||||
        let shouldTrack;
 | 
			
		||||
        if (focusWindow != null)
 | 
			
		||||
            shouldTrack = focusWindow == this._window;
 | 
			
		||||
        else
 | 
			
		||||
            shouldTrack = keyFocus && this._dialog.contains(keyFocus);
 | 
			
		||||
 | 
			
		||||
        if (this._tracked === shouldTrack)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (shouldTrack)
 | 
			
		||||
            Main.layoutManager.trackChrome(this._dialog,
 | 
			
		||||
                                           { affectsInputRegion: true });
 | 
			
		||||
        else
 | 
			
		||||
            Main.layoutManager.untrackChrome(this._dialog);
 | 
			
		||||
 | 
			
		||||
        // The buttons are broken when they aren't added to the input region,
 | 
			
		||||
        // so disable them properly in that case
 | 
			
		||||
        this._dialog.buttonLayout.get_children().forEach(b => {
 | 
			
		||||
            b.reactive = shouldTrack;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this._tracked = shouldTrack;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    vfunc_show() {
 | 
			
		||||
        if (this._dialog != null)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        Meta.disable_unredirect_for_screen(global.screen);
 | 
			
		||||
 | 
			
		||||
        this._timeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, ALIVE_TIMEOUT,
 | 
			
		||||
            () => {
 | 
			
		||||
                this._window.check_alive(global.display.get_current_time_roundtrip());
 | 
			
		||||
                return GLib.SOURCE_CONTINUE;
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
        this._windowFocusChangedId =
 | 
			
		||||
            global.display.connect('notify::focus-window',
 | 
			
		||||
                                   this._onFocusChanged.bind(this));
 | 
			
		||||
 | 
			
		||||
        this._keyFocusChangedId =
 | 
			
		||||
            global.stage.connect('notify::key-focus',
 | 
			
		||||
                                 this._onFocusChanged.bind(this));
 | 
			
		||||
 | 
			
		||||
        this._addWindowEffect();
 | 
			
		||||
        this._initDialog();
 | 
			
		||||
 | 
			
		||||
@@ -107,9 +160,7 @@ var CloseDialog = new Lang.Class({
 | 
			
		||||
                         { scale_y: 1,
 | 
			
		||||
                           transition: 'linear',
 | 
			
		||||
                           time: DIALOG_TRANSITION_TIME,
 | 
			
		||||
                           onComplete: () => {
 | 
			
		||||
                               Main.layoutManager.trackChrome(this._dialog, { affectsInputRegion: true });
 | 
			
		||||
                           }
 | 
			
		||||
                           onComplete: this._onFocusChanged.bind(this)
 | 
			
		||||
                         });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -117,6 +168,17 @@ var CloseDialog = new Lang.Class({
 | 
			
		||||
        if (this._dialog == null)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        Meta.enable_unredirect_for_screen(global.screen);
 | 
			
		||||
 | 
			
		||||
        GLib.source_remove(this._timeoutId);
 | 
			
		||||
        this._timeoutId = 0;
 | 
			
		||||
 | 
			
		||||
        global.display.disconnect(this._windowFocusChangedId)
 | 
			
		||||
        this._windowFocusChangedId = 0;
 | 
			
		||||
 | 
			
		||||
        global.stage.disconnect(this._keyFocusChangedId);
 | 
			
		||||
        this._keyFocusChangedId = 0;
 | 
			
		||||
 | 
			
		||||
        let dialog = this._dialog;
 | 
			
		||||
        this._dialog = null;
 | 
			
		||||
        this._removeWindowEffect();
 | 
			
		||||
 
 | 
			
		||||
@@ -210,6 +210,10 @@ var AutomountManager = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onVolumeRemoved(monitor, volume) {
 | 
			
		||||
        if (volume._allowAutorunExpireId && volume._allowAutorunExpireId > 0) {
 | 
			
		||||
            Mainloop.source_remove(volume._allowAutorunExpireId);
 | 
			
		||||
            delete volume._allowAutorunExpireId;
 | 
			
		||||
        }
 | 
			
		||||
        this._volumeQueue = 
 | 
			
		||||
            this._volumeQueue.filter(element => (element != volume));
 | 
			
		||||
    },
 | 
			
		||||
@@ -234,8 +238,10 @@ var AutomountManager = new Lang.Class({
 | 
			
		||||
    _allowAutorunExpire(volume) {
 | 
			
		||||
        let id = Mainloop.timeout_add_seconds(AUTORUN_EXPIRE_TIMEOUT_SECS, () => {
 | 
			
		||||
            volume.allowAutorun = false;
 | 
			
		||||
            delete volume._allowAutorunExpireId;
 | 
			
		||||
            return GLib.SOURCE_REMOVE;
 | 
			
		||||
        });
 | 
			
		||||
        volume._allowAutorunExpireId = id;
 | 
			
		||||
        GLib.Source.set_name_by_id(id, '[gnome-shell] volume.allowAutorun');
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -604,17 +604,12 @@ var NetworkAgent = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        this._native.connect('new-request', this._newRequest.bind(this));
 | 
			
		||||
        this._native.connect('cancel-request', this._cancelRequest.bind(this));
 | 
			
		||||
 | 
			
		||||
        this._initialized = false;
 | 
			
		||||
        this._native.init_async(GLib.PRIORITY_DEFAULT, null, (o, res) => {
 | 
			
		||||
            try {
 | 
			
		||||
                this._native.init_finish(res);
 | 
			
		||||
                this._initialized = true;
 | 
			
		||||
            } catch(e) {
 | 
			
		||||
                this._native = null;
 | 
			
		||||
                logError(e, 'error initializing the NetworkManager Agent');
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
        try {
 | 
			
		||||
            this._native.init(null);
 | 
			
		||||
        } catch(e) {
 | 
			
		||||
            this._native = null;
 | 
			
		||||
            logError(e, 'error initializing the NetworkManager Agent');
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    enable() {
 | 
			
		||||
@@ -622,7 +617,7 @@ var NetworkAgent = new Lang.Class({
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._native.auto_register = true;
 | 
			
		||||
        if (this._initialized && !this._native.registered)
 | 
			
		||||
        if (!this._native.registered)
 | 
			
		||||
            this._native.register_async(null, null);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -645,7 +640,7 @@ var NetworkAgent = new Lang.Class({
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._native.auto_register = false;
 | 
			
		||||
        if (this._initialized && this._native.registered)
 | 
			
		||||
        if (this._native.registered)
 | 
			
		||||
            this._native.unregister_async(null, null);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -52,6 +52,8 @@ var DashItemContainer = new Lang.Class({
 | 
			
		||||
        this.animatingOut = false;
 | 
			
		||||
 | 
			
		||||
        this.connect('destroy', () => {
 | 
			
		||||
            if (this.child != null)
 | 
			
		||||
                this.child.destroy();
 | 
			
		||||
            this.label.destroy();
 | 
			
		||||
        });
 | 
			
		||||
    },
 | 
			
		||||
 
 | 
			
		||||
@@ -183,7 +183,7 @@ var MessageDialogContent = new Lang.Class({
 | 
			
		||||
            this[`_${prop}`].add_style_class_name(`message-dialog-${prop}`);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        let textProps = { ellipsize_mode: Pango.EllipsizeMode.NONE,
 | 
			
		||||
        let textProps = { ellipsize: Pango.EllipsizeMode.NONE,
 | 
			
		||||
                          line_wrap: true };
 | 
			
		||||
        Object.assign(this._subtitle.clutter_text, textProps);
 | 
			
		||||
        Object.assign(this._body.clutter_text, textProps);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										32
									
								
								js/ui/dnd.js
									
									
									
									
									
								
							
							
						
						
									
										32
									
								
								js/ui/dnd.js
									
									
									
									
									
								
							@@ -125,6 +125,16 @@ var _Draggable = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onTouchEvent(actor, event) {
 | 
			
		||||
        // Here we only handle touch events on wayland. On X11
 | 
			
		||||
        // we do get emulated pointer events, which already works
 | 
			
		||||
        // for single-touch cases. Besides, the X11 passive touch grab
 | 
			
		||||
        // set up by Mutter will make us see first the touch events
 | 
			
		||||
        // and later the pointer events, so it will look like two
 | 
			
		||||
        // unrelated series of events, we want to avoid double handling
 | 
			
		||||
        // in these cases.
 | 
			
		||||
        if (!Meta.is_wayland_compositor())
 | 
			
		||||
            return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
 | 
			
		||||
        if (event.type() != Clutter.EventType.TOUCH_BEGIN ||
 | 
			
		||||
            !global.display.is_pointer_emulating_sequence(event.get_event_sequence()))
 | 
			
		||||
            return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
@@ -396,10 +406,15 @@ var _Draggable = new Lang.Class({
 | 
			
		||||
        return true;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _pickTargetActor() {
 | 
			
		||||
        return this._dragActor.get_stage().get_actor_at_pos(Clutter.PickMode.ALL,
 | 
			
		||||
                                                            this._dragX, this._dragY);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateDragHover() {
 | 
			
		||||
        this._updateHoverId = 0;
 | 
			
		||||
        let target = this._dragActor.get_stage().get_actor_at_pos(Clutter.PickMode.ALL,
 | 
			
		||||
                                                                  this._dragX, this._dragY);
 | 
			
		||||
        let target = this._pickTargetActor();
 | 
			
		||||
 | 
			
		||||
        let dragEvent = {
 | 
			
		||||
            x: this._dragX,
 | 
			
		||||
            y: this._dragY,
 | 
			
		||||
@@ -407,6 +422,18 @@ var _Draggable = new Lang.Class({
 | 
			
		||||
            source: this.actor._delegate,
 | 
			
		||||
            targetActor: target
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        let targetActorDestroyHandlerId;
 | 
			
		||||
        let handleTargetActorDestroyClosure;
 | 
			
		||||
        handleTargetActorDestroyClosure = () => {
 | 
			
		||||
            target = this._pickTargetActor();
 | 
			
		||||
            dragEvent.targetActor = target;
 | 
			
		||||
            targetActorDestroyHandlerId =
 | 
			
		||||
                target.connect('destroy', handleTargetActorDestroyClosure);
 | 
			
		||||
        };
 | 
			
		||||
        targetActorDestroyHandlerId =
 | 
			
		||||
            target.connect('destroy', handleTargetActorDestroyClosure);
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < dragMonitors.length; i++) {
 | 
			
		||||
            let motionFunc = dragMonitors[i].dragMotion;
 | 
			
		||||
            if (motionFunc) {
 | 
			
		||||
@@ -417,6 +444,7 @@ var _Draggable = new Lang.Class({
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        dragEvent.targetActor.disconnect(targetActorDestroyHandlerId);
 | 
			
		||||
 | 
			
		||||
        while (target) {
 | 
			
		||||
            if (target._delegate && target._delegate.handleDragOver) {
 | 
			
		||||
 
 | 
			
		||||
@@ -760,7 +760,7 @@ var EndSessionDialog = new Lang.Class({
 | 
			
		||||
        let updatePrepared = this._pkOfflineProxy.UpdatePrepared;
 | 
			
		||||
        let updatesAllowed = this._updatesPermission && this._updatesPermission.allowed;
 | 
			
		||||
 | 
			
		||||
        _setCheckBoxLabel(this._checkBox, dialogContent.checkBoxText);
 | 
			
		||||
        _setCheckBoxLabel(this._checkBox, dialogContent.checkBoxText || '');
 | 
			
		||||
        this._checkBox.actor.visible = (dialogContent.checkBoxText && updatePrepared && updatesAllowed);
 | 
			
		||||
        this._checkBox.actor.checked = (updatePrepared && updateTriggered);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -17,6 +17,9 @@ const Gtk = imports.gi.Gtk;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
const System = imports.system;
 | 
			
		||||
 | 
			
		||||
let _localTimeZone = null;
 | 
			
		||||
 | 
			
		||||
// We can't import shell JS modules yet, because they may have
 | 
			
		||||
// variable initializations, etc, that depend on init() already having
 | 
			
		||||
@@ -116,9 +119,26 @@ function init() {
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // Override to clear our own timezone cache as well
 | 
			
		||||
    const origClearDateCaches = System.clearDateCaches;
 | 
			
		||||
    System.clearDateCaches = function () {
 | 
			
		||||
        _localTimeZone = null;
 | 
			
		||||
        origClearDateCaches();
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // Work around https://bugzilla.mozilla.org/show_bug.cgi?id=508783
 | 
			
		||||
    Date.prototype.toLocaleFormat = function(format) {
 | 
			
		||||
        return Shell.util_format_date(format, this.getTime());
 | 
			
		||||
        if (_localTimeZone === null)
 | 
			
		||||
            _localTimeZone = GLib.TimeZone.new_local();
 | 
			
		||||
 | 
			
		||||
        let dt = GLib.DateTime.new(_localTimeZone,
 | 
			
		||||
            this.getYear(),
 | 
			
		||||
            this.getMonth() + 1,
 | 
			
		||||
            this.getDate(),
 | 
			
		||||
            this.getHours(),
 | 
			
		||||
            this.getMinutes(),
 | 
			
		||||
            this.getSeconds());
 | 
			
		||||
        return dt ? dt.format(format) : '';
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    let slowdownEnv = GLib.getenv('GNOME_SHELL_SLOWDOWN_FACTOR');
 | 
			
		||||
 
 | 
			
		||||
@@ -76,6 +76,7 @@ function disableExtension(uuid) {
 | 
			
		||||
    if (extension.stylesheet) {
 | 
			
		||||
        let theme = St.ThemeContext.get_for_stage(global.stage).get_theme();
 | 
			
		||||
        theme.unload_stylesheet(extension.stylesheet);
 | 
			
		||||
        delete extension.stylesheet;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
@@ -115,13 +116,18 @@ function enableExtension(uuid) {
 | 
			
		||||
    extensionOrder.push(uuid);
 | 
			
		||||
 | 
			
		||||
    let stylesheetNames = [global.session_mode + '.css', 'stylesheet.css'];
 | 
			
		||||
    let theme = St.ThemeContext.get_for_stage(global.stage).get_theme();
 | 
			
		||||
    for (let i = 0; i < stylesheetNames.length; i++) {
 | 
			
		||||
        let stylesheetFile = extension.dir.get_child(stylesheetNames[i]);
 | 
			
		||||
        if (stylesheetFile.query_exists(null)) {
 | 
			
		||||
            let theme = St.ThemeContext.get_for_stage(global.stage).get_theme();
 | 
			
		||||
        try {
 | 
			
		||||
            let stylesheetFile = extension.dir.get_child(stylesheetNames[i]);
 | 
			
		||||
            theme.load_stylesheet(stylesheetFile);
 | 
			
		||||
            extension.stylesheet = stylesheetFile;
 | 
			
		||||
            break;
 | 
			
		||||
        } catch (e) {
 | 
			
		||||
            if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND))
 | 
			
		||||
                continue; // not an error
 | 
			
		||||
            log(`Failed to load stylesheet for extension ${uuid}: ${e.message}`);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -131,6 +137,10 @@ function enableExtension(uuid) {
 | 
			
		||||
        _signals.emit('extension-state-changed', extension);
 | 
			
		||||
        return;
 | 
			
		||||
    } catch(e) {
 | 
			
		||||
        if (extension.stylesheet) {
 | 
			
		||||
            theme.unload_stylesheet(extension.stylesheet);
 | 
			
		||||
            delete extension.stylesheet;
 | 
			
		||||
        }
 | 
			
		||||
        logExtensionError(uuid, e);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -166,7 +166,7 @@ var CandidatePopup = new Lang.Class({
 | 
			
		||||
            this._panelService.cursor_down();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this._candidateArea.connect('candidate-clicked', (area, index, button, state) => {
 | 
			
		||||
        this._candidateArea.connect('candidate-clicked', () => {
 | 
			
		||||
            this._panelService.candidate_clicked(index, button, state);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -418,6 +418,11 @@ var IconGrid = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _animationDone() {
 | 
			
		||||
        this._clonesAnimating.forEach(clone => {
 | 
			
		||||
            clone.source.reactive = true;
 | 
			
		||||
            clone.source.opacity = 255;
 | 
			
		||||
            clone.destroy();
 | 
			
		||||
        });
 | 
			
		||||
        this._clonesAnimating = [];
 | 
			
		||||
        this.emit('animation-done');
 | 
			
		||||
    },
 | 
			
		||||
@@ -538,10 +543,6 @@ var IconGrid = new Lang.Class({
 | 
			
		||||
                                   onComplete: () => {
 | 
			
		||||
                                       if (isLastItem)
 | 
			
		||||
                                           this._animationDone();
 | 
			
		||||
 | 
			
		||||
                                       actor.opacity = 255;
 | 
			
		||||
                                       actor.reactive = true;
 | 
			
		||||
                                       actorClone.destroy();
 | 
			
		||||
                                   }};
 | 
			
		||||
                fadeParams = { time: ANIMATION_FADE_IN_TIME_FOR_ITEM,
 | 
			
		||||
                               transition: 'easeInOutQuad',
 | 
			
		||||
@@ -562,12 +563,8 @@ var IconGrid = new Lang.Class({
 | 
			
		||||
                                   scale_x: scaleX,
 | 
			
		||||
                                   scale_y: scaleY,
 | 
			
		||||
                                   onComplete: () => {
 | 
			
		||||
                                       if (isLastItem) {
 | 
			
		||||
                                       if (isLastItem)
 | 
			
		||||
                                           this._animationDone();
 | 
			
		||||
                                           this._restoreItemsOpacity();
 | 
			
		||||
                                       }
 | 
			
		||||
                                       actor.reactive = true;
 | 
			
		||||
                                       actorClone.destroy();
 | 
			
		||||
                                   }};
 | 
			
		||||
                fadeParams = { time: ANIMATION_FADE_IN_TIME_FOR_ITEM,
 | 
			
		||||
                               transition: 'easeInOutQuad',
 | 
			
		||||
@@ -581,12 +578,6 @@ var IconGrid = new Lang.Class({
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _restoreItemsOpacity() {
 | 
			
		||||
        for (let index = 0; index < this._items.length; index++) {
 | 
			
		||||
            this._items[index].actor.opacity = 255;
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _getAllocatedChildSizeAndSpacing(child) {
 | 
			
		||||
        let [,, natWidth, natHeight] = child.get_preferred_size();
 | 
			
		||||
        let width = Math.min(this._getHItemSize(), natWidth);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,5 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const FocusCaretTracker = imports.ui.focusCaretTracker;
 | 
			
		||||
const Atspi = imports.gi.Atspi;
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Gdk = imports.gi.Gdk;
 | 
			
		||||
@@ -13,6 +12,7 @@ const Signals = imports.signals;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
const InputSourceManager = imports.ui.status.keyboard;
 | 
			
		||||
 | 
			
		||||
const IBusManager = imports.misc.ibusManager;
 | 
			
		||||
const BoxPointer = imports.ui.boxpointer;
 | 
			
		||||
const Layout = imports.ui.layout;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
@@ -261,6 +261,7 @@ var Key = new Lang.Class({
 | 
			
		||||
        this._extended_keyboard = null;
 | 
			
		||||
        this._pressTimeoutId = 0;
 | 
			
		||||
        this._capturedPress = false;
 | 
			
		||||
 | 
			
		||||
        this._capturedEventId = 0;
 | 
			
		||||
        this._unmapId = 0;
 | 
			
		||||
        this._longPress = false;
 | 
			
		||||
@@ -484,6 +485,79 @@ var KeyboardModel = new Lang.Class({
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
var FocusTracker = new Lang.Class({
 | 
			
		||||
    Name: 'FocusTracker',
 | 
			
		||||
 | 
			
		||||
    _init() {
 | 
			
		||||
        this._currentWindow = null;
 | 
			
		||||
        this._currentWindowPositionId = 0;
 | 
			
		||||
 | 
			
		||||
        global.screen.get_display().connect('notify::focus-window', () => {
 | 
			
		||||
            this._setCurrentWindow(global.screen.get_display().focus_window);
 | 
			
		||||
            this.emit('window-changed', this._currentWindow);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        /* Valid for wayland clients */
 | 
			
		||||
        Main.inputMethod.connect('cursor-location-changed', (o, rect) => {
 | 
			
		||||
            let newRect = { x: rect.get_x(), y: rect.get_y(), width: rect.get_width(), height: rect.get_height() };
 | 
			
		||||
            this._setCurrentRect(newRect);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this._ibusManager = IBusManager.getIBusManager();
 | 
			
		||||
        this._ibusManager.connect('set-cursor-location', (manager, rect) => {
 | 
			
		||||
            /* Valid for X11 clients only */
 | 
			
		||||
            if (Main.inputMethod.currentFocus)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            this._setCurrentRect(rect);
 | 
			
		||||
        });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    get currentWindow() {
 | 
			
		||||
        return this._currentWindow;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _setCurrentWindow(window) {
 | 
			
		||||
        if (this._currentWindow)
 | 
			
		||||
            this._currentWindow.disconnect(this._currentWindowPositionId);
 | 
			
		||||
 | 
			
		||||
        this._currentWindow = window;
 | 
			
		||||
        if (window) {
 | 
			
		||||
            this._currentWindowPositionId = this._currentWindow.connect('position-changed', () => {
 | 
			
		||||
                if (global.display.get_grab_op() == Meta.GrabOp.NONE)
 | 
			
		||||
                    this.emit('position-changed');
 | 
			
		||||
                else
 | 
			
		||||
                    this.emit('reset');
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _setCurrentRect(rect) {
 | 
			
		||||
        if (this._currentWindow) {
 | 
			
		||||
            let frameRect = this._currentWindow.get_frame_rect();
 | 
			
		||||
            rect.x -= frameRect.x;
 | 
			
		||||
            rect.y -= frameRect.y;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._rect = rect;
 | 
			
		||||
        this.emit('position-changed');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getCurrentRect() {
 | 
			
		||||
        let rect = { x: this._rect.x, y: this._rect.y,
 | 
			
		||||
                     width: this._rect.width, height: this._rect.height };
 | 
			
		||||
 | 
			
		||||
        if (this._currentWindow) {
 | 
			
		||||
            let frameRect = this._currentWindow.get_frame_rect();
 | 
			
		||||
            rect.x += frameRect.x;
 | 
			
		||||
            rect.y += frameRect.y;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return rect;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(FocusTracker.prototype);
 | 
			
		||||
 | 
			
		||||
var Keyboard = new Lang.Class({
 | 
			
		||||
    Name: 'Keyboard',
 | 
			
		||||
 | 
			
		||||
@@ -491,15 +565,10 @@ var Keyboard = new Lang.Class({
 | 
			
		||||
        this.actor = null;
 | 
			
		||||
        this._focusInExtendedKeys = false;
 | 
			
		||||
 | 
			
		||||
        this._focusCaretTracker = new FocusCaretTracker.FocusCaretTracker();
 | 
			
		||||
        this._focusCaretTracker.connect('focus-changed', this._onFocusChanged.bind(this));
 | 
			
		||||
        this._focusCaretTracker.connect('caret-moved', this._onCaretMoved.bind(this));
 | 
			
		||||
        this._languagePopup = null;
 | 
			
		||||
        this._currentAccessible = null;
 | 
			
		||||
        this._caretTrackingEnabled = false;
 | 
			
		||||
        this._updateCaretPositionId = 0;
 | 
			
		||||
        this._currentFocusWindow = null;
 | 
			
		||||
        this._originalWindowY = null;
 | 
			
		||||
        this._animFocusedWindow = null;
 | 
			
		||||
        this._delayedAnimFocusWindow = null;
 | 
			
		||||
 | 
			
		||||
        this._enableKeyboard = false; // a11y settings value
 | 
			
		||||
        this._enabled = false; // enabled state (by setting or device type)
 | 
			
		||||
@@ -510,6 +579,14 @@ var Keyboard = new Lang.Class({
 | 
			
		||||
        this._lastDeviceId = null;
 | 
			
		||||
        this._suggestions = null;
 | 
			
		||||
 | 
			
		||||
        this._focusTracker = new FocusTracker();
 | 
			
		||||
        this._focusTracker.connect('position-changed', this._onFocusPositionChanged.bind(this));
 | 
			
		||||
        this._focusTracker.connect('reset', () => {
 | 
			
		||||
            this._delayedAnimFocusWindow = null;
 | 
			
		||||
            this._animFocusedWindow = null;
 | 
			
		||||
            this._oskFocusWindow = null;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        Meta.get_backend().connect('last-device-changed', 
 | 
			
		||||
            (backend, deviceId) => {
 | 
			
		||||
                let manager = Clutter.DeviceManager.get_default();
 | 
			
		||||
@@ -532,102 +609,15 @@ var Keyboard = new Lang.Class({
 | 
			
		||||
        this._keyboardRestingId = 0;
 | 
			
		||||
 | 
			
		||||
        Main.layoutManager.connect('monitors-changed', this._relayout.bind(this));
 | 
			
		||||
        //Main.inputMethod.connect('cursor-location-changed', (o, rect) => {
 | 
			
		||||
        //    if (this._keyboardVisible) {
 | 
			
		||||
        //        let currentWindow = global.screen.get_display().focus_window;
 | 
			
		||||
        //        this.setCursorLocation(currentWindow, rect.get_x(), rect.get_y(),
 | 
			
		||||
        //                               rect.get_width(), rect.get_height());
 | 
			
		||||
        //    }
 | 
			
		||||
        //});
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    get visible() {
 | 
			
		||||
        return this._keyboardVisible;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _setCaretTrackerEnabled(enabled) {
 | 
			
		||||
        if (this._caretTrackingEnabled == enabled)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._caretTrackingEnabled = enabled;
 | 
			
		||||
 | 
			
		||||
        if (enabled) {
 | 
			
		||||
            this._focusCaretTracker.registerFocusListener();
 | 
			
		||||
            this._focusCaretTracker.registerCaretListener();
 | 
			
		||||
        } else {
 | 
			
		||||
            this._focusCaretTracker.deregisterFocusListener();
 | 
			
		||||
            this._focusCaretTracker.deregisterCaretListener();
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateCaretPosition(accessible) {
 | 
			
		||||
        if (this._updateCaretPositionId)
 | 
			
		||||
            GLib.source_remove(this._updateCaretPositionId);
 | 
			
		||||
        if (!this._keyboardRequested)
 | 
			
		||||
            return;
 | 
			
		||||
        this._updateCaretPositionId = GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => {
 | 
			
		||||
            this._updateCaretPositionId = 0;
 | 
			
		||||
 | 
			
		||||
            let currentWindow = global.screen.get_display().focus_window;
 | 
			
		||||
            if (!currentWindow) {
 | 
			
		||||
                this.setCursorLocation(null);
 | 
			
		||||
                return GLib.SOURCE_REMOVE;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            let windowRect = currentWindow.get_frame_rect();
 | 
			
		||||
            let text = accessible.get_text_iface();
 | 
			
		||||
            let component = accessible.get_component_iface();
 | 
			
		||||
 | 
			
		||||
            try {
 | 
			
		||||
                let caretOffset = text.get_caret_offset();
 | 
			
		||||
                let caretRect = text.get_character_extents(caretOffset, Atspi.CoordType.WINDOW);
 | 
			
		||||
                let focusRect = component.get_extents(Atspi.CoordType.WINDOW);
 | 
			
		||||
 | 
			
		||||
                if (caretRect.width == 0 && caretRect.height == 0)
 | 
			
		||||
                    caretRect = focusRect;
 | 
			
		||||
 | 
			
		||||
                this.setCursorLocation(currentWindow, caretRect.x, caretRect.y, caretRect.width, caretRect.height);
 | 
			
		||||
            } catch (e) {
 | 
			
		||||
                log('Error updating caret position for OSK: ' + e.message);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return GLib.SOURCE_REMOVE;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        GLib.Source.set_name_by_id(this._updateCaretPositionId, '[gnome-shell] this._updateCaretPosition');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _focusIsTextEntry(accessible) {
 | 
			
		||||
        try {
 | 
			
		||||
            let role = accessible.get_role();
 | 
			
		||||
            let stateSet = accessible.get_state_set();
 | 
			
		||||
            return stateSet.contains(Atspi.StateType.EDITABLE) || role == Atspi.Role.TERMINAL;
 | 
			
		||||
        } catch (e) {
 | 
			
		||||
            log('Error determining accessible role: ' + e.message);
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onFocusChanged(caretTracker, event) {
 | 
			
		||||
        let accessible = event.source;
 | 
			
		||||
        if (!this._focusIsTextEntry(accessible))
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let focused = event.detail1 != 0;
 | 
			
		||||
        if (focused) {
 | 
			
		||||
            this._currentAccessible = accessible;
 | 
			
		||||
            this._updateCaretPosition(accessible);
 | 
			
		||||
            this.show(Main.layoutManager.focusIndex);
 | 
			
		||||
        } else if (this._currentAccessible == accessible) {
 | 
			
		||||
            this._currentAccessible = null;
 | 
			
		||||
            this.hide();
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onCaretMoved(caretTracker, event) {
 | 
			
		||||
        let accessible = event.source;
 | 
			
		||||
        if (this._currentAccessible == accessible)
 | 
			
		||||
            this._updateCaretPosition(accessible);
 | 
			
		||||
    _onFocusPositionChanged(focusTracker) {
 | 
			
		||||
        let rect = focusTracker.getCurrentRect();
 | 
			
		||||
        this.setCursorLocation(focusTracker.currentWindow, rect.x, rect.y, rect.width, rect.height);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _lastDeviceIsTouchscreen() {
 | 
			
		||||
@@ -650,8 +640,6 @@ var Keyboard = new Lang.Class({
 | 
			
		||||
        if (!this._enabled && !this._keyboardController)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._setCaretTrackerEnabled(this._enabled);
 | 
			
		||||
 | 
			
		||||
        if (this._enabled && !this._keyboardController)
 | 
			
		||||
            this._setupKeyboard();
 | 
			
		||||
        else if (!this._enabled)
 | 
			
		||||
@@ -936,9 +924,11 @@ var Keyboard = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _relayout() {
 | 
			
		||||
        if (this.actor == null)
 | 
			
		||||
            return;
 | 
			
		||||
        let monitor = Main.layoutManager.keyboardMonitor;
 | 
			
		||||
 | 
			
		||||
        if (this.actor == null || monitor == null)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let maxHeight = monitor.height / 3;
 | 
			
		||||
        this.actor.width = monitor.width;
 | 
			
		||||
        this.actor.height = maxHeight;
 | 
			
		||||
@@ -1027,11 +1017,14 @@ var Keyboard = new Lang.Class({
 | 
			
		||||
        if (!this._keyboardRequested)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (this._currentAccessible)
 | 
			
		||||
            this._updateCaretPosition(this._currentAccessible);
 | 
			
		||||
        Main.layoutManager.keyboardIndex = monitor;
 | 
			
		||||
        this._relayout();
 | 
			
		||||
        Main.layoutManager.showKeyboard();
 | 
			
		||||
 | 
			
		||||
        if (this._delayedAnimFocusWindow) {
 | 
			
		||||
            this._setAnimationWindow(this._delayedAnimFocusWindow);
 | 
			
		||||
            this._delayedAnimFocusWindow = null;
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    hide() {
 | 
			
		||||
@@ -1102,8 +1095,9 @@ var Keyboard = new Lang.Class({
 | 
			
		||||
        window.move_frame(true, frameRect.x, frameRect.y);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _animateWindow(window, show, deltaY) {
 | 
			
		||||
    _animateWindow(window, show) {
 | 
			
		||||
        let windowActor = window.get_compositor_private();
 | 
			
		||||
        let deltaY = Main.layoutManager.keyboardBox.height;
 | 
			
		||||
        if (!windowActor)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
@@ -1124,35 +1118,39 @@ var Keyboard = new Lang.Class({
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setCursorLocation(window, x, y , w, h) {
 | 
			
		||||
        if (window == this._oskFocusWindow)
 | 
			
		||||
    _setAnimationWindow(window) {
 | 
			
		||||
        if (this._animFocusedWindow == window)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (this._oskFocusWindow) {
 | 
			
		||||
            let display = global.screen.get_display();
 | 
			
		||||
        if (this._animFocusedWindow)
 | 
			
		||||
            this._animateWindow(this._animFocusedWindow, false);
 | 
			
		||||
        if (window)
 | 
			
		||||
            this._animateWindow(window, true);
 | 
			
		||||
 | 
			
		||||
            if (display.get_grab_op() == Meta.GrabOp.NONE ||
 | 
			
		||||
                display.get_focus_window() != this._oskFocusWindow)
 | 
			
		||||
                this._animateWindow(this._oskFocusWindow, false, this._oskFocusWindowDelta);
 | 
			
		||||
        this._animFocusedWindow = window;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
            this._oskFocusWindow = null;
 | 
			
		||||
            this._oskFocusWindowDelta = null;
 | 
			
		||||
        }
 | 
			
		||||
    setCursorLocation(window, x, y , w, h) {
 | 
			
		||||
        let monitor = Main.layoutManager.keyboardMonitor;
 | 
			
		||||
 | 
			
		||||
        if (window) {
 | 
			
		||||
            let monitor = Main.layoutManager.keyboardMonitor;
 | 
			
		||||
        if (window && monitor) {
 | 
			
		||||
            let keyboardHeight = Main.layoutManager.keyboardBox.height;
 | 
			
		||||
            let frameRect = window.get_frame_rect();
 | 
			
		||||
            let windowActor = window.get_compositor_private();
 | 
			
		||||
            let delta = 0;
 | 
			
		||||
            let focusObscured = false;
 | 
			
		||||
 | 
			
		||||
            if (frameRect.y + y + h >= monitor.height - keyboardHeight)
 | 
			
		||||
                delta = keyboardHeight;
 | 
			
		||||
 | 
			
		||||
            this._animateWindow(window, true, delta);
 | 
			
		||||
            this._oskFocusWindow = window;
 | 
			
		||||
            this._oskFocusWindowDelta = delta;
 | 
			
		||||
            if (y + h >= monitor.y + monitor.height - keyboardHeight) {
 | 
			
		||||
                if (this._keyboardVisible)
 | 
			
		||||
                    this._setAnimationWindow(window);
 | 
			
		||||
                else
 | 
			
		||||
                    this._delayedAnimFocusWindow = window;
 | 
			
		||||
            } else if (y < keyboardHeight) {
 | 
			
		||||
                this._delayedAnimFocusWindow = null;
 | 
			
		||||
                this._setAnimationWindow(null);
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            this._setAnimationWindow(null);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._oskFocusWindow = window;
 | 
			
		||||
    },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -203,6 +203,7 @@ var LayoutManager = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        // Set up stage hierarchy to group all UI actors under one container.
 | 
			
		||||
        this.uiGroup = new Shell.GenericContainer({ name: 'uiGroup' });
 | 
			
		||||
        this.uiGroup.set_flags(Clutter.ActorFlags.NO_LAYOUT);
 | 
			
		||||
        this.uiGroup.connect('allocate', (actor, box, flags) => {
 | 
			
		||||
            let children = actor.get_children();
 | 
			
		||||
            for (let i = 0; i < children.length; i++)
 | 
			
		||||
@@ -557,6 +558,8 @@ var LayoutManager = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    get focusMonitor() {
 | 
			
		||||
        if (this.focusIndex < 0)
 | 
			
		||||
            return null;
 | 
			
		||||
        return this.monitors[this.focusIndex];
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,6 @@ const MagnifierDBus = imports.ui.magnifierDBus;
 | 
			
		||||
const Params = imports.misc.params;
 | 
			
		||||
const PointerWatcher = imports.ui.pointerWatcher;
 | 
			
		||||
 | 
			
		||||
var MOUSE_POLL_FREQUENCY = 50;
 | 
			
		||||
var CROSSHAIRS_CLIP_SIZE = [100, 100];
 | 
			
		||||
var NO_CHANGE = 0.0;
 | 
			
		||||
 | 
			
		||||
@@ -152,8 +151,10 @@ var Magnifier = new Lang.Class({
 | 
			
		||||
     * Turn on mouse tracking, if not already doing so.
 | 
			
		||||
     */
 | 
			
		||||
    startTrackingMouse() {
 | 
			
		||||
        if (!this._pointerWatch)
 | 
			
		||||
            this._pointerWatch = PointerWatcher.getPointerWatcher().addWatch(MOUSE_POLL_FREQUENCY, this.scrollToMousePos.bind(this));
 | 
			
		||||
        if (!this._pointerWatch) {
 | 
			
		||||
            let interval = 1000 / Clutter.get_default_frame_rate();
 | 
			
		||||
            this._pointerWatch = PointerWatcher.getPointerWatcher().addWatch(interval, this.scrollToMousePos.bind(this));
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 
 | 
			
		||||
@@ -343,6 +343,9 @@ function loadTheme() {
 | 
			
		||||
    let theme = new St.Theme ({ application_stylesheet: _cssStylesheet,
 | 
			
		||||
                                default_stylesheet: _defaultCssStylesheet });
 | 
			
		||||
 | 
			
		||||
    if (theme.default_stylesheet == null)
 | 
			
		||||
        throw new Error("No valid stylesheet found for '%s'".format(sessionMode.stylesheetName));
 | 
			
		||||
 | 
			
		||||
    if (previousTheme) {
 | 
			
		||||
        let customStylesheets = previousTheme.get_custom_stylesheets();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -362,7 +362,8 @@ var Message = new Lang.Class({
 | 
			
		||||
        this.setBody(body);
 | 
			
		||||
 | 
			
		||||
        this._closeButton.connect('clicked', this.close.bind(this));
 | 
			
		||||
        this.actor.connect('notify::hover', this._sync.bind(this));
 | 
			
		||||
        let actorHoverId = this.actor.connect('notify::hover', this._sync.bind(this));
 | 
			
		||||
        this._closeButton.connect('destroy', this.actor.disconnect.bind(this.actor, actorHoverId));
 | 
			
		||||
        this.actor.connect('clicked', this._onClicked.bind(this));
 | 
			
		||||
        this.actor.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
        this._sync();
 | 
			
		||||
 
 | 
			
		||||
@@ -1320,6 +1320,7 @@ var MessageTray = new Lang.Class({
 | 
			
		||||
        this._bannerBin.y = -this._banner.actor.height;
 | 
			
		||||
        this.actor.show();
 | 
			
		||||
 | 
			
		||||
        Meta.disable_unredirect_for_screen(global.screen);
 | 
			
		||||
        this._updateShowingNotification();
 | 
			
		||||
 | 
			
		||||
        let [x, y, mods] = global.get_pointer();
 | 
			
		||||
@@ -1457,6 +1458,7 @@ var MessageTray = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        this._pointerInNotification = false;
 | 
			
		||||
        this._notificationRemoved = false;
 | 
			
		||||
        Meta.enable_unredirect_for_screen(global.screen);
 | 
			
		||||
 | 
			
		||||
        this._banner.actor.destroy();
 | 
			
		||||
        this._banner = null;
 | 
			
		||||
 
 | 
			
		||||
@@ -117,10 +117,8 @@ var FdoNotificationDaemon = new Lang.Class({
 | 
			
		||||
                 bitsPerSample, nChannels, data] = hints['image-data'];
 | 
			
		||||
            return Shell.util_create_pixbuf_from_data(data, GdkPixbuf.Colorspace.RGB, hasAlpha,
 | 
			
		||||
                                                      bitsPerSample, width, height, rowStride);
 | 
			
		||||
        } else if (hints['image-path']) {
 | 
			
		||||
            return new Gio.FileIcon({ file: Gio.File.new_for_path(hints['image-path']) });
 | 
			
		||||
        }
 | 
			
		||||
        return null;
 | 
			
		||||
        return this._iconForNotificationData(hints['image-path']);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _fallbackIconForNotificationData(hints) {
 | 
			
		||||
 
 | 
			
		||||
@@ -108,15 +108,30 @@ var OsdWindow = new Lang.Class({
 | 
			
		||||
        this._hideTimeoutId = 0;
 | 
			
		||||
        this._reset();
 | 
			
		||||
 | 
			
		||||
        Main.layoutManager.connect('monitors-changed',
 | 
			
		||||
                                   this._relayout.bind(this));
 | 
			
		||||
        this.actor.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
 | 
			
		||||
        this._monitorsChangedId =
 | 
			
		||||
            Main.layoutManager.connect('monitors-changed',
 | 
			
		||||
                                       this._relayout.bind(this));
 | 
			
		||||
        let themeContext = St.ThemeContext.get_for_stage(global.stage);
 | 
			
		||||
        themeContext.connect('notify::scale-factor',
 | 
			
		||||
                             this._relayout.bind(this));
 | 
			
		||||
        this._scaleChangedId =
 | 
			
		||||
            themeContext.connect('notify::scale-factor',
 | 
			
		||||
                                 this._relayout.bind(this));
 | 
			
		||||
        this._relayout();
 | 
			
		||||
        Main.uiGroup.add_child(this.actor);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onDestroy() {
 | 
			
		||||
        if (this._monitorsChangedId)
 | 
			
		||||
            Main.layoutManager.disconnect(this._monitorsChangedId);
 | 
			
		||||
        this._monitorsChangedId = 0;
 | 
			
		||||
 | 
			
		||||
        let themeContext = St.ThemeContext.get_for_stage(global.stage);
 | 
			
		||||
        if (this._scaleChangedId)
 | 
			
		||||
            themeContext.disconnect(this._scaleChangedId);
 | 
			
		||||
        this._scaleChangedId = 0;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setIcon(icon) {
 | 
			
		||||
        this._icon.gicon = icon;
 | 
			
		||||
    },
 | 
			
		||||
 
 | 
			
		||||
@@ -393,10 +393,8 @@ var Overview = new Lang.Class({
 | 
			
		||||
        if (!Main.layoutManager.primaryMonitor)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let workArea = Main.layoutManager.getWorkAreaForMonitor(Main.layoutManager.primaryIndex);
 | 
			
		||||
 | 
			
		||||
        this._coverPane.set_position(0, workArea.y);
 | 
			
		||||
        this._coverPane.set_size(workArea.width, workArea.height);
 | 
			
		||||
        this._coverPane.set_position(0, 0);
 | 
			
		||||
        this._coverPane.set_size(global.screen_width, global.screen_height);
 | 
			
		||||
 | 
			
		||||
        this._updateBackgrounds();
 | 
			
		||||
    },
 | 
			
		||||
 
 | 
			
		||||
@@ -284,6 +284,11 @@ var ThumbnailsSlider = new Lang.Class({
 | 
			
		||||
        return child.get_theme_node().get_length('visible-width');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onDragEnd() {
 | 
			
		||||
        this.actor.sync_hover();
 | 
			
		||||
        this.parent();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _getSlide() {
 | 
			
		||||
        if (!this._visible)
 | 
			
		||||
            return 0;
 | 
			
		||||
 
 | 
			
		||||
@@ -796,6 +796,7 @@ var Panel = new Lang.Class({
 | 
			
		||||
        this.actor.connect('get-preferred-height', this._getPreferredHeight.bind(this));
 | 
			
		||||
        this.actor.connect('allocate', this._allocate.bind(this));
 | 
			
		||||
        this.actor.connect('button-press-event', this._onButtonPress.bind(this));
 | 
			
		||||
        this.actor.connect('touch-event', this._onButtonPress.bind(this));
 | 
			
		||||
        this.actor.connect('key-press-event', this._onKeyPress.bind(this));
 | 
			
		||||
 | 
			
		||||
        Main.overview.connect('showing', () => {
 | 
			
		||||
@@ -939,8 +940,13 @@ var Panel = new Lang.Class({
 | 
			
		||||
        if (event.get_source() != actor)
 | 
			
		||||
            return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
 | 
			
		||||
        let button = event.get_button();
 | 
			
		||||
        if (button != 1)
 | 
			
		||||
        let type = event.type();
 | 
			
		||||
        let isPress = type == Clutter.EventType.BUTTON_PRESS;
 | 
			
		||||
        if (!isPress && type != Clutter.EventType.TOUCH_BEGIN)
 | 
			
		||||
            return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
 | 
			
		||||
        let button = isPress ? event.get_button() : -1;
 | 
			
		||||
        if (isPress && button != 1)
 | 
			
		||||
            return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
 | 
			
		||||
        let focusWindow = global.display.focus_window;
 | 
			
		||||
@@ -1079,6 +1085,7 @@ var Panel = new Lang.Class({
 | 
			
		||||
        let windows = activeWorkspace.list_windows().filter(metaWindow => {
 | 
			
		||||
            return metaWindow.is_on_primary_monitor() &&
 | 
			
		||||
                   metaWindow.showing_on_its_workspace() &&
 | 
			
		||||
                   !metaWindow.is_hidden() &&
 | 
			
		||||
                   metaWindow.get_window_type() != Meta.WindowType.DESKTOP;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -141,8 +141,17 @@ var PopupBaseMenuItem = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onKeyPressEvent(actor, event) {
 | 
			
		||||
        let symbol = event.get_key_symbol();
 | 
			
		||||
        let state = event.get_state();
 | 
			
		||||
 | 
			
		||||
        // if user has a modifier down (except capslock)
 | 
			
		||||
        // then don't handle the key press here
 | 
			
		||||
        state &= ~Clutter.ModifierType.LOCK_MASK;
 | 
			
		||||
        state &= Clutter.ModifierType.MODIFIER_MASK;
 | 
			
		||||
 | 
			
		||||
        if (state)
 | 
			
		||||
            return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
 | 
			
		||||
        let symbol = event.get_key_symbol();
 | 
			
		||||
        if (symbol == Clutter.KEY_space || symbol == Clutter.KEY_Return) {
 | 
			
		||||
            this.activate(event);
 | 
			
		||||
            return Clutter.EVENT_STOP;
 | 
			
		||||
 
 | 
			
		||||
@@ -119,9 +119,6 @@ var RemoteMenuItemMapper = new Lang.Class({
 | 
			
		||||
        this._trackerItem = trackerItem;
 | 
			
		||||
 | 
			
		||||
        this.menuItem = new PopupMenu.PopupBaseMenuItem();
 | 
			
		||||
        this._icon = new St.Icon({ style_class: 'popup-menu-icon' });
 | 
			
		||||
        this.menuItem.actor.add_child(this._icon);
 | 
			
		||||
 | 
			
		||||
        this._label = new St.Label();
 | 
			
		||||
        this.menuItem.actor.add_child(this._label);
 | 
			
		||||
        this.menuItem.actor.label_actor = this._label;
 | 
			
		||||
@@ -132,13 +129,11 @@ var RemoteMenuItemMapper = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        this._trackerItem.bind_property('visible', this.menuItem.actor, 'visible', GObject.BindingFlags.SYNC_CREATE);
 | 
			
		||||
 | 
			
		||||
        this._trackerItem.connect('notify::icon', this._updateIcon.bind(this));
 | 
			
		||||
        this._trackerItem.connect('notify::label', this._updateLabel.bind(this));
 | 
			
		||||
        this._trackerItem.connect('notify::sensitive', this._updateSensitivity.bind(this));
 | 
			
		||||
        this._trackerItem.connect('notify::role', this._updateRole.bind(this));
 | 
			
		||||
        this._trackerItem.connect('notify::toggled', this._updateDecoration.bind(this));
 | 
			
		||||
 | 
			
		||||
        this._updateIcon();
 | 
			
		||||
        this._updateLabel();
 | 
			
		||||
        this._updateSensitivity();
 | 
			
		||||
        this._updateRole();
 | 
			
		||||
@@ -148,11 +143,6 @@ var RemoteMenuItemMapper = new Lang.Class({
 | 
			
		||||
        });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateIcon() {
 | 
			
		||||
        this._icon.gicon = this._trackerItem.icon;
 | 
			
		||||
        this._icon.visible = (this._icon.gicon != null);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateLabel() {
 | 
			
		||||
        this._label.text = stripMnemonics(this._trackerItem.label);
 | 
			
		||||
    },
 | 
			
		||||
 
 | 
			
		||||
@@ -114,18 +114,16 @@ var RunDialog = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        this._history = new History.HistoryManager({ gsettingsKey: HISTORY_KEY,
 | 
			
		||||
                                                     entry: this._entryText });
 | 
			
		||||
        this._entryText.connect('activate', (o) => {
 | 
			
		||||
            this.popModal();
 | 
			
		||||
            this._run(o.get_text(),
 | 
			
		||||
                      Clutter.get_current_event().get_state() & Clutter.ModifierType.CONTROL_MASK);
 | 
			
		||||
            if (!this._commandError ||
 | 
			
		||||
                !this.pushModal())
 | 
			
		||||
                this.close();
 | 
			
		||||
        });
 | 
			
		||||
        this._entryText.connect('key-press-event', (o, e) => {
 | 
			
		||||
            let symbol = e.get_key_symbol();
 | 
			
		||||
            if (symbol == Clutter.Return || symbol == Clutter.KP_Enter) {
 | 
			
		||||
                this.popModal();
 | 
			
		||||
                this._run(o.get_text(),
 | 
			
		||||
                          e.get_state() & Clutter.ModifierType.CONTROL_MASK);
 | 
			
		||||
                if (!this._commandError ||
 | 
			
		||||
                    !this.pushModal())
 | 
			
		||||
                    this.close();
 | 
			
		||||
 | 
			
		||||
                return Clutter.EVENT_STOP;
 | 
			
		||||
            }
 | 
			
		||||
            if (symbol == Clutter.Tab) {
 | 
			
		||||
                let text = o.get_text();
 | 
			
		||||
                let prefix;
 | 
			
		||||
 
 | 
			
		||||
@@ -133,7 +133,7 @@ function _callRemote(obj, method, ...args) {
 | 
			
		||||
 * because of the normal X asynchronous mapping process, to actually wait
 | 
			
		||||
 * until the window has been mapped and exposed, use waitTestWindows().
 | 
			
		||||
 */
 | 
			
		||||
function createTestWindow(params) {
 | 
			
		||||
function createTestWindow(width, height, params) {
 | 
			
		||||
    params = Params.parse(params, { width: 640,
 | 
			
		||||
                                    height: 480,
 | 
			
		||||
                                    alpha: false,
 | 
			
		||||
 
 | 
			
		||||
@@ -192,6 +192,7 @@ var SearchResultsBase = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    clear() {
 | 
			
		||||
        this._cancellable.cancel();
 | 
			
		||||
        for (let resultId in this._resultDisplays)
 | 
			
		||||
            this._resultDisplays[resultId].actor.destroy();
 | 
			
		||||
        this._resultDisplays = {};
 | 
			
		||||
@@ -225,6 +226,12 @@ var SearchResultsBase = new Lang.Class({
 | 
			
		||||
            this._cancellable.reset();
 | 
			
		||||
 | 
			
		||||
            this.provider.getResultMetas(metasNeeded, metas => {
 | 
			
		||||
                if (this._cancellable.is_cancelled()) {
 | 
			
		||||
                    if (metas.length > 0)
 | 
			
		||||
                        log(`Search provider ${this.provider.id} returned results after the request was canceled`);
 | 
			
		||||
                    callback(false);
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                if (metas.length != metasNeeded.length) {
 | 
			
		||||
                    log('Wrong number of result metas returned by search provider ' + this.provider.id +
 | 
			
		||||
                        ': expected ' + metasNeeded.length + ' but got ' + metas.length);
 | 
			
		||||
 
 | 
			
		||||
@@ -360,11 +360,14 @@ var InputSourceManager = new Lang.Class({
 | 
			
		||||
        this._settings.connect('per-window-changed', this._sourcesPerWindowChanged.bind(this));
 | 
			
		||||
        this._sourcesPerWindowChanged();
 | 
			
		||||
        this._disableIBus = false;
 | 
			
		||||
        this._reloading = false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    reload() {
 | 
			
		||||
        this._reloading = true;
 | 
			
		||||
        this._keyboardManager.setKeyboardOptions(this._settings.keyboardOptions);
 | 
			
		||||
        this._inputSourcesChanged();
 | 
			
		||||
        this._reloading = false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _ibusReadyCallback(im, ready) {
 | 
			
		||||
@@ -458,7 +461,15 @@ var InputSourceManager = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    activateInputSource(is, interactive) {
 | 
			
		||||
        KeyboardManager.holdKeyboard();
 | 
			
		||||
        // The focus changes during holdKeyboard/releaseKeyboard may trick
 | 
			
		||||
        // the client into hiding UI containing the currently focused entry.
 | 
			
		||||
        // So holdKeyboard/releaseKeyboard are not called when
 | 
			
		||||
        // 'set-content-type' signal is received.
 | 
			
		||||
        // E.g. Focusing on a password entry in a popup in Xorg Firefox
 | 
			
		||||
        // will emit 'set-content-type' signal.
 | 
			
		||||
        // https://gitlab.gnome.org/GNOME/gnome-shell/issues/391
 | 
			
		||||
        if (!this._reloading)
 | 
			
		||||
            KeyboardManager.holdKeyboard();
 | 
			
		||||
        this._keyboardManager.apply(is.xkbId);
 | 
			
		||||
 | 
			
		||||
        // All the "xkb:..." IBus engines simply "echo" back symbols,
 | 
			
		||||
@@ -473,7 +484,10 @@ var InputSourceManager = new Lang.Class({
 | 
			
		||||
        else
 | 
			
		||||
            engine = 'xkb:us::eng';
 | 
			
		||||
 | 
			
		||||
        this._ibusManager.setEngine(engine, KeyboardManager.releaseKeyboard);
 | 
			
		||||
        if (!this._reloading)
 | 
			
		||||
            this._ibusManager.setEngine(engine, KeyboardManager.releaseKeyboard);
 | 
			
		||||
        else
 | 
			
		||||
            this._ibusManager.setEngine(engine);
 | 
			
		||||
        this._currentInputSourceChanged(is);
 | 
			
		||||
 | 
			
		||||
        if (interactive)
 | 
			
		||||
 
 | 
			
		||||
@@ -419,12 +419,14 @@ var NMConnectionDevice = new Lang.Class({
 | 
			
		||||
        this._deactivateItem.actor.visible = this._device.state > NM.DeviceState.DISCONNECTED;
 | 
			
		||||
 | 
			
		||||
        if (this._activeConnection == null) {
 | 
			
		||||
            this._activeConnection = this._device.active_connection;
 | 
			
		||||
 | 
			
		||||
            if (this._activeConnection) {
 | 
			
		||||
                ensureActiveConnectionProps(this._activeConnection, this._client);
 | 
			
		||||
                let item = this._connectionItems.get(this._activeConnection.connection.get_uuid());
 | 
			
		||||
                item.setActiveConnection(this._activeConnection);
 | 
			
		||||
            let activeConnection = this._device.active_connection;
 | 
			
		||||
            if (activeConnection && activeConnection.connection) {
 | 
			
		||||
                let item = this._connectionItems.get(activeConnection.connection.get_uuid());
 | 
			
		||||
                if (item) {
 | 
			
		||||
                    this._activeConnection = activeConnection;
 | 
			
		||||
                    ensureActiveConnectionProps(this._activeConnection, this._client);
 | 
			
		||||
                    item.setActiveConnection(this._activeConnection);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -1944,6 +1946,7 @@ var NMApplet = new Lang.Class({
 | 
			
		||||
        this.indicators.visible = this._client.nm_running;
 | 
			
		||||
        this.menu.actor.visible = this._client.networking_enabled;
 | 
			
		||||
 | 
			
		||||
        this._updateIcon();
 | 
			
		||||
        this._syncConnectivity();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -58,6 +58,9 @@ var AltSwitcher = new Lang.Class({
 | 
			
		||||
            childToShow = this._standard;
 | 
			
		||||
        } else if (this._alternate.visible) {
 | 
			
		||||
            childToShow = this._alternate;
 | 
			
		||||
        } else {
 | 
			
		||||
            this.actor.hide();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let childShown = this.actor.get_child();
 | 
			
		||||
@@ -79,7 +82,7 @@ var AltSwitcher = new Lang.Class({
 | 
			
		||||
            global.sync_pointer();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.actor.visible = (childToShow != null);
 | 
			
		||||
        this.actor.show();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onDestroy() {
 | 
			
		||||
 
 | 
			
		||||
@@ -56,11 +56,12 @@ const BoltDeviceProxy = Gio.DBusProxy.makeProxyWrapper(BoltDeviceInterface);
 | 
			
		||||
 | 
			
		||||
var Status = {
 | 
			
		||||
    DISCONNECTED: 'disconnected',
 | 
			
		||||
    CONNECTING: 'connecting',
 | 
			
		||||
    CONNECTED: 'connected',
 | 
			
		||||
    AUTHORIZING: 'authorizing',
 | 
			
		||||
    AUTH_ERROR: 'auth-error',
 | 
			
		||||
    AUTHORIZED: 'authorized'
 | 
			
		||||
    AUTHORIZED: 'authorized',
 | 
			
		||||
    AUTHORIZED_SECURE: 'authorized-secure',
 | 
			
		||||
    AUTHORIZED_NEWKEY: 'authorized-newkey'
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var Policy = {
 | 
			
		||||
@@ -69,7 +70,7 @@ var Policy = {
 | 
			
		||||
    AUTO: 'auto'
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var AuthCtrl = {
 | 
			
		||||
var AuthFlags = {
 | 
			
		||||
    NONE: 'none',
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -140,10 +141,9 @@ var Client = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    enrollDevice(id, policy, callback) {
 | 
			
		||||
	this._proxy.EnrollDeviceRemote(id, policy, AuthCtrl.NONE,
 | 
			
		||||
	this._proxy.EnrollDeviceRemote(id, policy, AuthFlags.NONE,
 | 
			
		||||
                                       (res, error) => {
 | 
			
		||||
	    if (error) {
 | 
			
		||||
		Gio.DBusError.strip_remote_error(error);
 | 
			
		||||
		callback(null, error);
 | 
			
		||||
		return;
 | 
			
		||||
	    }
 | 
			
		||||
@@ -228,7 +228,7 @@ var AuthRobot = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
    _onEnrollDone(device, error) {
 | 
			
		||||
	if (error)
 | 
			
		||||
	    this.emit('enroll-failed', device, error);
 | 
			
		||||
	    this.emit('enroll-failed', error, device);
 | 
			
		||||
 | 
			
		||||
	/* TODO: scan the list of devices to be authorized for children
 | 
			
		||||
	 *  of this device and remove them (and their children and
 | 
			
		||||
@@ -354,7 +354,7 @@ var Indicator = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
    _onEnrollFailed(obj, device, error) {
 | 
			
		||||
	const title = _('Thunderbolt authorization error');
 | 
			
		||||
	const body = _('Could not authorize the Thunderbolt device: %s'.format(error.message));
 | 
			
		||||
	const body = _('Could not authorize the thunderbolt device: %s'.format(error.message));
 | 
			
		||||
	this._notify(title, body);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -311,6 +311,7 @@ var ViewSelector = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    hide() {
 | 
			
		||||
        this.reset();
 | 
			
		||||
        this._workspacesDisplay.hide();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -459,7 +460,11 @@ var ViewSelector = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    reset() {
 | 
			
		||||
        global.stage.set_key_focus(null);
 | 
			
		||||
        // Don't drop the key focus on Clutter's side if anything but the
 | 
			
		||||
        // overview has pushed a modal (e.g. system modals when activated using
 | 
			
		||||
        // the overview).
 | 
			
		||||
        if (Main.modalCount <= 1)
 | 
			
		||||
            global.stage.set_key_focus(null);
 | 
			
		||||
 | 
			
		||||
        this._entry.text = '';
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -24,7 +24,7 @@ const EdgeDragAction = imports.ui.edgeDragAction;
 | 
			
		||||
const CloseDialog = imports.ui.closeDialog;
 | 
			
		||||
const SwitchMonitor = imports.ui.switchMonitor;
 | 
			
		||||
 | 
			
		||||
const SHELL_KEYBINDINGS_SCHEMA = 'org.gnome.shell.keybindings';
 | 
			
		||||
var SHELL_KEYBINDINGS_SCHEMA = 'org.gnome.shell.keybindings';
 | 
			
		||||
var MINIMIZE_WINDOW_ANIMATION_TIME = 0.2;
 | 
			
		||||
var SHOW_WINDOW_ANIMATION_TIME = 0.15;
 | 
			
		||||
var DIALOG_SHOW_WINDOW_ANIMATION_TIME = 0.1;
 | 
			
		||||
@@ -627,8 +627,8 @@ var AppSwitchAction = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        if (this.get_n_current_points() == 3) {
 | 
			
		||||
            for (let i = 0; i < this.get_n_current_points(); i++) {
 | 
			
		||||
                [startX, startY] = this.get_press_coords(i);
 | 
			
		||||
                [x, y] = this.get_motion_coords(i);
 | 
			
		||||
                let [startX, startY] = this.get_press_coords(i);
 | 
			
		||||
                let [x, y] = this.get_motion_coords(i);
 | 
			
		||||
 | 
			
		||||
                if (Math.abs(x - startX) > MOTION_THRESHOLD ||
 | 
			
		||||
                    Math.abs(y - startY) > MOTION_THRESHOLD)
 | 
			
		||||
@@ -1173,6 +1173,10 @@ var WindowManager = new Lang.Class({
 | 
			
		||||
                yScale = geom.height / actor.height;
 | 
			
		||||
            } else {
 | 
			
		||||
                let monitor = Main.layoutManager.monitors[actor.meta_window.get_monitor()];
 | 
			
		||||
                if (!monitor) {
 | 
			
		||||
                    this._minimizeWindowDone();
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                xDest = monitor.x;
 | 
			
		||||
                yDest = monitor.y;
 | 
			
		||||
                if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
 | 
			
		||||
@@ -1248,6 +1252,11 @@ var WindowManager = new Lang.Class({
 | 
			
		||||
                                geom.height / actor.height);
 | 
			
		||||
            } else {
 | 
			
		||||
                let monitor = Main.layoutManager.monitors[actor.meta_window.get_monitor()];
 | 
			
		||||
                if (!monitor) {
 | 
			
		||||
                    actor.show();
 | 
			
		||||
                    this._unminimizeWindowDone();
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                actor.set_position(monitor.x, monitor.y);
 | 
			
		||||
                if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
 | 
			
		||||
                    actor.x += monitor.width;
 | 
			
		||||
@@ -1754,6 +1763,14 @@ var WindowManager = new Lang.Class({
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < switchData.windows.length; i++) {
 | 
			
		||||
            let w = switchData.windows[i];
 | 
			
		||||
 | 
			
		||||
            w.windowDestroyId = w.window.connect('destroy', () => {
 | 
			
		||||
                switchData.windows.splice(switchData.windows.indexOf(w), 1);
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        switchData.inGroup.set_position(-xDest, -yDest);
 | 
			
		||||
        switchData.inGroup.raise_top();
 | 
			
		||||
 | 
			
		||||
@@ -1784,8 +1801,8 @@ var WindowManager = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < switchData.windows.length; i++) {
 | 
			
		||||
                let w = switchData.windows[i];
 | 
			
		||||
                if (w.window.is_destroyed()) // Window gone
 | 
			
		||||
                    continue;
 | 
			
		||||
                w.window.disconnect(w.windowDestroyId);
 | 
			
		||||
 | 
			
		||||
                if (w.window.get_parent() == switchData.outGroup) {
 | 
			
		||||
                    w.window.reparent(w.parent);
 | 
			
		||||
                    w.window.hide();
 | 
			
		||||
 
 | 
			
		||||
@@ -128,11 +128,10 @@ var WindowMenu = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        let screen = global.screen;
 | 
			
		||||
        let nMonitors = screen.get_n_monitors();
 | 
			
		||||
        if (nMonitors > 1) {
 | 
			
		||||
        let monitorIndex = window.get_monitor();
 | 
			
		||||
        if (nMonitors > 1 && monitorIndex >= 0) {
 | 
			
		||||
            this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
 | 
			
		||||
 | 
			
		||||
            let monitorIndex = window.get_monitor();
 | 
			
		||||
 | 
			
		||||
            let dir = Meta.ScreenDirection.UP;
 | 
			
		||||
            let upMonitorIndex =
 | 
			
		||||
                screen.get_monitor_neighbor_index(monitorIndex, dir);
 | 
			
		||||
 
 | 
			
		||||
@@ -137,8 +137,10 @@ var WindowClone = new Lang.Class({
 | 
			
		||||
        this._dragSlot = [0, 0, 0, 0];
 | 
			
		||||
        this._stackAbove = null;
 | 
			
		||||
 | 
			
		||||
        this._windowClone._updateId = this.metaWindow.connect('size-changed',
 | 
			
		||||
            this._onRealWindowSizeChanged.bind(this));
 | 
			
		||||
        this._windowClone._sizeChangedId = this.metaWindow.connect('size-changed',
 | 
			
		||||
            this._onMetaWindowSizeChanged.bind(this));
 | 
			
		||||
        this._windowClone._posChangedId = this.metaWindow.connect('position-changed',
 | 
			
		||||
            this._computeBoundingBox.bind(this));
 | 
			
		||||
        this._windowClone._destroyId =
 | 
			
		||||
            this.realWindow.connect('destroy', () => {
 | 
			
		||||
                // First destroy the clone and then destroy everything
 | 
			
		||||
@@ -206,8 +208,7 @@ var WindowClone = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
    addAttachedDialog(win) {
 | 
			
		||||
        this._doAddAttachedDialog(win, win.get_compositor_private());
 | 
			
		||||
        this._computeBoundingBox();
 | 
			
		||||
        this.emit('size-changed');
 | 
			
		||||
        this._onMetaWindowSizeChanged();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    hasAttachedDialogs() {
 | 
			
		||||
@@ -216,15 +217,14 @@ var WindowClone = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
    _doAddAttachedDialog(metaWin, realWin) {
 | 
			
		||||
        let clone = new Clutter.Clone({ source: realWin });
 | 
			
		||||
        clone._updateId = metaWin.connect('size-changed', () => {
 | 
			
		||||
            this._computeBoundingBox();
 | 
			
		||||
            this.emit('size-changed');
 | 
			
		||||
        });
 | 
			
		||||
        clone._sizeChangedId = metaWin.connect('size-changed',
 | 
			
		||||
            this._onMetaWindowSizeChanged.bind(this));
 | 
			
		||||
        clone._posChangedId = metaWin.connect('position-changed',
 | 
			
		||||
            this._onMetaWindowSizeChanged.bind(this));
 | 
			
		||||
        clone._destroyId = realWin.connect('destroy', () => {
 | 
			
		||||
            clone.destroy();
 | 
			
		||||
 | 
			
		||||
            this._computeBoundingBox();
 | 
			
		||||
            this.emit('size-changed');
 | 
			
		||||
            this._onMetaWindowSizeChanged();
 | 
			
		||||
        });
 | 
			
		||||
        this.actor.add_child(clone);
 | 
			
		||||
    },
 | 
			
		||||
@@ -321,12 +321,13 @@ var WindowClone = new Lang.Class({
 | 
			
		||||
            else
 | 
			
		||||
                realWindow = child.source;
 | 
			
		||||
 | 
			
		||||
            realWindow.meta_window.disconnect(child._updateId);
 | 
			
		||||
            realWindow.meta_window.disconnect(child._sizeChangedId);
 | 
			
		||||
            realWindow.meta_window.disconnect(child._posChangedId);
 | 
			
		||||
            realWindow.disconnect(child._destroyId);
 | 
			
		||||
        });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onRealWindowSizeChanged() {
 | 
			
		||||
    _onMetaWindowSizeChanged() {
 | 
			
		||||
        this._computeBoundingBox();
 | 
			
		||||
        this.emit('size-changed');
 | 
			
		||||
    },
 | 
			
		||||
@@ -469,7 +470,6 @@ var WindowOverlay = new Lang.Class({
 | 
			
		||||
        this._windowAddedId = 0;
 | 
			
		||||
 | 
			
		||||
        button.hide();
 | 
			
		||||
        title.hide();
 | 
			
		||||
 | 
			
		||||
        this.title = title;
 | 
			
		||||
        this.closeButton = button;
 | 
			
		||||
@@ -544,12 +544,10 @@ var WindowOverlay = new Lang.Class({
 | 
			
		||||
        let titleX = cloneX + (cloneWidth - title.width) / 2;
 | 
			
		||||
        let titleY = cloneY + cloneHeight - (title.height - this.borderSize) / 2;
 | 
			
		||||
 | 
			
		||||
        if (animate) {
 | 
			
		||||
            this._animateOverlayActor(title, Math.floor(titleX), Math.floor(titleY), title.width);
 | 
			
		||||
        } else {
 | 
			
		||||
            title.width = title.width;
 | 
			
		||||
        if (animate)
 | 
			
		||||
            this._animateOverlayActor(title, Math.floor(titleX), Math.floor(titleY));
 | 
			
		||||
        else
 | 
			
		||||
            title.set_position(Math.floor(titleX), Math.floor(titleY));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let borderX = cloneX - this.borderSize;
 | 
			
		||||
        let borderY = cloneY - this.borderSize;
 | 
			
		||||
@@ -568,10 +566,12 @@ var WindowOverlay = new Lang.Class({
 | 
			
		||||
    _animateOverlayActor(actor, x, y, width, height) {
 | 
			
		||||
        let params = { x: x,
 | 
			
		||||
                       y: y,
 | 
			
		||||
                       width: width,
 | 
			
		||||
                       time: Overview.ANIMATION_TIME,
 | 
			
		||||
                       transition: 'easeOutQuad' };
 | 
			
		||||
 | 
			
		||||
        if (width !== undefined)
 | 
			
		||||
            params.width = width;
 | 
			
		||||
 | 
			
		||||
        if (height !== undefined)
 | 
			
		||||
            params.height = height;
 | 
			
		||||
 | 
			
		||||
@@ -1431,34 +1431,26 @@ var Workspace = new Lang.Class({
 | 
			
		||||
    _doRemoveWindow(metaWin) {
 | 
			
		||||
        let win = metaWin.get_compositor_private();
 | 
			
		||||
 | 
			
		||||
        // find the position of the window in our list
 | 
			
		||||
        let index = this._lookupIndex (metaWin);
 | 
			
		||||
        let clone = this._removeWindowClone(metaWin);
 | 
			
		||||
 | 
			
		||||
        if (index == -1)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let clone = this._windows[index];
 | 
			
		||||
 | 
			
		||||
        this._windows.splice(index, 1);
 | 
			
		||||
        this._windowOverlays.splice(index, 1);
 | 
			
		||||
 | 
			
		||||
        // If metaWin.get_compositor_private() returned non-NULL, that
 | 
			
		||||
        // means the window still exists (and is just being moved to
 | 
			
		||||
        // another workspace or something), so set its overviewHint
 | 
			
		||||
        // accordingly. (If it returned NULL, then the window is being
 | 
			
		||||
        // destroyed; we'd like to animate this, but it's too late at
 | 
			
		||||
        // this point.)
 | 
			
		||||
        if (win) {
 | 
			
		||||
            let [stageX, stageY] = clone.actor.get_transformed_position();
 | 
			
		||||
            let [stageWidth, stageHeight] = clone.actor.get_transformed_size();
 | 
			
		||||
            win._overviewHint = {
 | 
			
		||||
                x: stageX,
 | 
			
		||||
                y: stageY,
 | 
			
		||||
                scale: stageWidth / clone.actor.width
 | 
			
		||||
            };
 | 
			
		||||
        if (clone) {
 | 
			
		||||
            // If metaWin.get_compositor_private() returned non-NULL, that
 | 
			
		||||
            // means the window still exists (and is just being moved to
 | 
			
		||||
            // another workspace or something), so set its overviewHint
 | 
			
		||||
            // accordingly. (If it returned NULL, then the window is being
 | 
			
		||||
            // destroyed; we'd like to animate this, but it's too late at
 | 
			
		||||
            // this point.)
 | 
			
		||||
            if (win) {
 | 
			
		||||
                let [stageX, stageY] = clone.actor.get_transformed_position();
 | 
			
		||||
                let [stageWidth, stageHeight] = clone.actor.get_transformed_size();
 | 
			
		||||
                win._overviewHint = {
 | 
			
		||||
                    x: stageX,
 | 
			
		||||
                    y: stageY,
 | 
			
		||||
                    scale: stageWidth / clone.actor.width
 | 
			
		||||
                };
 | 
			
		||||
            }
 | 
			
		||||
            clone.destroy();
 | 
			
		||||
        }
 | 
			
		||||
        clone.destroy();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        // We need to reposition the windows; to avoid shuffling windows
 | 
			
		||||
        // around while the user is interacting with the workspace, we delay
 | 
			
		||||
@@ -1514,7 +1506,7 @@ var Workspace = new Lang.Class({
 | 
			
		||||
            if (metaWin.is_attached_dialog()) {
 | 
			
		||||
                let parent = metaWin.get_transient_for();
 | 
			
		||||
                while (parent.is_attached_dialog())
 | 
			
		||||
                    parent = metaWin.get_transient_for();
 | 
			
		||||
                    parent = parent.get_transient_for();
 | 
			
		||||
 | 
			
		||||
                let idx = this._lookupIndex (parent);
 | 
			
		||||
                if (idx < 0) {
 | 
			
		||||
@@ -1848,6 +1840,9 @@ var Workspace = new Lang.Class({
 | 
			
		||||
        clone.connect('size-changed', () => {
 | 
			
		||||
            this._recalculateWindowPositions(WindowPositionFlags.NONE);
 | 
			
		||||
        });
 | 
			
		||||
        clone.actor.connect('destroy', () => {
 | 
			
		||||
            this._removeWindowClone(clone.metaWindow);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this.actor.add_actor(clone.actor);
 | 
			
		||||
 | 
			
		||||
@@ -1869,6 +1864,17 @@ var Workspace = new Lang.Class({
 | 
			
		||||
        return [clone, overlay];
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _removeWindowClone(metaWin) {
 | 
			
		||||
        // find the position of the window in our list
 | 
			
		||||
        let index = this._lookupIndex (metaWin);
 | 
			
		||||
 | 
			
		||||
        if (index == -1)
 | 
			
		||||
            return null;
 | 
			
		||||
 | 
			
		||||
        this._windowOverlays.splice(index, 1);
 | 
			
		||||
        return this._windows.splice(index, 1).pop();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onShowOverlayClose(windowOverlay) {
 | 
			
		||||
        for (let i = 0; i < this._windowOverlays.length; i++) {
 | 
			
		||||
            let overlay = this._windowOverlays[i];
 | 
			
		||||
 
 | 
			
		||||
@@ -31,7 +31,7 @@ var WORKSPACE_CUT_SIZE = 10;
 | 
			
		||||
 | 
			
		||||
var WORKSPACE_KEEP_ALIVE_TIME = 100;
 | 
			
		||||
 | 
			
		||||
const OVERRIDE_SCHEMA = 'org.gnome.shell.overrides';
 | 
			
		||||
var OVERRIDE_SCHEMA = 'org.gnome.shell.overrides';
 | 
			
		||||
 | 
			
		||||
/* A layout manager that requests size only for primary_actor, but then allocates
 | 
			
		||||
   all using a fixed layout */
 | 
			
		||||
@@ -68,7 +68,7 @@ var WindowClone = new Lang.Class({
 | 
			
		||||
        this.realWindow = realWindow;
 | 
			
		||||
        this.metaWindow = realWindow.meta_window;
 | 
			
		||||
 | 
			
		||||
        this.clone._updateId = this.metaWindow.connect('position-changed',
 | 
			
		||||
        this.clone._updateId = this.realWindow.connect('notify::position',
 | 
			
		||||
                                                       this._onPositionChanged.bind(this));
 | 
			
		||||
        this.clone._destroyId = this.realWindow.connect('destroy', () => {
 | 
			
		||||
            // First destroy the clone and then destroy everything
 | 
			
		||||
@@ -153,7 +153,7 @@ var WindowClone = new Lang.Class({
 | 
			
		||||
        let clone = new Clutter.Clone({ source: realDialog });
 | 
			
		||||
        this._updateDialogPosition(realDialog, clone);
 | 
			
		||||
 | 
			
		||||
        clone._updateId = metaDialog.connect('position-changed', dialog => {
 | 
			
		||||
        clone._updateId = realDialog.connect('notify::position', dialog => {
 | 
			
		||||
            this._updateDialogPosition(dialog, clone);
 | 
			
		||||
        });
 | 
			
		||||
        clone._destroyId = realDialog.connect('destroy', () => {
 | 
			
		||||
@@ -171,7 +171,6 @@ var WindowClone = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onPositionChanged() {
 | 
			
		||||
        let rect = this.metaWindow.get_frame_rect();
 | 
			
		||||
        this.actor.set_position(this.realWindow.x, this.realWindow.y);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -179,7 +178,7 @@ var WindowClone = new Lang.Class({
 | 
			
		||||
        this.actor.get_children().forEach(child => {
 | 
			
		||||
            let realWindow = child.source;
 | 
			
		||||
 | 
			
		||||
            realWindow.meta_window.disconnect(child._updateId);
 | 
			
		||||
            realWindow.disconnect(child._updateId);
 | 
			
		||||
            realWindow.disconnect(child._destroyId);
 | 
			
		||||
        });
 | 
			
		||||
    },
 | 
			
		||||
@@ -241,7 +240,7 @@ var WindowClone = new Lang.Class({
 | 
			
		||||
Signals.addSignalMethods(WindowClone.prototype);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const ThumbnailState = {
 | 
			
		||||
var ThumbnailState = {
 | 
			
		||||
    NEW   :         0,
 | 
			
		||||
    ANIMATING_IN :  1,
 | 
			
		||||
    NORMAL:         2,
 | 
			
		||||
@@ -372,18 +371,9 @@ var WorkspaceThumbnail = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _doRemoveWindow(metaWin) {
 | 
			
		||||
        let win = metaWin.get_compositor_private();
 | 
			
		||||
 | 
			
		||||
        // find the position of the window in our list
 | 
			
		||||
        let index = this._lookupIndex (metaWin);
 | 
			
		||||
 | 
			
		||||
        if (index == -1)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let clone = this._windows[index];
 | 
			
		||||
        this._windows.splice(index, 1);
 | 
			
		||||
 | 
			
		||||
        clone.destroy();
 | 
			
		||||
        let clone = this._removeWindowClone(metaWin);
 | 
			
		||||
        if (clone)
 | 
			
		||||
            clone.destroy();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _doAddWindow(metaWin) {
 | 
			
		||||
@@ -426,7 +416,7 @@ var WorkspaceThumbnail = new Lang.Class({
 | 
			
		||||
        } else if (metaWin.is_attached_dialog()) {
 | 
			
		||||
            let parent = metaWin.get_transient_for();
 | 
			
		||||
            while (parent.is_attached_dialog())
 | 
			
		||||
                parent = metaWin.get_transient_for();
 | 
			
		||||
                parent = parent.get_transient_for();
 | 
			
		||||
 | 
			
		||||
            let idx = this._lookupIndex (parent);
 | 
			
		||||
            if (idx < 0) {
 | 
			
		||||
@@ -535,6 +525,9 @@ var WorkspaceThumbnail = new Lang.Class({
 | 
			
		||||
        clone.connect('drag-end', () => {
 | 
			
		||||
            Main.overview.endWindowDrag(clone.metaWindow);
 | 
			
		||||
        });
 | 
			
		||||
        clone.actor.connect('destroy', () => {
 | 
			
		||||
            this._removeWindowClone(clone.metaWindow);
 | 
			
		||||
        });
 | 
			
		||||
        this._contents.add_actor(clone.actor);
 | 
			
		||||
 | 
			
		||||
        if (this._windows.length == 0)
 | 
			
		||||
@@ -547,6 +540,16 @@ var WorkspaceThumbnail = new Lang.Class({
 | 
			
		||||
        return clone;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _removeWindowClone(metaWin) {
 | 
			
		||||
        // find the position of the window in our list
 | 
			
		||||
        let index = this._lookupIndex (metaWin);
 | 
			
		||||
 | 
			
		||||
        if (index == -1)
 | 
			
		||||
            return null;
 | 
			
		||||
 | 
			
		||||
        return this._windows.splice(index, 1).pop();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    activate(time) {
 | 
			
		||||
        if (this.state > ThumbnailState.NORMAL)
 | 
			
		||||
            return;
 | 
			
		||||
@@ -673,7 +676,11 @@ var ThumbnailsBox = new Lang.Class({
 | 
			
		||||
        this._settings.connect('changed::dynamic-workspaces',
 | 
			
		||||
            this._updateSwitcherVisibility.bind(this));
 | 
			
		||||
 | 
			
		||||
        Main.layoutManager.connect('monitors-changed', this._rebuildThumbnails.bind(this));
 | 
			
		||||
        Main.layoutManager.connect('monitors-changed', () => {
 | 
			
		||||
            this._destroyThumbnails();
 | 
			
		||||
            if (Main.overview.visible)
 | 
			
		||||
                this._createThumbnails();
 | 
			
		||||
        });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateSwitcherVisibility() {
 | 
			
		||||
@@ -866,9 +873,6 @@ var ThumbnailsBox = new Lang.Class({
 | 
			
		||||
            Main.overview.connect('windows-restacked',
 | 
			
		||||
                                  this._syncStacking.bind(this));
 | 
			
		||||
 | 
			
		||||
        this._workareasChangedId =
 | 
			
		||||
            global.screen.connect('workareas-changed', this._rebuildThumbnails.bind(this));
 | 
			
		||||
 | 
			
		||||
        this._targetScale = 0;
 | 
			
		||||
        this._scale = 0;
 | 
			
		||||
        this._pendingScaleUpdate = false;
 | 
			
		||||
@@ -884,9 +888,6 @@ var ThumbnailsBox = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _destroyThumbnails() {
 | 
			
		||||
        if (this._thumbnails.length == 0)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (this._switchWorkspaceNotifyId > 0) {
 | 
			
		||||
            global.window_manager.disconnect(this._switchWorkspaceNotifyId);
 | 
			
		||||
            this._switchWorkspaceNotifyId = 0;
 | 
			
		||||
@@ -901,24 +902,12 @@ var ThumbnailsBox = new Lang.Class({
 | 
			
		||||
            this._syncStackingId = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this._workareasChangedId > 0) {
 | 
			
		||||
            global.screen.disconnect(this._workareasChangedId);
 | 
			
		||||
            this._workareasChangedId = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (let w = 0; w < this._thumbnails.length; w++)
 | 
			
		||||
            this._thumbnails[w].destroy();
 | 
			
		||||
        this._thumbnails = [];
 | 
			
		||||
        this._porthole = null;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _rebuildThumbnails() {
 | 
			
		||||
        this._destroyThumbnails();
 | 
			
		||||
 | 
			
		||||
        if (Main.overview.visible)
 | 
			
		||||
            this._createThumbnails();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _workspacesChanged() {
 | 
			
		||||
        let validThumbnails =
 | 
			
		||||
            this._thumbnails.filter(t => t.state <= ThumbnailState.NORMAL);
 | 
			
		||||
 
 | 
			
		||||
@@ -470,6 +470,7 @@ var WorkspacesDisplay = new Lang.Class({
 | 
			
		||||
        this._switchWorkspaceNotifyId = 0;
 | 
			
		||||
 | 
			
		||||
        this._notifyOpacityId = 0;
 | 
			
		||||
        this._restackedNotifyId = 0;
 | 
			
		||||
        this._scrollEventId = 0;
 | 
			
		||||
        this._keyPressEventId = 0;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
project('gnome-shell', 'c',
 | 
			
		||||
  version: '3.29.1',
 | 
			
		||||
  version: '3.28.4',
 | 
			
		||||
  meson_version: '>= 0.42.0',
 | 
			
		||||
  license: 'GPLv2+'
 | 
			
		||||
)
 | 
			
		||||
@@ -23,7 +23,7 @@ gi_req = '>= 1.49.1'
 | 
			
		||||
gjs_req = '>= 1.47.0'
 | 
			
		||||
gtk_req = '>= 3.15.0'
 | 
			
		||||
json_glib_req = '>= 0.13.2'
 | 
			
		||||
mutter_req = '>= 3.29.1'
 | 
			
		||||
mutter_req = '>= 3.28.0'
 | 
			
		||||
polkit_req = '>= 0.100'
 | 
			
		||||
schemas_req = '>= 3.21.3'
 | 
			
		||||
startup_req = '>= 0.11'
 | 
			
		||||
@@ -31,7 +31,7 @@ ibus_req = '>= 1.5.2'
 | 
			
		||||
 | 
			
		||||
bt_req = '>= 3.9.0'
 | 
			
		||||
gst_req = '>= 0.11.92'
 | 
			
		||||
nm_req = '>= 1.10.4'
 | 
			
		||||
nm_req = '>= 0.9.8'
 | 
			
		||||
secret_req = '>= 0.18'
 | 
			
		||||
 | 
			
		||||
gnome = import('gnome')
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										64
									
								
								po/cs.po
									
									
									
									
									
								
							
							
						
						
									
										64
									
								
								po/cs.po
									
									
									
									
									
								
							@@ -11,8 +11,8 @@ msgid ""
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Project-Id-Version: gnome-shell\n"
 | 
			
		||||
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-shell/issues\n"
 | 
			
		||||
"POT-Creation-Date: 2018-04-13 19:54+0000\n"
 | 
			
		||||
"PO-Revision-Date: 2018-04-24 17:32+0200\n"
 | 
			
		||||
"POT-Creation-Date: 2018-02-26 12:57+0000\n"
 | 
			
		||||
"PO-Revision-Date: 2018-02-26 17:57+0100\n"
 | 
			
		||||
"Last-Translator: Marek Černocký <marek@manet.cz>\n"
 | 
			
		||||
"Language-Team: čeština <gnome-cs-list@gnome.org>\n"
 | 
			
		||||
"Language: cs\n"
 | 
			
		||||
@@ -332,7 +332,7 @@ msgstr ""
 | 
			
		||||
"Nastala chyba při načítání dialogového okna předvoleb pro rozšíření %s:"
 | 
			
		||||
 | 
			
		||||
#: js/gdm/authPrompt.js:147 js/ui/audioDeviceSelection.js:71
 | 
			
		||||
#: js/ui/components/networkAgent.js:117 js/ui/components/polkitAgent.js:153
 | 
			
		||||
#: js/ui/components/networkAgent.js:117 js/ui/components/polkitAgent.js:148
 | 
			
		||||
#: js/ui/endSessionDialog.js:482 js/ui/extensionDownloader.js:197
 | 
			
		||||
#: js/ui/shellMountOperation.js:343 js/ui/status/network.js:919
 | 
			
		||||
msgid "Cancel"
 | 
			
		||||
@@ -667,12 +667,12 @@ msgstr "Přidat mezi oblíbené"
 | 
			
		||||
msgid "Show Details"
 | 
			
		||||
msgstr "Zobrazit podrobnosti"
 | 
			
		||||
 | 
			
		||||
#: js/ui/appFavorites.js:140
 | 
			
		||||
#: js/ui/appFavorites.js:138
 | 
			
		||||
#, javascript-format
 | 
			
		||||
msgid "%s has been added to your favorites."
 | 
			
		||||
msgstr "%s byl přidán mezi oblíbené."
 | 
			
		||||
 | 
			
		||||
#: js/ui/appFavorites.js:174
 | 
			
		||||
#: js/ui/appFavorites.js:172
 | 
			
		||||
#, javascript-format
 | 
			
		||||
msgid "%s has been removed from your favorites."
 | 
			
		||||
msgstr "%s byl odstraněn z oblíbených."
 | 
			
		||||
@@ -867,7 +867,7 @@ msgstr "Externí svazek odpojen"
 | 
			
		||||
msgid "Open with %s"
 | 
			
		||||
msgstr "Otevřít pomocí %s"
 | 
			
		||||
 | 
			
		||||
#: js/ui/components/keyring.js:107 js/ui/components/polkitAgent.js:295
 | 
			
		||||
#: js/ui/components/keyring.js:107 js/ui/components/polkitAgent.js:284
 | 
			
		||||
msgid "Password:"
 | 
			
		||||
msgstr "Heslo:"
 | 
			
		||||
 | 
			
		||||
@@ -955,15 +955,15 @@ msgstr "Pro připojení k „%s“ je vyžadováno heslo."
 | 
			
		||||
msgid "Network Manager"
 | 
			
		||||
msgstr "Network Manager"
 | 
			
		||||
 | 
			
		||||
#: js/ui/components/polkitAgent.js:48
 | 
			
		||||
#: js/ui/components/polkitAgent.js:43
 | 
			
		||||
msgid "Authentication Required"
 | 
			
		||||
msgstr "Je vyžadováno ověření"
 | 
			
		||||
 | 
			
		||||
#: js/ui/components/polkitAgent.js:76
 | 
			
		||||
#: js/ui/components/polkitAgent.js:71
 | 
			
		||||
msgid "Administrator"
 | 
			
		||||
msgstr "Správce"
 | 
			
		||||
 | 
			
		||||
#: js/ui/components/polkitAgent.js:156
 | 
			
		||||
#: js/ui/components/polkitAgent.js:151
 | 
			
		||||
msgid "Authenticate"
 | 
			
		||||
msgstr "Ověřit"
 | 
			
		||||
 | 
			
		||||
@@ -971,7 +971,7 @@ msgstr "Ověřit"
 | 
			
		||||
#. * requested authentication was not gained; this can happen
 | 
			
		||||
#. * because of an authentication error (like invalid password),
 | 
			
		||||
#. * for instance.
 | 
			
		||||
#: js/ui/components/polkitAgent.js:281 js/ui/shellMountOperation.js:327
 | 
			
		||||
#: js/ui/components/polkitAgent.js:270 js/ui/shellMountOperation.js:327
 | 
			
		||||
msgid "Sorry, that didn’t work. Please try again."
 | 
			
		||||
msgstr "Ověření bohužel nebylo úspěšné. Zkuste to prosím znovu."
 | 
			
		||||
 | 
			
		||||
@@ -1021,7 +1021,7 @@ msgstr "Přidat světový čas…"
 | 
			
		||||
msgid "World Clocks"
 | 
			
		||||
msgstr "Světové hodiny"
 | 
			
		||||
 | 
			
		||||
#: js/ui/dateMenu.js:227
 | 
			
		||||
#: js/ui/dateMenu.js:225
 | 
			
		||||
msgid "Weather"
 | 
			
		||||
msgstr "Počasí"
 | 
			
		||||
 | 
			
		||||
@@ -1029,7 +1029,7 @@ msgstr "Počasí"
 | 
			
		||||
#. libgweather for the possible condition strings. If at all
 | 
			
		||||
#. possible, the sentence should match the grammatical case etc. of
 | 
			
		||||
#. the inserted conditions.
 | 
			
		||||
#: js/ui/dateMenu.js:291
 | 
			
		||||
#: js/ui/dateMenu.js:289
 | 
			
		||||
#, javascript-format
 | 
			
		||||
msgid "%s all day."
 | 
			
		||||
msgstr "%s celý den."
 | 
			
		||||
@@ -1038,7 +1038,7 @@ msgstr "%s celý den."
 | 
			
		||||
#. libgweather for the possible condition strings. If at all
 | 
			
		||||
#. possible, the sentence should match the grammatical case etc. of
 | 
			
		||||
#. the inserted conditions.
 | 
			
		||||
#: js/ui/dateMenu.js:297
 | 
			
		||||
#: js/ui/dateMenu.js:295
 | 
			
		||||
#, javascript-format
 | 
			
		||||
msgid "%s, then %s later."
 | 
			
		||||
msgstr "%s, později %s."
 | 
			
		||||
@@ -1047,30 +1047,30 @@ msgstr "%s, později %s."
 | 
			
		||||
#. libgweather for the possible condition strings. If at all
 | 
			
		||||
#. possible, the sentence should match the grammatical case etc. of
 | 
			
		||||
#. the inserted conditions.
 | 
			
		||||
#: js/ui/dateMenu.js:303
 | 
			
		||||
#: js/ui/dateMenu.js:301
 | 
			
		||||
#, javascript-format
 | 
			
		||||
msgid "%s, then %s, followed by %s later."
 | 
			
		||||
msgstr "%s, pak %s a později %s."
 | 
			
		||||
 | 
			
		||||
#: js/ui/dateMenu.js:314
 | 
			
		||||
#: js/ui/dateMenu.js:312
 | 
			
		||||
msgid "Select a location…"
 | 
			
		||||
msgstr "Vybrat místo…"
 | 
			
		||||
 | 
			
		||||
#: js/ui/dateMenu.js:317
 | 
			
		||||
#: js/ui/dateMenu.js:315
 | 
			
		||||
msgid "Loading…"
 | 
			
		||||
msgstr "Načítá se…"
 | 
			
		||||
 | 
			
		||||
#. Translators: %s is a temperature with unit, e.g. "23℃"
 | 
			
		||||
#: js/ui/dateMenu.js:323
 | 
			
		||||
#: js/ui/dateMenu.js:321
 | 
			
		||||
#, javascript-format
 | 
			
		||||
msgid "Feels like %s."
 | 
			
		||||
msgstr "Pocitově jako %s."
 | 
			
		||||
msgstr "Pocitová teplota %s."
 | 
			
		||||
 | 
			
		||||
#: js/ui/dateMenu.js:326
 | 
			
		||||
#: js/ui/dateMenu.js:324
 | 
			
		||||
msgid "Go online for weather information"
 | 
			
		||||
msgstr "Připojit se kvůli informacím o počasí"
 | 
			
		||||
 | 
			
		||||
#: js/ui/dateMenu.js:328
 | 
			
		||||
#: js/ui/dateMenu.js:326
 | 
			
		||||
msgid "Weather information is currently unavailable"
 | 
			
		||||
msgstr "Informace o počasí nejsou nyní dostupné"
 | 
			
		||||
 | 
			
		||||
@@ -1986,16 +1986,16 @@ msgstr "Uspat do paměti"
 | 
			
		||||
msgid "Power Off"
 | 
			
		||||
msgstr "Vypnout"
 | 
			
		||||
 | 
			
		||||
#: js/ui/status/thunderbolt.js:294
 | 
			
		||||
#: js/ui/status/thunderbolt.js:272
 | 
			
		||||
msgid "Thunderbolt"
 | 
			
		||||
msgstr "Thunderbolt"
 | 
			
		||||
 | 
			
		||||
#. we are done
 | 
			
		||||
#: js/ui/status/thunderbolt.js:350
 | 
			
		||||
#: js/ui/status/thunderbolt.js:328
 | 
			
		||||
msgid "Unknown Thunderbolt device"
 | 
			
		||||
msgstr "Neznámé zařízení Thunderbolt"
 | 
			
		||||
 | 
			
		||||
#: js/ui/status/thunderbolt.js:351
 | 
			
		||||
#: js/ui/status/thunderbolt.js:329
 | 
			
		||||
msgid ""
 | 
			
		||||
"New device has been detected while you were away. Please disconnect and "
 | 
			
		||||
"reconnect the device to start using it."
 | 
			
		||||
@@ -2003,13 +2003,13 @@ msgstr ""
 | 
			
		||||
"Zatímco jste byli pryč, bylo nalezeno nové zařízení. Odpojte jej prosím a "
 | 
			
		||||
"znovu připojte, abyste jej mohli používat."
 | 
			
		||||
 | 
			
		||||
#: js/ui/status/thunderbolt.js:356
 | 
			
		||||
#: js/ui/status/thunderbolt.js:334
 | 
			
		||||
msgid "Thunderbolt authorization error"
 | 
			
		||||
msgstr "Chyba ověření Thunderbolt"
 | 
			
		||||
 | 
			
		||||
#: js/ui/status/thunderbolt.js:357
 | 
			
		||||
#: js/ui/status/thunderbolt.js:335
 | 
			
		||||
#, javascript-format
 | 
			
		||||
msgid "Could not authorize the Thunderbolt device: %s"
 | 
			
		||||
msgid "Could not authorize the thunderbolt device: %s"
 | 
			
		||||
msgstr "Nezdařilo se provést ověření zařízení Thunderbolt: %s"
 | 
			
		||||
 | 
			
		||||
#: js/ui/status/volume.js:128
 | 
			
		||||
@@ -2233,3 +2233,15 @@ msgstr[2] "%u vstupů"
 | 
			
		||||
#: subprojects/gvc/gvc-mixer-control.c:2738
 | 
			
		||||
msgid "System Sounds"
 | 
			
		||||
msgstr "Systémové zvuky"
 | 
			
		||||
 | 
			
		||||
#~ msgctxt "search-result"
 | 
			
		||||
#~ msgid "Power off"
 | 
			
		||||
#~ msgstr "Vypnout"
 | 
			
		||||
 | 
			
		||||
#~ msgctxt "search-result"
 | 
			
		||||
#~ msgid "Log out"
 | 
			
		||||
#~ msgstr "Odhlásit se"
 | 
			
		||||
 | 
			
		||||
#~ msgctxt "search-result"
 | 
			
		||||
#~ msgid "Switch user"
 | 
			
		||||
#~ msgstr "Přepnout uživatele"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										51
									
								
								po/es.po
									
									
									
									
									
								
							
							
						
						
									
										51
									
								
								po/es.po
									
									
									
									
									
								
							@@ -9,8 +9,8 @@ msgid ""
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Project-Id-Version: gnome-shell.master\n"
 | 
			
		||||
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-shell/issues\n"
 | 
			
		||||
"POT-Creation-Date: 2018-04-13 19:54+0000\n"
 | 
			
		||||
"PO-Revision-Date: 2018-04-25 12:54+0200\n"
 | 
			
		||||
"POT-Creation-Date: 2018-02-22 09:24+0000\n"
 | 
			
		||||
"PO-Revision-Date: 2018-02-23 08:26+0100\n"
 | 
			
		||||
"Last-Translator: Daniel Mustieles <daniel.mustieles@gmail.com>\n"
 | 
			
		||||
"Language-Team: es <gnome-es-list@gnome.org>\n"
 | 
			
		||||
"Language: es\n"
 | 
			
		||||
@@ -346,7 +346,7 @@ msgid "There was an error loading the preferences dialog for %s:"
 | 
			
		||||
msgstr "Hubo un error al lanzar el diálogo de preferencias para %s:"
 | 
			
		||||
 | 
			
		||||
#: js/gdm/authPrompt.js:147 js/ui/audioDeviceSelection.js:71
 | 
			
		||||
#: js/ui/components/networkAgent.js:117 js/ui/components/polkitAgent.js:153
 | 
			
		||||
#: js/ui/components/networkAgent.js:117 js/ui/components/polkitAgent.js:148
 | 
			
		||||
#: js/ui/endSessionDialog.js:482 js/ui/extensionDownloader.js:197
 | 
			
		||||
#: js/ui/shellMountOperation.js:343 js/ui/status/network.js:919
 | 
			
		||||
msgid "Cancel"
 | 
			
		||||
@@ -665,12 +665,12 @@ msgstr "Añadir a los favoritos"
 | 
			
		||||
msgid "Show Details"
 | 
			
		||||
msgstr "Mostrar detalles"
 | 
			
		||||
 | 
			
		||||
#: js/ui/appFavorites.js:140
 | 
			
		||||
#: js/ui/appFavorites.js:138
 | 
			
		||||
#, javascript-format
 | 
			
		||||
msgid "%s has been added to your favorites."
 | 
			
		||||
msgstr "Se ha añadido %s a sus favoritos."
 | 
			
		||||
 | 
			
		||||
#: js/ui/appFavorites.js:174
 | 
			
		||||
#: js/ui/appFavorites.js:172
 | 
			
		||||
#, javascript-format
 | 
			
		||||
msgid "%s has been removed from your favorites."
 | 
			
		||||
msgstr "Se ha quitado %s de sus favoritos."
 | 
			
		||||
@@ -865,7 +865,7 @@ msgstr "Dispositivo externo desconectado"
 | 
			
		||||
msgid "Open with %s"
 | 
			
		||||
msgstr "Abrir con %s"
 | 
			
		||||
 | 
			
		||||
#: js/ui/components/keyring.js:107 js/ui/components/polkitAgent.js:295
 | 
			
		||||
#: js/ui/components/keyring.js:107 js/ui/components/polkitAgent.js:284
 | 
			
		||||
msgid "Password:"
 | 
			
		||||
msgstr "Contraseña:"
 | 
			
		||||
 | 
			
		||||
@@ -953,15 +953,15 @@ msgstr "Se requiere una contraseña para conectarse a «%s»."
 | 
			
		||||
msgid "Network Manager"
 | 
			
		||||
msgstr "Gestor de la red"
 | 
			
		||||
 | 
			
		||||
#: js/ui/components/polkitAgent.js:48
 | 
			
		||||
#: js/ui/components/polkitAgent.js:43
 | 
			
		||||
msgid "Authentication Required"
 | 
			
		||||
msgstr "Se necesita autenticación"
 | 
			
		||||
 | 
			
		||||
#: js/ui/components/polkitAgent.js:76
 | 
			
		||||
#: js/ui/components/polkitAgent.js:71
 | 
			
		||||
msgid "Administrator"
 | 
			
		||||
msgstr "Administrador"
 | 
			
		||||
 | 
			
		||||
#: js/ui/components/polkitAgent.js:156
 | 
			
		||||
#: js/ui/components/polkitAgent.js:151
 | 
			
		||||
msgid "Authenticate"
 | 
			
		||||
msgstr "Autenticar"
 | 
			
		||||
 | 
			
		||||
@@ -969,7 +969,7 @@ msgstr "Autenticar"
 | 
			
		||||
#. * requested authentication was not gained; this can happen
 | 
			
		||||
#. * because of an authentication error (like invalid password),
 | 
			
		||||
#. * for instance.
 | 
			
		||||
#: js/ui/components/polkitAgent.js:281 js/ui/shellMountOperation.js:327
 | 
			
		||||
#: js/ui/components/polkitAgent.js:270 js/ui/shellMountOperation.js:327
 | 
			
		||||
msgid "Sorry, that didn’t work. Please try again."
 | 
			
		||||
msgstr "Eso no ha funcionado. Inténtelo de nuevo."
 | 
			
		||||
 | 
			
		||||
@@ -1017,7 +1017,7 @@ msgstr "Añadir relojes del mundo…"
 | 
			
		||||
msgid "World Clocks"
 | 
			
		||||
msgstr "Relojes del mundo"
 | 
			
		||||
 | 
			
		||||
#: js/ui/dateMenu.js:227
 | 
			
		||||
#: js/ui/dateMenu.js:225
 | 
			
		||||
msgid "Weather"
 | 
			
		||||
msgstr "Meteorología"
 | 
			
		||||
 | 
			
		||||
@@ -1025,7 +1025,7 @@ msgstr "Meteorología"
 | 
			
		||||
#. libgweather for the possible condition strings. If at all
 | 
			
		||||
#. possible, the sentence should match the grammatical case etc. of
 | 
			
		||||
#. the inserted conditions.
 | 
			
		||||
#: js/ui/dateMenu.js:291
 | 
			
		||||
#: js/ui/dateMenu.js:289
 | 
			
		||||
#, javascript-format
 | 
			
		||||
msgid "%s all day."
 | 
			
		||||
msgstr "%s todo el día."
 | 
			
		||||
@@ -1034,7 +1034,7 @@ msgstr "%s todo el día."
 | 
			
		||||
#. libgweather for the possible condition strings. If at all
 | 
			
		||||
#. possible, the sentence should match the grammatical case etc. of
 | 
			
		||||
#. the inserted conditions.
 | 
			
		||||
#: js/ui/dateMenu.js:297
 | 
			
		||||
#: js/ui/dateMenu.js:295
 | 
			
		||||
#, javascript-format
 | 
			
		||||
msgid "%s, then %s later."
 | 
			
		||||
msgstr "%s, luego %s."
 | 
			
		||||
@@ -1043,30 +1043,30 @@ msgstr "%s, luego %s."
 | 
			
		||||
#. libgweather for the possible condition strings. If at all
 | 
			
		||||
#. possible, the sentence should match the grammatical case etc. of
 | 
			
		||||
#. the inserted conditions.
 | 
			
		||||
#: js/ui/dateMenu.js:303
 | 
			
		||||
#: js/ui/dateMenu.js:301
 | 
			
		||||
#, javascript-format
 | 
			
		||||
msgid "%s, then %s, followed by %s later."
 | 
			
		||||
msgstr "%s, luego %s seguido de %s."
 | 
			
		||||
 | 
			
		||||
#: js/ui/dateMenu.js:314
 | 
			
		||||
#: js/ui/dateMenu.js:312
 | 
			
		||||
msgid "Select a location…"
 | 
			
		||||
msgstr "Seleccionar ubicación…"
 | 
			
		||||
 | 
			
		||||
#: js/ui/dateMenu.js:317
 | 
			
		||||
#: js/ui/dateMenu.js:315
 | 
			
		||||
msgid "Loading…"
 | 
			
		||||
msgstr "Cargando…"
 | 
			
		||||
 | 
			
		||||
#. Translators: %s is a temperature with unit, e.g. "23℃"
 | 
			
		||||
#: js/ui/dateMenu.js:323
 | 
			
		||||
#: js/ui/dateMenu.js:321
 | 
			
		||||
#, javascript-format
 | 
			
		||||
msgid "Feels like %s."
 | 
			
		||||
msgstr "Sensación térmica de %s."
 | 
			
		||||
 | 
			
		||||
#: js/ui/dateMenu.js:326
 | 
			
		||||
#: js/ui/dateMenu.js:324
 | 
			
		||||
msgid "Go online for weather information"
 | 
			
		||||
msgstr "Conectarse para obtener la información meteorológica"
 | 
			
		||||
 | 
			
		||||
#: js/ui/dateMenu.js:328
 | 
			
		||||
#: js/ui/dateMenu.js:326
 | 
			
		||||
msgid "Weather information is currently unavailable"
 | 
			
		||||
msgstr "La información meteorológica no está disponible actualmente."
 | 
			
		||||
 | 
			
		||||
@@ -1968,16 +1968,16 @@ msgstr "Suspender"
 | 
			
		||||
msgid "Power Off"
 | 
			
		||||
msgstr "Apagar"
 | 
			
		||||
 | 
			
		||||
#: js/ui/status/thunderbolt.js:294
 | 
			
		||||
#: js/ui/status/thunderbolt.js:272
 | 
			
		||||
msgid "Thunderbolt"
 | 
			
		||||
msgstr "Thunderbolt"
 | 
			
		||||
 | 
			
		||||
#. we are done
 | 
			
		||||
#: js/ui/status/thunderbolt.js:350
 | 
			
		||||
#: js/ui/status/thunderbolt.js:328
 | 
			
		||||
msgid "Unknown Thunderbolt device"
 | 
			
		||||
msgstr "Dispositivo Thunderbolt desconocido"
 | 
			
		||||
 | 
			
		||||
#: js/ui/status/thunderbolt.js:351
 | 
			
		||||
#: js/ui/status/thunderbolt.js:329
 | 
			
		||||
msgid ""
 | 
			
		||||
"New device has been detected while you were away. Please disconnect and "
 | 
			
		||||
"reconnect the device to start using it."
 | 
			
		||||
@@ -1985,14 +1985,13 @@ msgstr ""
 | 
			
		||||
"Se ha detectado un dispositivo nuevo mientras estaba fuera. Desconéctelo y "
 | 
			
		||||
"vuélvalo a conectar para empezar a usarlo."
 | 
			
		||||
 | 
			
		||||
#: js/ui/status/thunderbolt.js:356
 | 
			
		||||
#: js/ui/status/thunderbolt.js:334
 | 
			
		||||
msgid "Thunderbolt authorization error"
 | 
			
		||||
msgstr "Error de autorización de Thunderbolt"
 | 
			
		||||
 | 
			
		||||
#: js/ui/status/thunderbolt.js:357
 | 
			
		||||
#: js/ui/status/thunderbolt.js:335
 | 
			
		||||
#, javascript-format
 | 
			
		||||
#| msgid "Could not authorize the thunderbolt device: %s"
 | 
			
		||||
msgid "Could not authorize the Thunderbolt device: %s"
 | 
			
		||||
msgid "Could not authorize the thunderbolt device: %s"
 | 
			
		||||
msgstr "No se pudo autorizar el dispositivo Thunderbolt: %s"
 | 
			
		||||
 | 
			
		||||
#: js/ui/status/volume.js:128
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										54
									
								
								po/hr.po
									
									
									
									
									
								
							
							
						
						
									
										54
									
								
								po/hr.po
									
									
									
									
									
								
							@@ -7,8 +7,8 @@ msgid ""
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Project-Id-Version: gnome-shell master\n"
 | 
			
		||||
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-shell/issues\n"
 | 
			
		||||
"POT-Creation-Date: 2018-04-13 19:54+0000\n"
 | 
			
		||||
"PO-Revision-Date: 2018-04-16 14:30+0200\n"
 | 
			
		||||
"POT-Creation-Date: 2018-02-26 17:00+0000\n"
 | 
			
		||||
"PO-Revision-Date: 2018-03-07 22:46+0100\n"
 | 
			
		||||
"Last-Translator: gogo <trebelnik2@gmail.com>\n"
 | 
			
		||||
"Language-Team: Croatian <hr@li.org>\n"
 | 
			
		||||
"Language: hr\n"
 | 
			
		||||
@@ -337,7 +337,7 @@ msgid "There was an error loading the preferences dialog for %s:"
 | 
			
		||||
msgstr "Dogodila se greška učitavanja dijaloga osobitosti za %s:"
 | 
			
		||||
 | 
			
		||||
#: js/gdm/authPrompt.js:147 js/ui/audioDeviceSelection.js:71
 | 
			
		||||
#: js/ui/components/networkAgent.js:117 js/ui/components/polkitAgent.js:153
 | 
			
		||||
#: js/ui/components/networkAgent.js:117 js/ui/components/polkitAgent.js:148
 | 
			
		||||
#: js/ui/endSessionDialog.js:482 js/ui/extensionDownloader.js:197
 | 
			
		||||
#: js/ui/shellMountOperation.js:343 js/ui/status/network.js:919
 | 
			
		||||
msgid "Cancel"
 | 
			
		||||
@@ -663,12 +663,12 @@ msgstr "Dodaj u omiljene"
 | 
			
		||||
msgid "Show Details"
 | 
			
		||||
msgstr "Prikaži pojedinosti"
 | 
			
		||||
 | 
			
		||||
#: js/ui/appFavorites.js:140
 | 
			
		||||
#: js/ui/appFavorites.js:138
 | 
			
		||||
#, javascript-format
 | 
			
		||||
msgid "%s has been added to your favorites."
 | 
			
		||||
msgstr "%s je dodan u omiljene."
 | 
			
		||||
 | 
			
		||||
#: js/ui/appFavorites.js:174
 | 
			
		||||
#: js/ui/appFavorites.js:172
 | 
			
		||||
#, javascript-format
 | 
			
		||||
msgid "%s has been removed from your favorites."
 | 
			
		||||
msgstr "%s je uklonjen iz omiljenih."
 | 
			
		||||
@@ -863,7 +863,7 @@ msgstr "Vanjski uređaj odspojen"
 | 
			
		||||
msgid "Open with %s"
 | 
			
		||||
msgstr "Otvori s(a) %s"
 | 
			
		||||
 | 
			
		||||
#: js/ui/components/keyring.js:107 js/ui/components/polkitAgent.js:295
 | 
			
		||||
#: js/ui/components/keyring.js:107 js/ui/components/polkitAgent.js:284
 | 
			
		||||
msgid "Password:"
 | 
			
		||||
msgstr "Lozinka:"
 | 
			
		||||
 | 
			
		||||
@@ -950,15 +950,15 @@ msgstr "Potrebna je lozinka za povezivanje s “%s”."
 | 
			
		||||
msgid "Network Manager"
 | 
			
		||||
msgstr "Mrežni upravitelj"
 | 
			
		||||
 | 
			
		||||
#: js/ui/components/polkitAgent.js:48
 | 
			
		||||
#: js/ui/components/polkitAgent.js:43
 | 
			
		||||
msgid "Authentication Required"
 | 
			
		||||
msgstr "Potrebna je ovjera"
 | 
			
		||||
 | 
			
		||||
#: js/ui/components/polkitAgent.js:76
 | 
			
		||||
#: js/ui/components/polkitAgent.js:71
 | 
			
		||||
msgid "Administrator"
 | 
			
		||||
msgstr "Administrator"
 | 
			
		||||
 | 
			
		||||
#: js/ui/components/polkitAgent.js:156
 | 
			
		||||
#: js/ui/components/polkitAgent.js:151
 | 
			
		||||
msgid "Authenticate"
 | 
			
		||||
msgstr "Ovjeri"
 | 
			
		||||
 | 
			
		||||
@@ -966,7 +966,7 @@ msgstr "Ovjeri"
 | 
			
		||||
#. * requested authentication was not gained; this can happen
 | 
			
		||||
#. * because of an authentication error (like invalid password),
 | 
			
		||||
#. * for instance.
 | 
			
		||||
#: js/ui/components/polkitAgent.js:281 js/ui/shellMountOperation.js:327
 | 
			
		||||
#: js/ui/components/polkitAgent.js:270 js/ui/shellMountOperation.js:327
 | 
			
		||||
msgid "Sorry, that didn’t work. Please try again."
 | 
			
		||||
msgstr "Nažalost, to ne radi. Pokušajte ponovno."
 | 
			
		||||
 | 
			
		||||
@@ -1014,7 +1014,7 @@ msgstr "Dodaj satove iz svijeta…"
 | 
			
		||||
msgid "World Clocks"
 | 
			
		||||
msgstr "Svjetski satovi"
 | 
			
		||||
 | 
			
		||||
#: js/ui/dateMenu.js:227
 | 
			
		||||
#: js/ui/dateMenu.js:225
 | 
			
		||||
msgid "Weather"
 | 
			
		||||
msgstr "Vrijeme"
 | 
			
		||||
 | 
			
		||||
@@ -1022,7 +1022,7 @@ msgstr "Vrijeme"
 | 
			
		||||
#. libgweather for the possible condition strings. If at all
 | 
			
		||||
#. possible, the sentence should match the grammatical case etc. of
 | 
			
		||||
#. the inserted conditions.
 | 
			
		||||
#: js/ui/dateMenu.js:291
 | 
			
		||||
#: js/ui/dateMenu.js:289
 | 
			
		||||
#, javascript-format
 | 
			
		||||
msgid "%s all day."
 | 
			
		||||
msgstr "%s cijeli dan."
 | 
			
		||||
@@ -1031,7 +1031,7 @@ msgstr "%s cijeli dan."
 | 
			
		||||
#. libgweather for the possible condition strings. If at all
 | 
			
		||||
#. possible, the sentence should match the grammatical case etc. of
 | 
			
		||||
#. the inserted conditions.
 | 
			
		||||
#: js/ui/dateMenu.js:297
 | 
			
		||||
#: js/ui/dateMenu.js:295
 | 
			
		||||
#, javascript-format
 | 
			
		||||
msgid "%s, then %s later."
 | 
			
		||||
msgstr "%s, zatim %s kasnije."
 | 
			
		||||
@@ -1040,30 +1040,30 @@ msgstr "%s, zatim %s kasnije."
 | 
			
		||||
#. libgweather for the possible condition strings. If at all
 | 
			
		||||
#. possible, the sentence should match the grammatical case etc. of
 | 
			
		||||
#. the inserted conditions.
 | 
			
		||||
#: js/ui/dateMenu.js:303
 | 
			
		||||
#: js/ui/dateMenu.js:301
 | 
			
		||||
#, javascript-format
 | 
			
		||||
msgid "%s, then %s, followed by %s later."
 | 
			
		||||
msgstr "%s, zatim %s, praćena s %s kasnije."
 | 
			
		||||
 | 
			
		||||
#: js/ui/dateMenu.js:314
 | 
			
		||||
#: js/ui/dateMenu.js:312
 | 
			
		||||
msgid "Select a location…"
 | 
			
		||||
msgstr "Odaberi lokaciju…"
 | 
			
		||||
 | 
			
		||||
#: js/ui/dateMenu.js:317
 | 
			
		||||
#: js/ui/dateMenu.js:315
 | 
			
		||||
msgid "Loading…"
 | 
			
		||||
msgstr "Pretraživanje…"
 | 
			
		||||
 | 
			
		||||
#. Translators: %s is a temperature with unit, e.g. "23℃"
 | 
			
		||||
#: js/ui/dateMenu.js:323
 | 
			
		||||
#: js/ui/dateMenu.js:321
 | 
			
		||||
#, javascript-format
 | 
			
		||||
msgid "Feels like %s."
 | 
			
		||||
msgstr "Kao da je %s."
 | 
			
		||||
 | 
			
		||||
#: js/ui/dateMenu.js:326
 | 
			
		||||
#: js/ui/dateMenu.js:324
 | 
			
		||||
msgid "Go online for weather information"
 | 
			
		||||
msgstr "Posjetite za opširnije vremenske informacije"
 | 
			
		||||
 | 
			
		||||
#: js/ui/dateMenu.js:328
 | 
			
		||||
#: js/ui/dateMenu.js:326
 | 
			
		||||
msgid "Weather information is currently unavailable"
 | 
			
		||||
msgstr "Vremenske informacije su trenutno nedostupne"
 | 
			
		||||
 | 
			
		||||
@@ -1977,16 +1977,16 @@ msgstr "Suspendiraj"
 | 
			
		||||
msgid "Power Off"
 | 
			
		||||
msgstr "Isključivanje"
 | 
			
		||||
 | 
			
		||||
#: js/ui/status/thunderbolt.js:294
 | 
			
		||||
#: js/ui/status/thunderbolt.js:272
 | 
			
		||||
msgid "Thunderbolt"
 | 
			
		||||
msgstr "Thunderbolt"
 | 
			
		||||
 | 
			
		||||
#. we are done
 | 
			
		||||
#: js/ui/status/thunderbolt.js:350
 | 
			
		||||
#: js/ui/status/thunderbolt.js:328
 | 
			
		||||
msgid "Unknown Thunderbolt device"
 | 
			
		||||
msgstr "Nepoznati Thunderbolt uređaj"
 | 
			
		||||
 | 
			
		||||
#: js/ui/status/thunderbolt.js:351
 | 
			
		||||
#: js/ui/status/thunderbolt.js:329
 | 
			
		||||
msgid ""
 | 
			
		||||
"New device has been detected while you were away. Please disconnect and "
 | 
			
		||||
"reconnect the device to start using it."
 | 
			
		||||
@@ -1994,14 +1994,14 @@ msgstr ""
 | 
			
		||||
"Otkriven je novi uređaj dok ste bili odsutni. Odspojite i ponovno spojite "
 | 
			
		||||
"uređaj kako bi ga mogli koristiti."
 | 
			
		||||
 | 
			
		||||
#: js/ui/status/thunderbolt.js:356
 | 
			
		||||
#: js/ui/status/thunderbolt.js:334
 | 
			
		||||
msgid "Thunderbolt authorization error"
 | 
			
		||||
msgstr "Greška Thunderbolt odobravanja"
 | 
			
		||||
msgstr "Greška Thunderbolt ovjere"
 | 
			
		||||
 | 
			
		||||
#: js/ui/status/thunderbolt.js:357
 | 
			
		||||
#: js/ui/status/thunderbolt.js:335
 | 
			
		||||
#, javascript-format
 | 
			
		||||
msgid "Could not authorize the Thunderbolt device: %s"
 | 
			
		||||
msgstr "Nemoguće odobravanje Thunderbolt uređaja: %s"
 | 
			
		||||
msgid "Could not authorize the thunderbolt device: %s"
 | 
			
		||||
msgstr "Nemoguća ovjera Thunderbolt uređaja: %s"
 | 
			
		||||
 | 
			
		||||
#: js/ui/status/volume.js:128
 | 
			
		||||
msgid "Volume changed"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										87
									
								
								po/sl.po
									
									
									
									
									
								
							
							
						
						
									
										87
									
								
								po/sl.po
									
									
									
									
									
								
							@@ -8,8 +8,8 @@ msgid ""
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Project-Id-Version: gnome-shell master\n"
 | 
			
		||||
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-shell/issues\n"
 | 
			
		||||
"POT-Creation-Date: 2018-04-17 15:11+0000\n"
 | 
			
		||||
"PO-Revision-Date: 2018-04-17 18:32+0200\n"
 | 
			
		||||
"POT-Creation-Date: 2018-03-18 10:36+0000\n"
 | 
			
		||||
"PO-Revision-Date: 2018-03-19 21:42+0100\n"
 | 
			
		||||
"Last-Translator: Matej Urbančič <mateju@svn.gnome.org>\n"
 | 
			
		||||
"Language-Team: Slovenian GNOME Translation Team <gnome-si@googlegroups.com>\n"
 | 
			
		||||
"Language: sl\n"
 | 
			
		||||
@@ -66,19 +66,19 @@ msgstr "Upravljanje oken in zaganjanje programov"
 | 
			
		||||
msgid "Enable internal tools useful for developers and testers from Alt-F2"
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Omogoči dostop do orodij razvijalcev in preizkuševalcev programske opreme "
 | 
			
		||||
"prek vnosnega polja Alt-F2."
 | 
			
		||||
"preko Alt-F2 vnosnega polja."
 | 
			
		||||
 | 
			
		||||
#: data/org.gnome.shell.gschema.xml.in:9
 | 
			
		||||
msgid ""
 | 
			
		||||
"Allows access to internal debugging and monitoring tools using the Alt-F2 "
 | 
			
		||||
"dialog."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Dovoli dostop do razhroščevanja in drugih orodij nadzora prek vnosnega polja "
 | 
			
		||||
"Alt-F2."
 | 
			
		||||
"Dovoli dostop do razhroščevanja in drugih orodij nadzora preko Alt-F2 "
 | 
			
		||||
"vnosnega polja."
 | 
			
		||||
 | 
			
		||||
#: data/org.gnome.shell.gschema.xml.in:16
 | 
			
		||||
msgid "UUIDs of extensions to enable"
 | 
			
		||||
msgstr "Določila razširitev UUID, ki bodo omogočene"
 | 
			
		||||
msgstr "Določila UUID razširitev, ki bodo omogočene"
 | 
			
		||||
 | 
			
		||||
#: data/org.gnome.shell.gschema.xml.in:17
 | 
			
		||||
msgid ""
 | 
			
		||||
@@ -87,9 +87,10 @@ msgid ""
 | 
			
		||||
"list. You can also manipulate this list with the EnableExtension and "
 | 
			
		||||
"DisableExtension D-Bus methods on org.gnome.Shell."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Razširitve lupine GNOME imajo nastavljeno določilo UUID; ključ določa seznam "
 | 
			
		||||
"razširitev, ki naj bodo naložene ob zagonu. Upravljanje seznama je mogoče "
 | 
			
		||||
"tudi prek vodila D-BUs na org.gnome.Shell."
 | 
			
		||||
"Razširitve lupine GNOME imajo določila UUID; ključ določa seznam razširitev, "
 | 
			
		||||
"ki bodo naložene. Razširitev, ki se naj naloži, mora biti zavedena na tem "
 | 
			
		||||
"seznamu. Upravljanje seznama je mogoče tudi preko vodila D-BUs na org.gnome."
 | 
			
		||||
"Shell."
 | 
			
		||||
 | 
			
		||||
#: data/org.gnome.shell.gschema.xml.in:26
 | 
			
		||||
msgid "Disable user extensions"
 | 
			
		||||
@@ -114,8 +115,8 @@ msgid ""
 | 
			
		||||
"load all extensions regardless of the versions they claim to support."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Lupina GNOME naloži le razširitve, ki so skladne z nameščeno različico. "
 | 
			
		||||
"Izbrana možnost onemogoči preverjanje, zato so lahko naložene tudi "
 | 
			
		||||
"razširitve, katerih skladnost ni potrjena."
 | 
			
		||||
"Izbrana možnost onemogoči preverjanje skladnosti, zato so lahko naložene "
 | 
			
		||||
"tudi razširitve, katerih skladnost ni potrjena."
 | 
			
		||||
 | 
			
		||||
#: data/org.gnome.shell.gschema.xml.in:43
 | 
			
		||||
msgid "List of desktop file IDs for favorite applications"
 | 
			
		||||
@@ -126,7 +127,7 @@ msgid ""
 | 
			
		||||
"The applications corresponding to these identifiers will be displayed in the "
 | 
			
		||||
"favorites area."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Programi, ki ustrezajo določilom, bodo prikazani v polju priljubljenih "
 | 
			
		||||
"Programi določeni s temi določili bodo prikazani v območju priljubljenih "
 | 
			
		||||
"programov"
 | 
			
		||||
 | 
			
		||||
#: data/org.gnome.shell.gschema.xml.in:51
 | 
			
		||||
@@ -144,18 +145,18 @@ msgstr "Zgodovina pogovornega okna ukazov (Alt-F2)"
 | 
			
		||||
#. Translators: looking glass is a debugger and inspector tool, see https://wiki.gnome.org/Projects/GnomeShell/LookingGlass
 | 
			
		||||
#: data/org.gnome.shell.gschema.xml.in:63
 | 
			
		||||
msgid "History for the looking glass dialog"
 | 
			
		||||
msgstr "Zgodovina za pogovorno okno povečevala"
 | 
			
		||||
msgstr "Zgodovina za pogovorno okno povečevalnega stekla"
 | 
			
		||||
 | 
			
		||||
#: data/org.gnome.shell.gschema.xml.in:67
 | 
			
		||||
msgid "Always show the “Log out” menu item in the user menu."
 | 
			
		||||
msgstr "Vedno pokaži možnost »Odjave« v uporabniškem meniju."
 | 
			
		||||
msgstr "Vedno pokaži možnost »Odjava« v uporabniškem meniju."
 | 
			
		||||
 | 
			
		||||
#: data/org.gnome.shell.gschema.xml.in:68
 | 
			
		||||
msgid ""
 | 
			
		||||
"This key overrides the automatic hiding of the “Log out” menu item in single-"
 | 
			
		||||
"user, single-session situations."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Izbira prepiše možnost samodejnega skrivanja gumba za »Odjavo« na sistemskem "
 | 
			
		||||
"Izbira prepiše možnost samodejnega skrivanja predmeta »Odjava« na sistemskem "
 | 
			
		||||
"meniju pri eno-uporabniškem in eno-sejnem zagonu."
 | 
			
		||||
 | 
			
		||||
#: data/org.gnome.shell.gschema.xml.in:75
 | 
			
		||||
@@ -173,8 +174,8 @@ msgid ""
 | 
			
		||||
"state of the checkbox."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Za priklop oddaljenega datotečnega sistema ali šifrirane naprave bo po "
 | 
			
		||||
"izbiri podana zahteva za vnos gesla. Na pogovornem oknu bo prikazana tudi "
 | 
			
		||||
"možnost »Shrani geslo«. Ta možnost določa privzeto stanje izbirnega polja."
 | 
			
		||||
"izbiri možnosti zahtevano geslo. Na pogovornem oknu bo prikazana možnost "
 | 
			
		||||
"»Shrani geslo«. Ta možnost določa privzeto stanje izbirnega polja."
 | 
			
		||||
 | 
			
		||||
#: data/org.gnome.shell.gschema.xml.in:85
 | 
			
		||||
msgid ""
 | 
			
		||||
@@ -332,7 +333,7 @@ msgid "There was an error loading the preferences dialog for %s:"
 | 
			
		||||
msgstr "Prišlo je do napake med nalaganjem pogovornega okna z možnostmi za %s:"
 | 
			
		||||
 | 
			
		||||
#: js/gdm/authPrompt.js:147 js/ui/audioDeviceSelection.js:71
 | 
			
		||||
#: js/ui/components/networkAgent.js:117 js/ui/components/polkitAgent.js:153
 | 
			
		||||
#: js/ui/components/networkAgent.js:117 js/ui/components/polkitAgent.js:148
 | 
			
		||||
#: js/ui/endSessionDialog.js:482 js/ui/extensionDownloader.js:197
 | 
			
		||||
#: js/ui/shellMountOperation.js:343 js/ui/status/network.js:919
 | 
			
		||||
msgid "Cancel"
 | 
			
		||||
@@ -663,12 +664,12 @@ msgstr "Dodaj med priljubljene"
 | 
			
		||||
msgid "Show Details"
 | 
			
		||||
msgstr "Pokaži besedilo"
 | 
			
		||||
 | 
			
		||||
#: js/ui/appFavorites.js:140
 | 
			
		||||
#: js/ui/appFavorites.js:138
 | 
			
		||||
#, javascript-format
 | 
			
		||||
msgid "%s has been added to your favorites."
 | 
			
		||||
msgstr "Program »%s« je dodan med priljubljeno."
 | 
			
		||||
 | 
			
		||||
#: js/ui/appFavorites.js:174
 | 
			
		||||
#: js/ui/appFavorites.js:172
 | 
			
		||||
#, javascript-format
 | 
			
		||||
msgid "%s has been removed from your favorites."
 | 
			
		||||
msgstr "Program »%s« je odstranjen iz priljubljenih."
 | 
			
		||||
@@ -839,7 +840,7 @@ msgid ""
 | 
			
		||||
"You may choose to wait a short while for it to continue or force the "
 | 
			
		||||
"application to quit entirely."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Lahko počakate, če se program morda začne spet odzivati, lahko pa vsilite "
 | 
			
		||||
"Lahko še malo počakate, če začne morda program spet delovati, ali pa vsilite "
 | 
			
		||||
"končanje delovanja."
 | 
			
		||||
 | 
			
		||||
#: js/ui/closeDialog.js:61
 | 
			
		||||
@@ -863,13 +864,13 @@ msgstr "Zunanji pogon je odklopljen"
 | 
			
		||||
msgid "Open with %s"
 | 
			
		||||
msgstr "Odpri s programom %s"
 | 
			
		||||
 | 
			
		||||
#: js/ui/components/keyring.js:107 js/ui/components/polkitAgent.js:295
 | 
			
		||||
#: js/ui/components/keyring.js:107 js/ui/components/polkitAgent.js:284
 | 
			
		||||
msgid "Password:"
 | 
			
		||||
msgstr "Geslo:"
 | 
			
		||||
 | 
			
		||||
#: js/ui/components/keyring.js:140
 | 
			
		||||
msgid "Type again:"
 | 
			
		||||
msgstr "Ponovni vpis:"
 | 
			
		||||
msgstr "Vpišite znova:"
 | 
			
		||||
 | 
			
		||||
#: js/ui/components/networkAgent.js:112 js/ui/status/network.js:245
 | 
			
		||||
#: js/ui/status/network.js:336 js/ui/status/network.js:922
 | 
			
		||||
@@ -886,19 +887,19 @@ msgstr "Geslo:"
 | 
			
		||||
#. static WEP
 | 
			
		||||
#: js/ui/components/networkAgent.js:210
 | 
			
		||||
msgid "Key: "
 | 
			
		||||
msgstr "Ključ: "
 | 
			
		||||
msgstr "Ključ:"
 | 
			
		||||
 | 
			
		||||
#: js/ui/components/networkAgent.js:249
 | 
			
		||||
msgid "Identity: "
 | 
			
		||||
msgstr "_Istovetnost: "
 | 
			
		||||
msgstr "_Istovetnost:"
 | 
			
		||||
 | 
			
		||||
#: js/ui/components/networkAgent.js:251
 | 
			
		||||
msgid "Private key password: "
 | 
			
		||||
msgstr "Geslo zasebnega ključa: "
 | 
			
		||||
msgstr "Geslo zasebnega ključa:"
 | 
			
		||||
 | 
			
		||||
#: js/ui/components/networkAgent.js:263
 | 
			
		||||
msgid "Service: "
 | 
			
		||||
msgstr "Storitev: "
 | 
			
		||||
msgstr "Storitev:"
 | 
			
		||||
 | 
			
		||||
#: js/ui/components/networkAgent.js:292 js/ui/components/networkAgent.js:659
 | 
			
		||||
msgid "Authentication required by wireless network"
 | 
			
		||||
@@ -919,7 +920,7 @@ msgstr "Žična overitev 802.1X"
 | 
			
		||||
 | 
			
		||||
#: js/ui/components/networkAgent.js:299
 | 
			
		||||
msgid "Network name: "
 | 
			
		||||
msgstr "Naziv omrežja: "
 | 
			
		||||
msgstr "Naziv omrežja:"
 | 
			
		||||
 | 
			
		||||
#: js/ui/components/networkAgent.js:304 js/ui/components/networkAgent.js:667
 | 
			
		||||
msgid "DSL authentication"
 | 
			
		||||
@@ -951,15 +952,15 @@ msgstr "Za povezavo z omrežjem »%s« je zahtevano geslo."
 | 
			
		||||
msgid "Network Manager"
 | 
			
		||||
msgstr "Upravljalnik omrežij"
 | 
			
		||||
 | 
			
		||||
#: js/ui/components/polkitAgent.js:48
 | 
			
		||||
#: js/ui/components/polkitAgent.js:43
 | 
			
		||||
msgid "Authentication Required"
 | 
			
		||||
msgstr "Zahtevana je overitev"
 | 
			
		||||
 | 
			
		||||
#: js/ui/components/polkitAgent.js:76
 | 
			
		||||
#: js/ui/components/polkitAgent.js:71
 | 
			
		||||
msgid "Administrator"
 | 
			
		||||
msgstr "Skrbnik"
 | 
			
		||||
 | 
			
		||||
#: js/ui/components/polkitAgent.js:156
 | 
			
		||||
#: js/ui/components/polkitAgent.js:151
 | 
			
		||||
msgid "Authenticate"
 | 
			
		||||
msgstr "Overi"
 | 
			
		||||
 | 
			
		||||
@@ -967,7 +968,7 @@ msgstr "Overi"
 | 
			
		||||
#. * requested authentication was not gained; this can happen
 | 
			
		||||
#. * because of an authentication error (like invalid password),
 | 
			
		||||
#. * for instance.
 | 
			
		||||
#: js/ui/components/polkitAgent.js:281 js/ui/shellMountOperation.js:327
 | 
			
		||||
#: js/ui/components/polkitAgent.js:270 js/ui/shellMountOperation.js:327
 | 
			
		||||
msgid "Sorry, that didn’t work. Please try again."
 | 
			
		||||
msgstr "Overitev je spodletela.. Poskusite znova."
 | 
			
		||||
 | 
			
		||||
@@ -1015,7 +1016,7 @@ msgstr "Dodaj svetovni čas ..."
 | 
			
		||||
msgid "World Clocks"
 | 
			
		||||
msgstr "Svetovni časi"
 | 
			
		||||
 | 
			
		||||
#: js/ui/dateMenu.js:227
 | 
			
		||||
#: js/ui/dateMenu.js:225
 | 
			
		||||
msgid "Weather"
 | 
			
		||||
msgstr "Vreme"
 | 
			
		||||
 | 
			
		||||
@@ -1023,7 +1024,7 @@ msgstr "Vreme"
 | 
			
		||||
#. libgweather for the possible condition strings. If at all
 | 
			
		||||
#. possible, the sentence should match the grammatical case etc. of
 | 
			
		||||
#. the inserted conditions.
 | 
			
		||||
#: js/ui/dateMenu.js:291
 | 
			
		||||
#: js/ui/dateMenu.js:289
 | 
			
		||||
#, javascript-format
 | 
			
		||||
msgid "%s all day."
 | 
			
		||||
msgstr "%s – ves dan."
 | 
			
		||||
@@ -1032,7 +1033,7 @@ msgstr "%s – ves dan."
 | 
			
		||||
#. libgweather for the possible condition strings. If at all
 | 
			
		||||
#. possible, the sentence should match the grammatical case etc. of
 | 
			
		||||
#. the inserted conditions.
 | 
			
		||||
#: js/ui/dateMenu.js:297
 | 
			
		||||
#: js/ui/dateMenu.js:295
 | 
			
		||||
#, javascript-format
 | 
			
		||||
msgid "%s, then %s later."
 | 
			
		||||
msgstr "%s, sledi %s."
 | 
			
		||||
@@ -1041,30 +1042,30 @@ msgstr "%s, sledi %s."
 | 
			
		||||
#. libgweather for the possible condition strings. If at all
 | 
			
		||||
#. possible, the sentence should match the grammatical case etc. of
 | 
			
		||||
#. the inserted conditions.
 | 
			
		||||
#: js/ui/dateMenu.js:303
 | 
			
		||||
#: js/ui/dateMenu.js:301
 | 
			
		||||
#, javascript-format
 | 
			
		||||
msgid "%s, then %s, followed by %s later."
 | 
			
		||||
msgstr "%s, sledi %s, kasneje tudi %s."
 | 
			
		||||
 | 
			
		||||
#: js/ui/dateMenu.js:314
 | 
			
		||||
#: js/ui/dateMenu.js:312
 | 
			
		||||
msgid "Select a location…"
 | 
			
		||||
msgstr "Izbor mesta ..."
 | 
			
		||||
 | 
			
		||||
#: js/ui/dateMenu.js:317
 | 
			
		||||
#: js/ui/dateMenu.js:315
 | 
			
		||||
msgid "Loading…"
 | 
			
		||||
msgstr "Poteka nalaganje ..."
 | 
			
		||||
 | 
			
		||||
#. Translators: %s is a temperature with unit, e.g. "23℃"
 | 
			
		||||
#: js/ui/dateMenu.js:323
 | 
			
		||||
#: js/ui/dateMenu.js:321
 | 
			
		||||
#, javascript-format
 | 
			
		||||
msgid "Feels like %s."
 | 
			
		||||
msgstr "Občuti se kot %s."
 | 
			
		||||
 | 
			
		||||
#: js/ui/dateMenu.js:326
 | 
			
		||||
#: js/ui/dateMenu.js:324
 | 
			
		||||
msgid "Go online for weather information"
 | 
			
		||||
msgstr "Preglej splet za podrobnosti o vremenu."
 | 
			
		||||
 | 
			
		||||
#: js/ui/dateMenu.js:328
 | 
			
		||||
#: js/ui/dateMenu.js:326
 | 
			
		||||
msgid "Weather information is currently unavailable"
 | 
			
		||||
msgstr "Podatki o vremenu trenutno niso na voljo."
 | 
			
		||||
 | 
			
		||||
@@ -2013,8 +2014,8 @@ msgstr "Napaka overitve naprave Thunderbolt"
 | 
			
		||||
 | 
			
		||||
#: js/ui/status/thunderbolt.js:357
 | 
			
		||||
#, javascript-format
 | 
			
		||||
msgid "Could not authorize the Thunderbolt device: %s"
 | 
			
		||||
msgstr "Naprave Thunderbolt ni mogoče overiti: %s"
 | 
			
		||||
msgid "Could not authorize the thunderbolt device: %s"
 | 
			
		||||
msgstr "Naprave thunderbolt ni mogoče overiti: %s"
 | 
			
		||||
 | 
			
		||||
#: js/ui/status/volume.js:128
 | 
			
		||||
msgid "Volume changed"
 | 
			
		||||
 
 | 
			
		||||
@@ -590,11 +590,6 @@ app_load_events (App *app)
 | 
			
		||||
  g_list_free (app->live_views);
 | 
			
		||||
  app->live_views = NULL;
 | 
			
		||||
 | 
			
		||||
  if (!app->since || !app->until)
 | 
			
		||||
    {
 | 
			
		||||
      print_debug ("Skipping load of events, no time interval set yet");
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
  /* timezone could have changed */
 | 
			
		||||
  app_update_timezone (app);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -347,10 +347,10 @@ if options.perf == None:
 | 
			
		||||
        options.perf = 'core'
 | 
			
		||||
 | 
			
		||||
if options.extra_filter is None:
 | 
			
		||||
    options.extra_filter = []
 | 
			
		||||
 | 
			
		||||
if options.perf == 'hwtest':
 | 
			
		||||
    options.extra_filter.append('Gedit')
 | 
			
		||||
    if options.hwtest:
 | 
			
		||||
        options.extra_filter = ['Gedit']
 | 
			
		||||
    else:
 | 
			
		||||
        options.extra_filter = []
 | 
			
		||||
 | 
			
		||||
if args:
 | 
			
		||||
    parser.print_usage()
 | 
			
		||||
 
 | 
			
		||||
@@ -103,6 +103,7 @@ libshell_menu_dep = declare_dependency(link_with: libshell_menu)
 | 
			
		||||
 | 
			
		||||
libshell_public_headers = [
 | 
			
		||||
  'shell-app.h',
 | 
			
		||||
  'shell-app-cache.h',
 | 
			
		||||
  'shell-app-system.h',
 | 
			
		||||
  'shell-app-usage.h',
 | 
			
		||||
  'shell-embedded-window.h',
 | 
			
		||||
@@ -138,6 +139,7 @@ libshell_private_headers = [
 | 
			
		||||
libshell_sources = [
 | 
			
		||||
  'gnome-shell-plugin.c',
 | 
			
		||||
  'shell-app.c',
 | 
			
		||||
  'shell-app-cache.c',
 | 
			
		||||
  'shell-app-system.c',
 | 
			
		||||
  'shell-app-usage.c',
 | 
			
		||||
  'shell-embedded-window.c',
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										439
									
								
								src/shell-app-cache.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										439
									
								
								src/shell-app-cache.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,439 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
#include "shell-app-cache.h"
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * SECTION:shell-app-cache
 | 
			
		||||
 * @title: ShellAppCache
 | 
			
		||||
 * @short_description: application information cache
 | 
			
		||||
 *
 | 
			
		||||
 * The #ShellAppCache is responsible for caching information about #GAppInfo
 | 
			
		||||
 * to ensure that the compositor thread never needs to perform disk reads to
 | 
			
		||||
 * access them. All of the work is done off-thread. When the new data has
 | 
			
		||||
 * been loaded, a #ShellAppCache::changed signal is emitted.
 | 
			
		||||
 *
 | 
			
		||||
 * Additionally, the #ShellAppCache caches information about translations for
 | 
			
		||||
 * directories. This allows translation provided in [Desktop Entry] GKeyFiles
 | 
			
		||||
 * to be available when building StLabel and other elements without performing
 | 
			
		||||
 * costly disk reads.
 | 
			
		||||
 *
 | 
			
		||||
 * Various monitors are used to keep this information up to date while the
 | 
			
		||||
 * Shell is running.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define DEFAULT_TIMEOUT_SECONDS 5
 | 
			
		||||
 | 
			
		||||
struct _ShellAppCache
 | 
			
		||||
{
 | 
			
		||||
  GObject          parent_instance;
 | 
			
		||||
 | 
			
		||||
  GMutex           mutex;
 | 
			
		||||
 | 
			
		||||
  GAppInfoMonitor *monitor;
 | 
			
		||||
  GPtrArray       *dir_monitors;
 | 
			
		||||
  GHashTable      *folders;
 | 
			
		||||
  GCancellable    *cancellable;
 | 
			
		||||
  GList           *app_infos;
 | 
			
		||||
 | 
			
		||||
  guint            queued_update;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
  GList      *app_infos;
 | 
			
		||||
  GHashTable *folders;
 | 
			
		||||
} CacheState;
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE (ShellAppCache, shell_app_cache, G_TYPE_OBJECT)
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
  CHANGED,
 | 
			
		||||
  N_SIGNALS
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static guint signals [N_SIGNALS];
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
cache_state_free (CacheState *state)
 | 
			
		||||
{
 | 
			
		||||
  g_clear_pointer (&state->folders, g_hash_table_unref);
 | 
			
		||||
  g_list_free_full (state->app_infos, g_object_unref);
 | 
			
		||||
  g_slice_free (CacheState, state);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static CacheState *
 | 
			
		||||
cache_state_new (void)
 | 
			
		||||
{
 | 
			
		||||
  CacheState *state;
 | 
			
		||||
 | 
			
		||||
  state = g_slice_new0 (CacheState);
 | 
			
		||||
  state->folders = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
 | 
			
		||||
 | 
			
		||||
  return g_steal_pointer (&state);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * shell_app_cache_get_default:
 | 
			
		||||
 *
 | 
			
		||||
 * Gets the default #ShellAppCache.
 | 
			
		||||
 *
 | 
			
		||||
 * Returns: (transfer none): a #ShellAppCache
 | 
			
		||||
 */
 | 
			
		||||
ShellAppCache *
 | 
			
		||||
shell_app_cache_get_default (void)
 | 
			
		||||
{
 | 
			
		||||
  static ShellAppCache *instance;
 | 
			
		||||
 | 
			
		||||
  if (instance == NULL)
 | 
			
		||||
    {
 | 
			
		||||
      instance = g_object_new (SHELL_TYPE_APP_CACHE, NULL);
 | 
			
		||||
      g_object_add_weak_pointer (G_OBJECT (instance), (gpointer *)&instance);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return instance;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
load_folder (GHashTable *folders,
 | 
			
		||||
             const char *path)
 | 
			
		||||
{
 | 
			
		||||
  g_autoptr(GDir) dir = NULL;
 | 
			
		||||
  const char *name;
 | 
			
		||||
 | 
			
		||||
  g_assert (folders != NULL);
 | 
			
		||||
  g_assert (path != NULL);
 | 
			
		||||
 | 
			
		||||
  dir = g_dir_open (path, 0, NULL);
 | 
			
		||||
  if (dir == NULL)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  while ((name = g_dir_read_name (dir)))
 | 
			
		||||
    {
 | 
			
		||||
      g_autofree gchar *filename = NULL;
 | 
			
		||||
      g_autoptr(GKeyFile) keyfile = NULL;
 | 
			
		||||
 | 
			
		||||
      /* First added wins */
 | 
			
		||||
      if (g_hash_table_contains (folders, name))
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      filename = g_build_filename (path, name, NULL);
 | 
			
		||||
      keyfile = g_key_file_new ();
 | 
			
		||||
 | 
			
		||||
      if (g_key_file_load_from_file (keyfile, filename, G_KEY_FILE_NONE, NULL))
 | 
			
		||||
        g_hash_table_insert (folders,
 | 
			
		||||
                             g_strdup (name),
 | 
			
		||||
                             g_key_file_get_locale_string (keyfile,
 | 
			
		||||
                                                           "Desktop Entry",
 | 
			
		||||
                                                           "Name",
 | 
			
		||||
                                                           NULL,
 | 
			
		||||
                                                           NULL));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
load_folders (GHashTable *folders)
 | 
			
		||||
{
 | 
			
		||||
  const char * const *dirs;
 | 
			
		||||
  g_autofree gchar *userdir = NULL;
 | 
			
		||||
  guint i;
 | 
			
		||||
 | 
			
		||||
  g_assert (folders != NULL);
 | 
			
		||||
 | 
			
		||||
  userdir = g_build_filename (g_get_user_data_dir (), "desktop-directories", NULL);
 | 
			
		||||
  load_folder (folders, userdir);
 | 
			
		||||
 | 
			
		||||
  dirs = g_get_system_data_dirs ();
 | 
			
		||||
  for (i = 0; dirs[i] != NULL; i++)
 | 
			
		||||
    {
 | 
			
		||||
      g_autofree gchar *sysdir = g_build_filename (dirs[i], "desktop-directories", NULL);
 | 
			
		||||
      load_folder (folders, sysdir);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
shell_app_cache_worker (GTask        *task,
 | 
			
		||||
                        gpointer      source_object,
 | 
			
		||||
                        gpointer      task_data,
 | 
			
		||||
                        GCancellable *cancellable)
 | 
			
		||||
{
 | 
			
		||||
  CacheState *state;
 | 
			
		||||
 | 
			
		||||
  g_assert (G_IS_TASK (task));
 | 
			
		||||
  g_assert (SHELL_IS_APP_CACHE (source_object));
 | 
			
		||||
 | 
			
		||||
  state = cache_state_new ();
 | 
			
		||||
  state->app_infos = g_app_info_get_all ();
 | 
			
		||||
  load_folders (state->folders);
 | 
			
		||||
 | 
			
		||||
  g_task_return_pointer (task, state, (GDestroyNotify)cache_state_free);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
apply_update_cb (GObject      *object,
 | 
			
		||||
                 GAsyncResult *result,
 | 
			
		||||
                 gpointer      user_data)
 | 
			
		||||
{
 | 
			
		||||
  ShellAppCache *cache = (ShellAppCache *)object;
 | 
			
		||||
  g_autoptr(GError) error = NULL;
 | 
			
		||||
  CacheState *state;
 | 
			
		||||
 | 
			
		||||
  g_assert (SHELL_IS_APP_CACHE (cache));
 | 
			
		||||
  g_assert (G_IS_TASK (result));
 | 
			
		||||
  g_assert (user_data == NULL);
 | 
			
		||||
 | 
			
		||||
  state = g_task_propagate_pointer (G_TASK (result), &error);
 | 
			
		||||
 | 
			
		||||
  if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  g_mutex_lock (&cache->mutex);
 | 
			
		||||
  g_list_free_full (cache->app_infos, g_object_unref);
 | 
			
		||||
  cache->app_infos = g_steal_pointer (&state->app_infos);
 | 
			
		||||
  g_clear_pointer (&cache->folders, g_hash_table_unref);
 | 
			
		||||
  cache->folders = g_steal_pointer (&state->folders);
 | 
			
		||||
  g_mutex_unlock (&cache->mutex);
 | 
			
		||||
 | 
			
		||||
  g_signal_emit (cache, signals[CHANGED], 0);
 | 
			
		||||
 | 
			
		||||
  cache_state_free (state);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
shell_app_cache_do_update (gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
  ShellAppCache *cache = user_data;
 | 
			
		||||
  g_autoptr(GTask) task = NULL;
 | 
			
		||||
 | 
			
		||||
  cache->queued_update = 0;
 | 
			
		||||
 | 
			
		||||
  /* Reset the cancellable state so we don't race with
 | 
			
		||||
   * two updates coming back overlapped and applying the
 | 
			
		||||
   * information in the wrong order.
 | 
			
		||||
   */
 | 
			
		||||
  g_cancellable_cancel (cache->cancellable);
 | 
			
		||||
  g_clear_object (&cache->cancellable);
 | 
			
		||||
  cache->cancellable = g_cancellable_new ();
 | 
			
		||||
 | 
			
		||||
  task = g_task_new (cache, cache->cancellable, apply_update_cb, NULL);
 | 
			
		||||
  g_task_set_source_tag (task, shell_app_cache_do_update);
 | 
			
		||||
  g_task_run_in_thread (task, shell_app_cache_worker);
 | 
			
		||||
 | 
			
		||||
  return G_SOURCE_REMOVE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
shell_app_cache_queue_update (ShellAppCache *self)
 | 
			
		||||
{
 | 
			
		||||
  g_assert (SHELL_IS_APP_CACHE (self));
 | 
			
		||||
 | 
			
		||||
  if (self->queued_update != 0)
 | 
			
		||||
    g_source_remove (self->queued_update);
 | 
			
		||||
 | 
			
		||||
  self->queued_update = g_timeout_add_seconds (DEFAULT_TIMEOUT_SECONDS,
 | 
			
		||||
                                               shell_app_cache_do_update,
 | 
			
		||||
                                               self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
monitor_data_dir (ShellAppCache *self,
 | 
			
		||||
                  const gchar   *directory)
 | 
			
		||||
{
 | 
			
		||||
  g_autofree gchar *subdir = NULL;
 | 
			
		||||
  g_autoptr(GFile) file = NULL;
 | 
			
		||||
  g_autoptr(GFileMonitor) monitor = NULL;
 | 
			
		||||
 | 
			
		||||
  g_assert (SHELL_IS_APP_CACHE (self));
 | 
			
		||||
 | 
			
		||||
  if (directory == NULL)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  subdir = g_build_filename (directory, "desktop-directories", NULL);
 | 
			
		||||
  file = g_file_new_for_path (subdir);
 | 
			
		||||
  monitor = g_file_monitor_directory (file, G_FILE_MONITOR_NONE, NULL, NULL);
 | 
			
		||||
 | 
			
		||||
  if (monitor != NULL)
 | 
			
		||||
    {
 | 
			
		||||
      g_file_monitor_set_rate_limit (monitor, DEFAULT_TIMEOUT_SECONDS * 1000);
 | 
			
		||||
      g_signal_connect_object (monitor,
 | 
			
		||||
                               "changed",
 | 
			
		||||
                               G_CALLBACK (shell_app_cache_queue_update),
 | 
			
		||||
                               self,
 | 
			
		||||
                               G_CONNECT_SWAPPED);
 | 
			
		||||
      g_ptr_array_add (self->dir_monitors, g_steal_pointer (&monitor));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
shell_app_cache_finalize (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
  ShellAppCache *self = (ShellAppCache *)object;
 | 
			
		||||
 | 
			
		||||
  g_clear_object (&self->monitor);
 | 
			
		||||
 | 
			
		||||
  if (self->queued_update)
 | 
			
		||||
    {
 | 
			
		||||
      g_source_remove (self->queued_update);
 | 
			
		||||
      self->queued_update = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_clear_pointer (&self->dir_monitors, g_ptr_array_unref);
 | 
			
		||||
  g_clear_pointer (&self->folders, g_hash_table_unref);
 | 
			
		||||
  g_list_free_full (self->app_infos, g_object_unref);
 | 
			
		||||
  g_mutex_clear (&self->mutex);
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (shell_app_cache_parent_class)->finalize (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
shell_app_cache_class_init (ShellAppCacheClass *klass)
 | 
			
		||||
{
 | 
			
		||||
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
 | 
			
		||||
 | 
			
		||||
  object_class->finalize = shell_app_cache_finalize;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * ShellAppCache::changed:
 | 
			
		||||
   *
 | 
			
		||||
   * The "changed" signal is emitted when the cache has updated
 | 
			
		||||
   * information about installed applications.
 | 
			
		||||
   */
 | 
			
		||||
  signals [CHANGED] =
 | 
			
		||||
    g_signal_new ("changed",
 | 
			
		||||
                  G_TYPE_FROM_CLASS (klass),
 | 
			
		||||
                  G_SIGNAL_RUN_LAST,
 | 
			
		||||
                  0, NULL, NULL, NULL,
 | 
			
		||||
                  G_TYPE_NONE, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
shell_app_cache_init (ShellAppCache *self)
 | 
			
		||||
{
 | 
			
		||||
  const gchar * const *sysdirs;
 | 
			
		||||
  guint i;
 | 
			
		||||
 | 
			
		||||
  g_mutex_init (&self->mutex);
 | 
			
		||||
 | 
			
		||||
  /* Monitor directories for translation changes */
 | 
			
		||||
  self->dir_monitors = g_ptr_array_new_with_free_func (g_object_unref);
 | 
			
		||||
  monitor_data_dir (self, g_get_user_data_dir ());
 | 
			
		||||
  sysdirs = g_get_system_data_dirs ();
 | 
			
		||||
  for (i = 0; sysdirs[i] != NULL; i++)
 | 
			
		||||
    monitor_data_dir (self, sysdirs[i]);
 | 
			
		||||
 | 
			
		||||
  /* Load translated directory names immediately */
 | 
			
		||||
  self->folders = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
 | 
			
		||||
  load_folders (self->folders);
 | 
			
		||||
 | 
			
		||||
  /* Setup AppMonitor to track changes */
 | 
			
		||||
  self->monitor = g_app_info_monitor_get ();
 | 
			
		||||
  g_signal_connect_object (self->monitor,
 | 
			
		||||
                           "changed",
 | 
			
		||||
                           G_CALLBACK (shell_app_cache_queue_update),
 | 
			
		||||
                           self,
 | 
			
		||||
                           G_CONNECT_SWAPPED);
 | 
			
		||||
  self->app_infos = g_app_info_get_all ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * shell_app_cache_get_all:
 | 
			
		||||
 * @cache: (nullable): a #ShellAppCache or %NULL
 | 
			
		||||
 *
 | 
			
		||||
 * Like g_app_info_get_all() but always returns a
 | 
			
		||||
 * cached set of application info so the caller can be
 | 
			
		||||
 * sure that I/O will not happen on the current thread.
 | 
			
		||||
 *
 | 
			
		||||
 * Returns: (transfer full) (element-type GAppInfo):
 | 
			
		||||
 *   a newly allocated GList of references to GAppInfos.
 | 
			
		||||
 */
 | 
			
		||||
GList *
 | 
			
		||||
shell_app_cache_get_all (ShellAppCache *cache)
 | 
			
		||||
{
 | 
			
		||||
  GList *ret;
 | 
			
		||||
 | 
			
		||||
  if (cache == NULL)
 | 
			
		||||
    cache = shell_app_cache_get_default ();
 | 
			
		||||
 | 
			
		||||
  g_return_val_if_fail (SHELL_IS_APP_CACHE (cache), NULL);
 | 
			
		||||
 | 
			
		||||
  g_mutex_lock (&cache->mutex);
 | 
			
		||||
  ret = g_list_copy_deep (cache->app_infos, (GCopyFunc)g_object_ref, NULL);
 | 
			
		||||
  g_mutex_unlock (&cache->mutex);
 | 
			
		||||
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * shell_app_cache_get_info:
 | 
			
		||||
 * @cache: (nullable): a #ShellAppCache or %NULL
 | 
			
		||||
 * @id: the application id
 | 
			
		||||
 *
 | 
			
		||||
 * A replacement for g_desktop_app_info_new() that will lookup the information
 | 
			
		||||
 * from the cache instead of (re)loading from disk.
 | 
			
		||||
 *
 | 
			
		||||
 * Returns: (nullable) (transfer full): a #GDesktopAppInfo or %NULL
 | 
			
		||||
 */
 | 
			
		||||
GDesktopAppInfo *
 | 
			
		||||
shell_app_cache_get_info (ShellAppCache *cache,
 | 
			
		||||
                          const char    *id)
 | 
			
		||||
{
 | 
			
		||||
  GDesktopAppInfo *ret = NULL;
 | 
			
		||||
  const GList *iter;
 | 
			
		||||
 | 
			
		||||
  if (cache == NULL)
 | 
			
		||||
    cache = shell_app_cache_get_default ();
 | 
			
		||||
 | 
			
		||||
  g_return_val_if_fail (SHELL_IS_APP_CACHE (cache), NULL);
 | 
			
		||||
 | 
			
		||||
  g_mutex_lock (&cache->mutex);
 | 
			
		||||
 | 
			
		||||
  for (iter = cache->app_infos; iter != NULL; iter = iter->next)
 | 
			
		||||
    {
 | 
			
		||||
      GAppInfo *info = iter->data;
 | 
			
		||||
 | 
			
		||||
      if (g_strcmp0 (id, g_app_info_get_id (info)) == 0)
 | 
			
		||||
        {
 | 
			
		||||
          ret = g_object_ref (G_DESKTOP_APP_INFO (info));
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_mutex_unlock (&cache->mutex);
 | 
			
		||||
 | 
			
		||||
  return g_steal_pointer (&ret);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * shell_app_cache_translate_folder:
 | 
			
		||||
 * @cache: (nullable): a #ShellAppCache or %NULL
 | 
			
		||||
 * @name: the folder name
 | 
			
		||||
 *
 | 
			
		||||
 * Gets the translated folder name for @name if any exists. Otherwise
 | 
			
		||||
 * a copy of @name is returned.
 | 
			
		||||
 *
 | 
			
		||||
 * Returns: the translated string
 | 
			
		||||
 */
 | 
			
		||||
char *
 | 
			
		||||
shell_app_cache_translate_folder (ShellAppCache *cache,
 | 
			
		||||
                                  const char    *name)
 | 
			
		||||
{
 | 
			
		||||
  char *ret;
 | 
			
		||||
 | 
			
		||||
  if (cache == NULL)
 | 
			
		||||
    cache = shell_app_cache_get_default ();
 | 
			
		||||
 | 
			
		||||
  g_return_val_if_fail (SHELL_IS_APP_CACHE (cache), NULL);
 | 
			
		||||
 | 
			
		||||
  if (name == NULL)
 | 
			
		||||
    return NULL;
 | 
			
		||||
 | 
			
		||||
  g_mutex_lock (&cache->mutex);
 | 
			
		||||
  ret = g_strdup (g_hash_table_lookup (cache->folders, name));
 | 
			
		||||
  g_mutex_unlock (&cache->mutex);
 | 
			
		||||
 | 
			
		||||
  if (ret == NULL)
 | 
			
		||||
    ret = g_strdup (name);
 | 
			
		||||
 | 
			
		||||
  return g_steal_pointer (&ret);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										19
									
								
								src/shell-app-cache.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/shell-app-cache.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
#ifndef __SHELL_APP_CACHE__
 | 
			
		||||
#define __SHELL_APP_CACHE__
 | 
			
		||||
 | 
			
		||||
#include <gio/gio.h>
 | 
			
		||||
#include <gio/gdesktopappinfo.h>
 | 
			
		||||
 | 
			
		||||
#define SHELL_TYPE_APP_CACHE (shell_app_cache_get_type())
 | 
			
		||||
 | 
			
		||||
G_DECLARE_FINAL_TYPE (ShellAppCache, shell_app_cache, SHELL, APP_CACHE, GObject)
 | 
			
		||||
 | 
			
		||||
ShellAppCache   *shell_app_cache_get_default      (void);
 | 
			
		||||
GList           *shell_app_cache_get_all          (ShellAppCache *cache);
 | 
			
		||||
GDesktopAppInfo *shell_app_cache_get_info         (ShellAppCache *cache,
 | 
			
		||||
                                                   const char    *id);
 | 
			
		||||
char            *shell_app_cache_translate_folder (ShellAppCache *cache,
 | 
			
		||||
                                                   const char    *name);
 | 
			
		||||
 | 
			
		||||
#endif /* __SHELL_APP_CACHE__ */
 | 
			
		||||
@@ -9,11 +9,20 @@
 | 
			
		||||
#include <gio/gio.h>
 | 
			
		||||
#include <glib/gi18n.h>
 | 
			
		||||
 | 
			
		||||
#include "shell-app-cache.h"
 | 
			
		||||
#include "shell-app-private.h"
 | 
			
		||||
#include "shell-window-tracker-private.h"
 | 
			
		||||
#include "shell-app-system-private.h"
 | 
			
		||||
#include "shell-global.h"
 | 
			
		||||
#include "shell-util.h"
 | 
			
		||||
#include "st.h"
 | 
			
		||||
 | 
			
		||||
/* Rescan for at most RESCAN_TIMEOUT_MS * MAX_RESCAN_RETRIES. That
 | 
			
		||||
 * should be plenty of time for even a slow spinning drive to update
 | 
			
		||||
 * the icon cache.
 | 
			
		||||
 */
 | 
			
		||||
#define RESCAN_TIMEOUT_MS 2500
 | 
			
		||||
#define MAX_RESCAN_RETRIES 6
 | 
			
		||||
 | 
			
		||||
/* Vendor prefixes are something that can be preprended to a .desktop
 | 
			
		||||
 * file name.  Undo this.
 | 
			
		||||
@@ -50,6 +59,9 @@ struct _ShellAppSystemPrivate {
 | 
			
		||||
  GHashTable *running_apps;
 | 
			
		||||
  GHashTable *id_to_app;
 | 
			
		||||
  GHashTable *startup_wm_class_to_id;
 | 
			
		||||
 | 
			
		||||
  guint rescan_icons_timeout_id;
 | 
			
		||||
  guint n_rescan_retries;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void shell_app_system_finalize (GObject *object);
 | 
			
		||||
@@ -82,12 +94,14 @@ static void
 | 
			
		||||
scan_startup_wm_class_to_id (ShellAppSystem *self)
 | 
			
		||||
{
 | 
			
		||||
  ShellAppSystemPrivate *priv = self->priv;
 | 
			
		||||
  GList *apps, *l;
 | 
			
		||||
  g_autolist(GAppInfo) all = NULL;
 | 
			
		||||
  const GList *l;
 | 
			
		||||
 | 
			
		||||
  g_hash_table_remove_all (priv->startup_wm_class_to_id);
 | 
			
		||||
 | 
			
		||||
  apps = g_app_info_get_all ();
 | 
			
		||||
  for (l = apps; l != NULL; l = l->next)
 | 
			
		||||
  all = shell_app_cache_get_all (NULL);
 | 
			
		||||
 | 
			
		||||
  for (l = all; l != NULL; l = l->next)
 | 
			
		||||
    {
 | 
			
		||||
      GAppInfo *info = l->data;
 | 
			
		||||
      const char *startup_wm_class, *id, *old_id;
 | 
			
		||||
@@ -105,8 +119,6 @@ scan_startup_wm_class_to_id (ShellAppSystem *self)
 | 
			
		||||
        g_hash_table_insert (priv->startup_wm_class_to_id,
 | 
			
		||||
                             g_strdup (startup_wm_class), g_strdup (id));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_list_free_full (apps, g_object_unref);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
@@ -119,7 +131,7 @@ app_is_stale (ShellApp *app)
 | 
			
		||||
  if (shell_app_is_window_backed (app))
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  info = g_desktop_app_info_new (shell_app_get_id (app));
 | 
			
		||||
  info = shell_app_cache_get_info (NULL, shell_app_get_id (app));
 | 
			
		||||
  if (!info)
 | 
			
		||||
    return TRUE;
 | 
			
		||||
 | 
			
		||||
@@ -156,12 +168,52 @@ stale_app_remove_func (gpointer key,
 | 
			
		||||
  return app_is_stale (value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
installed_changed (GAppInfoMonitor *monitor,
 | 
			
		||||
                   gpointer         user_data)
 | 
			
		||||
static gboolean
 | 
			
		||||
rescan_icon_theme_cb (gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
  ShellAppSystem *self = user_data;
 | 
			
		||||
  ShellAppSystemPrivate *priv;
 | 
			
		||||
  ShellAppSystem *self;
 | 
			
		||||
  StTextureCache *texture_cache;
 | 
			
		||||
  gboolean rescanned;
 | 
			
		||||
 | 
			
		||||
  self = (ShellAppSystem *) user_data;
 | 
			
		||||
  priv = self->priv;
 | 
			
		||||
 | 
			
		||||
  texture_cache = st_texture_cache_get_default ();
 | 
			
		||||
  rescanned = st_texture_cache_rescan_icon_theme (texture_cache);
 | 
			
		||||
 | 
			
		||||
  priv->n_rescan_retries++;
 | 
			
		||||
 | 
			
		||||
  if (rescanned || priv->n_rescan_retries >= MAX_RESCAN_RETRIES)
 | 
			
		||||
    {
 | 
			
		||||
      priv->n_rescan_retries = 0;
 | 
			
		||||
      priv->rescan_icons_timeout_id = 0;
 | 
			
		||||
      return G_SOURCE_REMOVE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return G_SOURCE_CONTINUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
rescan_icon_theme (ShellAppSystem *self)
 | 
			
		||||
{
 | 
			
		||||
  ShellAppSystemPrivate *priv = self->priv;
 | 
			
		||||
 | 
			
		||||
  priv->n_rescan_retries = 0;
 | 
			
		||||
 | 
			
		||||
  if (priv->rescan_icons_timeout_id > 0)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  priv->rescan_icons_timeout_id = g_timeout_add (RESCAN_TIMEOUT_MS,
 | 
			
		||||
                                                 rescan_icon_theme_cb,
 | 
			
		||||
                                                 self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
installed_changed (ShellAppCache  *cache,
 | 
			
		||||
                   ShellAppSystem *self)
 | 
			
		||||
{
 | 
			
		||||
  rescan_icon_theme (self);
 | 
			
		||||
  scan_startup_wm_class_to_id (self);
 | 
			
		||||
 | 
			
		||||
  g_hash_table_foreach_remove (self->priv->id_to_app, stale_app_remove_func, NULL);
 | 
			
		||||
@@ -173,7 +225,7 @@ static void
 | 
			
		||||
shell_app_system_init (ShellAppSystem *self)
 | 
			
		||||
{
 | 
			
		||||
  ShellAppSystemPrivate *priv;
 | 
			
		||||
  GAppInfoMonitor *monitor;
 | 
			
		||||
  ShellAppCache *cache;
 | 
			
		||||
 | 
			
		||||
  self->priv = priv = shell_app_system_get_instance_private (self);
 | 
			
		||||
 | 
			
		||||
@@ -184,9 +236,9 @@ shell_app_system_init (ShellAppSystem *self)
 | 
			
		||||
 | 
			
		||||
  priv->startup_wm_class_to_id = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
 | 
			
		||||
 | 
			
		||||
  monitor = g_app_info_monitor_get ();
 | 
			
		||||
  g_signal_connect (monitor, "changed", G_CALLBACK (installed_changed), self);
 | 
			
		||||
  installed_changed (monitor, self);
 | 
			
		||||
  cache = shell_app_cache_get_default ();
 | 
			
		||||
  g_signal_connect (cache, "changed", G_CALLBACK (installed_changed), self);
 | 
			
		||||
  installed_changed (cache, self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -199,6 +251,9 @@ shell_app_system_finalize (GObject *object)
 | 
			
		||||
  g_hash_table_destroy (priv->id_to_app);
 | 
			
		||||
  g_hash_table_destroy (priv->startup_wm_class_to_id);
 | 
			
		||||
 | 
			
		||||
  if (priv->rescan_icons_timeout_id)
 | 
			
		||||
    g_source_remove (priv->rescan_icons_timeout_id);
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (shell_app_system_parent_class)->finalize (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -237,7 +292,7 @@ shell_app_system_lookup_app (ShellAppSystem   *self,
 | 
			
		||||
  if (app)
 | 
			
		||||
    return app;
 | 
			
		||||
 | 
			
		||||
  info = g_desktop_app_info_new (id);
 | 
			
		||||
  info = shell_app_cache_get_info (NULL, id);
 | 
			
		||||
  if (!info)
 | 
			
		||||
    return NULL;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1190,37 +1190,12 @@ app_child_setup (gpointer user_data)
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
_shell_app_watch_callback (GPid      pid,
 | 
			
		||||
                           gint      status,
 | 
			
		||||
                           ShellApp *app)
 | 
			
		||||
{
 | 
			
		||||
  if (app->state == SHELL_APP_STATE_STARTING)
 | 
			
		||||
    {
 | 
			
		||||
      ShellWindowTracker *tracker = shell_window_tracker_get_default ();
 | 
			
		||||
      GSList *startup_sequences = shell_window_tracker_get_startup_sequences (tracker);
 | 
			
		||||
      GSList *iter = NULL;
 | 
			
		||||
 | 
			
		||||
      for (iter = startup_sequences; iter; iter = g_slist_next (iter))
 | 
			
		||||
        {
 | 
			
		||||
          ShellStartupSequence *sequence = (ShellStartupSequence*) iter->data;
 | 
			
		||||
          ShellApp *startup_app = shell_startup_sequence_get_app (sequence);
 | 
			
		||||
          if (startup_app == app)
 | 
			
		||||
            shell_startup_sequence_complete (sequence);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      shell_app_state_transition (app, SHELL_APP_STATE_STOPPED);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_spawn_close_pid (pid);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
wait_pid (GDesktopAppInfo *appinfo,
 | 
			
		||||
          GPid             pid,
 | 
			
		||||
          ShellApp        *app)
 | 
			
		||||
          gpointer         user_data)
 | 
			
		||||
{
 | 
			
		||||
  g_child_watch_add (pid, (GChildWatchFunc) _shell_app_watch_callback, app);
 | 
			
		||||
  g_child_watch_add (pid, (GChildWatchFunc) g_spawn_close_pid, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -1267,8 +1242,7 @@ shell_app_launch (ShellApp     *app,
 | 
			
		||||
#else
 | 
			
		||||
                                                   NULL, NULL,
 | 
			
		||||
#endif
 | 
			
		||||
                                                   (GDesktopAppLaunchCallback) wait_pid,
 | 
			
		||||
                                                   app,
 | 
			
		||||
                                                   wait_pid, NULL,
 | 
			
		||||
                                                   error);
 | 
			
		||||
  g_object_unref (context);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -87,6 +87,8 @@ struct _ShellGlobal {
 | 
			
		||||
  /* For sound notifications */
 | 
			
		||||
  ca_context *sound_context;
 | 
			
		||||
 | 
			
		||||
  GHashTable *save_ops;
 | 
			
		||||
 | 
			
		||||
  gboolean has_modal;
 | 
			
		||||
  gboolean frame_timestamps;
 | 
			
		||||
  gboolean frame_finish_timestamp;
 | 
			
		||||
@@ -322,6 +324,10 @@ shell_global_init (ShellGlobal *global)
 | 
			
		||||
                                     NULL);
 | 
			
		||||
 | 
			
		||||
  g_strfreev (search_path);
 | 
			
		||||
 | 
			
		||||
  global->save_ops = g_hash_table_new_full (g_file_hash,
 | 
			
		||||
                                            (GEqualFunc) g_file_equal,
 | 
			
		||||
                                            g_object_unref, g_object_unref);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -341,6 +347,8 @@ shell_global_finalize (GObject *object)
 | 
			
		||||
  g_free (global->imagedir);
 | 
			
		||||
  g_free (global->userdatadir);
 | 
			
		||||
 | 
			
		||||
  g_hash_table_unref (global->save_ops);
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS(shell_global_parent_class)->finalize (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1757,20 +1765,133 @@ shell_global_get_session_mode (ShellGlobal *global)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
save_variant (GFile      *dir,
 | 
			
		||||
              const char *property_name,
 | 
			
		||||
              GVariant   *variant)
 | 
			
		||||
delete_variant_cb (GObject      *object,
 | 
			
		||||
                   GAsyncResult *result,
 | 
			
		||||
                   gpointer      user_data)
 | 
			
		||||
{
 | 
			
		||||
  ShellGlobal *global = user_data;
 | 
			
		||||
  GError *error = NULL;
 | 
			
		||||
 | 
			
		||||
  if (!g_file_delete_finish (G_FILE (object), result, &error))
 | 
			
		||||
    {
 | 
			
		||||
      if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
 | 
			
		||||
        {
 | 
			
		||||
          g_warning ("Could not delete runtime/persistent state file: %s\n",
 | 
			
		||||
                     error->message);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      g_error_free (error);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_hash_table_remove (global->save_ops, object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
replace_contents_worker (GTask        *task,
 | 
			
		||||
                         gpointer      source_object,
 | 
			
		||||
                         gpointer      task_data,
 | 
			
		||||
                         GCancellable *cancellable)
 | 
			
		||||
{
 | 
			
		||||
  GFile *file = source_object;
 | 
			
		||||
  GBytes *bytes = task_data;
 | 
			
		||||
  GError *error = NULL;
 | 
			
		||||
  const gchar *data;
 | 
			
		||||
  gsize len;
 | 
			
		||||
 | 
			
		||||
  data = g_bytes_get_data (bytes, &len);
 | 
			
		||||
 | 
			
		||||
  if (!g_file_replace_contents (file, data, len, NULL, FALSE,
 | 
			
		||||
                                G_FILE_CREATE_REPLACE_DESTINATION,
 | 
			
		||||
                                NULL, cancellable, &error))
 | 
			
		||||
    g_task_return_error (task, g_steal_pointer (&error));
 | 
			
		||||
  else
 | 
			
		||||
    g_task_return_boolean (task, TRUE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
replace_contents_async (GFile               *path,
 | 
			
		||||
                        GBytes              *bytes,
 | 
			
		||||
                        GCancellable        *cancellable,
 | 
			
		||||
                        GAsyncReadyCallback  callback,
 | 
			
		||||
                        gpointer             user_data)
 | 
			
		||||
{
 | 
			
		||||
  g_autoptr(GTask) task = NULL;
 | 
			
		||||
 | 
			
		||||
  g_assert (G_IS_FILE (path));
 | 
			
		||||
  g_assert (bytes != NULL);
 | 
			
		||||
  g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
 | 
			
		||||
 | 
			
		||||
  task = g_task_new (path, cancellable, callback, user_data);
 | 
			
		||||
  g_task_set_source_tag (task, replace_contents_async);
 | 
			
		||||
  g_task_set_task_data (task, g_bytes_ref (bytes), (GDestroyNotify)g_bytes_unref);
 | 
			
		||||
  g_task_run_in_thread (task, replace_contents_worker);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
replace_contents_finish (GFile         *file,
 | 
			
		||||
                         GAsyncResult  *result,
 | 
			
		||||
                         GError       **error)
 | 
			
		||||
{
 | 
			
		||||
  return g_task_propagate_boolean (G_TASK (result), error);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
replace_variant_cb (GObject      *object,
 | 
			
		||||
                    GAsyncResult *result,
 | 
			
		||||
                    gpointer      user_data)
 | 
			
		||||
{
 | 
			
		||||
  ShellGlobal *global = user_data;
 | 
			
		||||
  GError *error = NULL;
 | 
			
		||||
 | 
			
		||||
  if (!replace_contents_finish (G_FILE (object), result, &error))
 | 
			
		||||
    {
 | 
			
		||||
      if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
 | 
			
		||||
        {
 | 
			
		||||
          g_warning ("Could not replace runtime/persistent state file: %s\n",
 | 
			
		||||
                     error->message);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      g_error_free (error);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_hash_table_remove (global->save_ops, object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
save_variant (ShellGlobal *global,
 | 
			
		||||
              GFile       *dir,
 | 
			
		||||
              const char  *property_name,
 | 
			
		||||
              GVariant    *variant)
 | 
			
		||||
{
 | 
			
		||||
  GFile *path = g_file_get_child (dir, property_name);
 | 
			
		||||
  GCancellable *cancellable;
 | 
			
		||||
 | 
			
		||||
  cancellable = g_hash_table_lookup (global->save_ops, path);
 | 
			
		||||
  g_cancellable_cancel (cancellable);
 | 
			
		||||
 | 
			
		||||
  cancellable = g_cancellable_new ();
 | 
			
		||||
  g_hash_table_insert (global->save_ops, g_object_ref (path), cancellable);
 | 
			
		||||
 | 
			
		||||
  if (variant == NULL || g_variant_get_data (variant) == NULL)
 | 
			
		||||
    (void) g_file_delete (path, NULL, NULL);
 | 
			
		||||
    {
 | 
			
		||||
      g_file_delete_async (path, G_PRIORITY_DEFAULT, cancellable,
 | 
			
		||||
                           delete_variant_cb, global);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      gsize size = g_variant_get_size (variant);
 | 
			
		||||
      g_file_replace_contents (path, g_variant_get_data (variant), size,
 | 
			
		||||
                               NULL, FALSE, G_FILE_CREATE_REPLACE_DESTINATION,
 | 
			
		||||
                               NULL, NULL, NULL);
 | 
			
		||||
      g_autoptr(GBytes) bytes = NULL;
 | 
			
		||||
 | 
			
		||||
      bytes = g_bytes_new_with_free_func (g_variant_get_data (variant),
 | 
			
		||||
                                          g_variant_get_size (variant),
 | 
			
		||||
                                          (GDestroyNotify)g_variant_unref,
 | 
			
		||||
                                          g_variant_ref (variant));
 | 
			
		||||
      /* g_file_replace_contents_async() can potentially fsync() from the
 | 
			
		||||
       * calling thread when completing the asynchronous task. Instead, we
 | 
			
		||||
       * want to force that fsync() to a thread to avoid blocking the
 | 
			
		||||
       * compositor main loop. Using our own replace_contents_async()
 | 
			
		||||
       * simply executes the operation synchronously from a thread.
 | 
			
		||||
       */
 | 
			
		||||
      replace_contents_async (path, bytes, cancellable, replace_variant_cb, global);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_object_unref (path);
 | 
			
		||||
@@ -1824,7 +1945,7 @@ shell_global_set_runtime_state (ShellGlobal  *global,
 | 
			
		||||
                                const char   *property_name,
 | 
			
		||||
                                GVariant     *variant)
 | 
			
		||||
{
 | 
			
		||||
  save_variant (global->runtime_state_path, property_name, variant);
 | 
			
		||||
  save_variant (global, global->runtime_state_path, property_name, variant);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -1859,7 +1980,7 @@ shell_global_set_persistent_state (ShellGlobal *global,
 | 
			
		||||
                                   const char  *property_name,
 | 
			
		||||
                                   GVariant    *variant)
 | 
			
		||||
{
 | 
			
		||||
  save_variant (global->userdatadir_path, property_name, variant);
 | 
			
		||||
  save_variant (global, global->userdatadir_path, property_name, variant);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 
 | 
			
		||||
@@ -906,11 +906,6 @@ shell_startup_sequence_create_icon (ShellStartupSequence *sequence, guint size)
 | 
			
		||||
  return texture;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
shell_startup_sequence_complete (ShellStartupSequence *sequence)
 | 
			
		||||
{
 | 
			
		||||
  sn_startup_sequence_complete ((SnStartupSequence*)sequence);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * shell_window_tracker_get_default:
 | 
			
		||||
 
 | 
			
		||||
@@ -36,7 +36,6 @@ const char *shell_startup_sequence_get_name (ShellStartupSequence *sequence);
 | 
			
		||||
gboolean shell_startup_sequence_get_completed (ShellStartupSequence *sequence);
 | 
			
		||||
int shell_startup_sequence_get_workspace (ShellStartupSequence *sequence);
 | 
			
		||||
ClutterActor *shell_startup_sequence_create_icon (ShellStartupSequence *sequence, guint size);
 | 
			
		||||
void shell_startup_sequence_complete (ShellStartupSequence *sequence);
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -205,7 +205,8 @@ st_adjustment_class_init (StAdjustmentClass *klass)
 | 
			
		||||
                                                        G_MAXDOUBLE,
 | 
			
		||||
                                                        0.0,
 | 
			
		||||
                                                        ST_PARAM_READWRITE |
 | 
			
		||||
                                                        G_PARAM_CONSTRUCT));
 | 
			
		||||
                                                        G_PARAM_CONSTRUCT |
 | 
			
		||||
                                                        G_PARAM_EXPLICIT_NOTIFY));
 | 
			
		||||
  g_object_class_install_property (object_class,
 | 
			
		||||
                                   PROP_UPPER,
 | 
			
		||||
                                   g_param_spec_double ("upper",
 | 
			
		||||
@@ -215,7 +216,8 @@ st_adjustment_class_init (StAdjustmentClass *klass)
 | 
			
		||||
                                                        G_MAXDOUBLE,
 | 
			
		||||
                                                        0.0,
 | 
			
		||||
                                                        ST_PARAM_READWRITE |
 | 
			
		||||
                                                        G_PARAM_CONSTRUCT));
 | 
			
		||||
                                                        G_PARAM_CONSTRUCT |
 | 
			
		||||
                                                        G_PARAM_EXPLICIT_NOTIFY));
 | 
			
		||||
  g_object_class_install_property (object_class,
 | 
			
		||||
                                   PROP_VALUE,
 | 
			
		||||
                                   g_param_spec_double ("value",
 | 
			
		||||
@@ -225,7 +227,8 @@ st_adjustment_class_init (StAdjustmentClass *klass)
 | 
			
		||||
                                                        G_MAXDOUBLE,
 | 
			
		||||
                                                        0.0,
 | 
			
		||||
                                                        ST_PARAM_READWRITE |
 | 
			
		||||
                                                        G_PARAM_CONSTRUCT));
 | 
			
		||||
                                                        G_PARAM_CONSTRUCT |
 | 
			
		||||
                                                        G_PARAM_EXPLICIT_NOTIFY));
 | 
			
		||||
  g_object_class_install_property (object_class,
 | 
			
		||||
                                   PROP_STEP_INC,
 | 
			
		||||
                                   g_param_spec_double ("step-increment",
 | 
			
		||||
@@ -235,7 +238,8 @@ st_adjustment_class_init (StAdjustmentClass *klass)
 | 
			
		||||
                                                        G_MAXDOUBLE,
 | 
			
		||||
                                                        0.0,
 | 
			
		||||
                                                        ST_PARAM_READWRITE |
 | 
			
		||||
                                                        G_PARAM_CONSTRUCT));
 | 
			
		||||
                                                        G_PARAM_CONSTRUCT |
 | 
			
		||||
                                                        G_PARAM_EXPLICIT_NOTIFY));
 | 
			
		||||
  g_object_class_install_property (object_class,
 | 
			
		||||
                                   PROP_PAGE_INC,
 | 
			
		||||
                                   g_param_spec_double ("page-increment",
 | 
			
		||||
@@ -245,7 +249,8 @@ st_adjustment_class_init (StAdjustmentClass *klass)
 | 
			
		||||
                                                        G_MAXDOUBLE,
 | 
			
		||||
                                                        0.0,
 | 
			
		||||
                                                        ST_PARAM_READWRITE |
 | 
			
		||||
                                                        G_PARAM_CONSTRUCT));
 | 
			
		||||
                                                        G_PARAM_CONSTRUCT |
 | 
			
		||||
                                                        G_PARAM_EXPLICIT_NOTIFY));
 | 
			
		||||
  g_object_class_install_property (object_class,
 | 
			
		||||
                                   PROP_PAGE_SIZE,
 | 
			
		||||
                                   g_param_spec_double ("page-size",
 | 
			
		||||
@@ -255,7 +260,8 @@ st_adjustment_class_init (StAdjustmentClass *klass)
 | 
			
		||||
                                                        G_MAXDOUBLE,
 | 
			
		||||
                                                        0.0,
 | 
			
		||||
                                                        ST_PARAM_READWRITE |
 | 
			
		||||
                                                        G_PARAM_CONSTRUCT));
 | 
			
		||||
                                                        G_PARAM_CONSTRUCT |
 | 
			
		||||
                                                        G_PARAM_EXPLICIT_NOTIFY));
 | 
			
		||||
  /**
 | 
			
		||||
   * StAdjustment::changed:
 | 
			
		||||
   * @self: the #StAdjustment
 | 
			
		||||
 
 | 
			
		||||
@@ -177,15 +177,15 @@ st_bin_get_preferred_height (ClutterActor *self,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
st_bin_dispose (GObject *gobject)
 | 
			
		||||
st_bin_destroy (ClutterActor *actor)
 | 
			
		||||
{
 | 
			
		||||
  StBinPrivate *priv = st_bin_get_instance_private (ST_BIN (gobject));
 | 
			
		||||
  StBinPrivate *priv = st_bin_get_instance_private (ST_BIN (actor));
 | 
			
		||||
 | 
			
		||||
  if (priv->child)
 | 
			
		||||
    clutter_actor_destroy (priv->child);
 | 
			
		||||
  g_assert (priv->child == NULL);
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (st_bin_parent_class)->dispose (gobject);
 | 
			
		||||
  CLUTTER_ACTOR_CLASS (st_bin_parent_class)->destroy (actor);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -315,11 +315,11 @@ st_bin_class_init (StBinClass *klass)
 | 
			
		||||
 | 
			
		||||
  gobject_class->set_property = st_bin_set_property;
 | 
			
		||||
  gobject_class->get_property = st_bin_get_property;
 | 
			
		||||
  gobject_class->dispose = st_bin_dispose;
 | 
			
		||||
 | 
			
		||||
  actor_class->get_preferred_width = st_bin_get_preferred_width;
 | 
			
		||||
  actor_class->get_preferred_height = st_bin_get_preferred_height;
 | 
			
		||||
  actor_class->allocate = st_bin_allocate;
 | 
			
		||||
  actor_class->destroy = st_bin_destroy;
 | 
			
		||||
 | 
			
		||||
  widget_class->popup_menu = st_bin_popup_menu;
 | 
			
		||||
  widget_class->navigate_focus = st_bin_navigate_focus;
 | 
			
		||||
 
 | 
			
		||||
@@ -90,7 +90,7 @@ adjustment_value_notify_cb (StAdjustment *adjustment,
 | 
			
		||||
                            GParamSpec   *pspec,
 | 
			
		||||
                            StBoxLayout  *box)
 | 
			
		||||
{
 | 
			
		||||
  clutter_actor_queue_redraw (CLUTTER_ACTOR (box));
 | 
			
		||||
  clutter_actor_queue_relayout (CLUTTER_ACTOR (box));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -490,7 +490,7 @@ st_box_layout_get_paint_volume (ClutterActor       *actor,
 | 
			
		||||
                                ClutterPaintVolume *volume)
 | 
			
		||||
{
 | 
			
		||||
  StBoxLayout *self = ST_BOX_LAYOUT (actor);
 | 
			
		||||
  gdouble x, y;
 | 
			
		||||
  gdouble x, y, lower, upper;
 | 
			
		||||
  StBoxLayoutPrivate *priv = self->priv;
 | 
			
		||||
  StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor));
 | 
			
		||||
  ClutterActorBox allocation_box;
 | 
			
		||||
@@ -505,13 +505,42 @@ st_box_layout_get_paint_volume (ClutterActor       *actor,
 | 
			
		||||
   * our paint volume on that. */
 | 
			
		||||
  if (priv->hadjustment || priv->vadjustment)
 | 
			
		||||
    {
 | 
			
		||||
      gdouble width, height;
 | 
			
		||||
 | 
			
		||||
      clutter_actor_get_allocation_box (actor, &allocation_box);
 | 
			
		||||
      st_theme_node_get_content_box (theme_node, &allocation_box, &content_box);
 | 
			
		||||
      origin.x = content_box.x1 - allocation_box.x1;
 | 
			
		||||
      origin.y = content_box.y1 - allocation_box.y2;
 | 
			
		||||
      origin.z = 0.f;
 | 
			
		||||
      clutter_paint_volume_set_width (volume, content_box.x2 - content_box.x1);
 | 
			
		||||
      clutter_paint_volume_set_height (volume, content_box.y2 - content_box.y1);
 | 
			
		||||
 | 
			
		||||
      if (priv->hadjustment)
 | 
			
		||||
        {
 | 
			
		||||
          g_object_get (priv->hadjustment,
 | 
			
		||||
                        "lower", &lower,
 | 
			
		||||
                        "upper", &upper,
 | 
			
		||||
                        NULL);
 | 
			
		||||
          width = upper - lower;
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        {
 | 
			
		||||
          width = content_box.x2 - content_box.x1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      if (priv->vadjustment)
 | 
			
		||||
        {
 | 
			
		||||
          g_object_get (priv->vadjustment,
 | 
			
		||||
                        "lower", &lower,
 | 
			
		||||
                        "upper", &upper,
 | 
			
		||||
                        NULL);
 | 
			
		||||
          height = upper - lower;
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        {
 | 
			
		||||
          height = content_box.y2 - content_box.y1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      clutter_paint_volume_set_width (volume, width);
 | 
			
		||||
      clutter_paint_volume_set_height (volume, height);
 | 
			
		||||
    }
 | 
			
		||||
  else if (!CLUTTER_ACTOR_CLASS (st_box_layout_parent_class)->get_paint_volume (actor, volume))
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 
 | 
			
		||||
@@ -248,14 +248,17 @@ st_button_touch_event (ClutterActor      *actor,
 | 
			
		||||
  if (event->type == CLUTTER_TOUCH_BEGIN && !priv->press_sequence)
 | 
			
		||||
    {
 | 
			
		||||
      clutter_input_device_sequence_grab (device, sequence, actor);
 | 
			
		||||
      st_button_press (button, device, 0, sequence);
 | 
			
		||||
      if (!clutter_event_is_pointer_emulated ((ClutterEvent*) event))
 | 
			
		||||
        st_button_press (button, device, 0, sequence);
 | 
			
		||||
      return CLUTTER_EVENT_STOP;
 | 
			
		||||
    }
 | 
			
		||||
  else if (event->type == CLUTTER_TOUCH_END &&
 | 
			
		||||
           priv->device == device &&
 | 
			
		||||
           priv->press_sequence == sequence)
 | 
			
		||||
    {
 | 
			
		||||
      st_button_release (button, device, mask, 0, sequence);
 | 
			
		||||
      if (!clutter_event_is_pointer_emulated ((ClutterEvent*) event))
 | 
			
		||||
        st_button_release (button, device, mask, 0, sequence);
 | 
			
		||||
 | 
			
		||||
      clutter_input_device_sequence_ungrab (device, sequence);
 | 
			
		||||
      return CLUTTER_EVENT_STOP;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -308,8 +308,9 @@ st_entry_style_changed (StWidget *self)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  theme_node = st_widget_get_theme_node (self);
 | 
			
		||||
 | 
			
		||||
  _st_set_text_from_style (CLUTTER_TEXT (priv->entry), theme_node);
 | 
			
		||||
 
 | 
			
		||||
  st_theme_node_get_foreground_color (theme_node, &color);
 | 
			
		||||
  clutter_text_set_color (CLUTTER_TEXT (priv->entry), &color);
 | 
			
		||||
 | 
			
		||||
  if (st_theme_node_lookup_length (theme_node, "caret-size", TRUE, &size))
 | 
			
		||||
    clutter_text_set_cursor_size (CLUTTER_TEXT (priv->entry), (int)(.5 + size));
 | 
			
		||||
@@ -905,6 +906,13 @@ st_entry_unmap (ClutterActor *actor)
 | 
			
		||||
  CLUTTER_ACTOR_CLASS (st_entry_parent_class)->unmap (actor);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
st_entry_get_paint_volume (ClutterActor       *actor,
 | 
			
		||||
                           ClutterPaintVolume *volume)
 | 
			
		||||
{
 | 
			
		||||
  return clutter_paint_volume_set_from_allocation (volume, actor);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
st_entry_class_init (StEntryClass *klass)
 | 
			
		||||
{
 | 
			
		||||
@@ -922,6 +930,7 @@ st_entry_class_init (StEntryClass *klass)
 | 
			
		||||
  actor_class->allocate = st_entry_allocate;
 | 
			
		||||
  actor_class->paint = st_entry_paint;
 | 
			
		||||
  actor_class->unmap = st_entry_unmap;
 | 
			
		||||
  actor_class->get_paint_volume = st_entry_get_paint_volume;
 | 
			
		||||
 | 
			
		||||
  actor_class->key_press_event = st_entry_key_press_event;
 | 
			
		||||
  actor_class->key_focus_in = st_entry_key_focus_in;
 | 
			
		||||
@@ -1286,10 +1295,10 @@ st_entry_get_input_hints (StEntry *entry)
 | 
			
		||||
  return clutter_text_get_input_hints (CLUTTER_TEXT (priv->entry));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
_st_entry_icon_press_cb (ClutterActor       *actor,
 | 
			
		||||
                         ClutterButtonEvent *event,
 | 
			
		||||
                         StEntry            *entry)
 | 
			
		||||
static void
 | 
			
		||||
_st_entry_icon_clicked_cb (ClutterClickAction *action,
 | 
			
		||||
                           ClutterActor       *actor,
 | 
			
		||||
                           StEntry            *entry)
 | 
			
		||||
{
 | 
			
		||||
  StEntryPrivate *priv = ST_ENTRY_PRIV (entry);
 | 
			
		||||
 | 
			
		||||
@@ -1297,8 +1306,6 @@ _st_entry_icon_press_cb (ClutterActor       *actor,
 | 
			
		||||
    g_signal_emit (entry, entry_signals[PRIMARY_ICON_CLICKED], 0);
 | 
			
		||||
  else
 | 
			
		||||
    g_signal_emit (entry, entry_signals[SECONDARY_ICON_CLICKED], 0);
 | 
			
		||||
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -1308,21 +1315,24 @@ _st_entry_set_icon (StEntry       *entry,
 | 
			
		||||
{
 | 
			
		||||
  if (*icon)
 | 
			
		||||
    {
 | 
			
		||||
      g_signal_handlers_disconnect_by_func (*icon,
 | 
			
		||||
                                            _st_entry_icon_press_cb,
 | 
			
		||||
                                            entry);
 | 
			
		||||
      clutter_actor_remove_action_by_name (*icon, "entry-icon-action");
 | 
			
		||||
      clutter_actor_remove_child (CLUTTER_ACTOR (entry), *icon);
 | 
			
		||||
      *icon = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (new_icon)
 | 
			
		||||
    {
 | 
			
		||||
      ClutterAction *action;
 | 
			
		||||
 | 
			
		||||
      *icon = g_object_ref (new_icon);
 | 
			
		||||
 | 
			
		||||
      clutter_actor_set_reactive (*icon, TRUE);
 | 
			
		||||
      clutter_actor_add_child (CLUTTER_ACTOR (entry), *icon);
 | 
			
		||||
      g_signal_connect (*icon, "button-release-event",
 | 
			
		||||
                        G_CALLBACK (_st_entry_icon_press_cb), entry);
 | 
			
		||||
 | 
			
		||||
      action = clutter_click_action_new ();
 | 
			
		||||
      clutter_actor_add_action_with_name (*icon, "entry-icon-action", action);
 | 
			
		||||
      g_signal_connect (action, "clicked",
 | 
			
		||||
                        G_CALLBACK (_st_entry_icon_clicked_cb), entry);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  clutter_actor_queue_relayout (CLUTTER_ACTOR (entry));
 | 
			
		||||
 
 | 
			
		||||
@@ -180,6 +180,7 @@ st_label_dispose (GObject   *object)
 | 
			
		||||
{
 | 
			
		||||
  StLabelPrivate *priv = ST_LABEL (object)->priv;
 | 
			
		||||
 | 
			
		||||
  priv->label = NULL;
 | 
			
		||||
  g_clear_pointer (&priv->text_shadow_pipeline, cogl_object_unref);
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (st_label_parent_class)->dispose (object);
 | 
			
		||||
 
 | 
			
		||||
@@ -116,7 +116,6 @@ _st_set_text_from_style (ClutterText *text,
 | 
			
		||||
  PangoAttrList *attribs = NULL;
 | 
			
		||||
  const PangoFontDescription *font;
 | 
			
		||||
  StTextAlign align;
 | 
			
		||||
  gdouble spacing;
 | 
			
		||||
 | 
			
		||||
  st_theme_node_get_foreground_color (theme_node, &color);
 | 
			
		||||
  clutter_text_set_color (text, &color);
 | 
			
		||||
@@ -124,11 +123,11 @@ _st_set_text_from_style (ClutterText *text,
 | 
			
		||||
  font = st_theme_node_get_font (theme_node);
 | 
			
		||||
  clutter_text_set_font_description (text, (PangoFontDescription *) font);
 | 
			
		||||
 | 
			
		||||
  attribs = pango_attr_list_new ();
 | 
			
		||||
 | 
			
		||||
  decoration = st_theme_node_get_text_decoration (theme_node);
 | 
			
		||||
  if (decoration)
 | 
			
		||||
    {
 | 
			
		||||
      attribs = pango_attr_list_new ();
 | 
			
		||||
 | 
			
		||||
      if (decoration & ST_TEXT_DECORATION_UNDERLINE)
 | 
			
		||||
        {
 | 
			
		||||
          PangoAttribute *underline = pango_attr_underline_new (PANGO_UNDERLINE_SINGLE);
 | 
			
		||||
@@ -144,13 +143,6 @@ _st_set_text_from_style (ClutterText *text,
 | 
			
		||||
       */
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  spacing = st_theme_node_get_letter_spacing (theme_node);
 | 
			
		||||
  if (spacing)
 | 
			
		||||
    {
 | 
			
		||||
      PangoAttribute *letter_spacing = pango_attr_letter_spacing_new ((int)(.5 + spacing) * PANGO_SCALE);
 | 
			
		||||
      pango_attr_list_insert (attribs, letter_spacing);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  clutter_text_set_attributes (text, attribs);
 | 
			
		||||
 | 
			
		||||
  if (attribs)
 | 
			
		||||
 
 | 
			
		||||
@@ -304,6 +304,13 @@ st_scroll_view_pick (ClutterActor       *actor,
 | 
			
		||||
    clutter_actor_paint (priv->vscroll);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
st_scroll_view_get_paint_volume (ClutterActor       *actor,
 | 
			
		||||
                                 ClutterPaintVolume *volume)
 | 
			
		||||
{
 | 
			
		||||
  return clutter_paint_volume_set_from_allocation (volume, actor);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static double
 | 
			
		||||
get_scrollbar_width (StScrollView *scroll,
 | 
			
		||||
                     gfloat        for_height)
 | 
			
		||||
@@ -793,6 +800,7 @@ st_scroll_view_class_init (StScrollViewClass *klass)
 | 
			
		||||
 | 
			
		||||
  actor_class->paint = st_scroll_view_paint;
 | 
			
		||||
  actor_class->pick = st_scroll_view_pick;
 | 
			
		||||
  actor_class->get_paint_volume = st_scroll_view_get_paint_volume;
 | 
			
		||||
  actor_class->get_preferred_width = st_scroll_view_get_preferred_width;
 | 
			
		||||
  actor_class->get_preferred_height = st_scroll_view_get_preferred_height;
 | 
			
		||||
  actor_class->allocate = st_scroll_view_allocate;
 | 
			
		||||
 
 | 
			
		||||
@@ -37,6 +37,7 @@ struct _StTextureCachePrivate
 | 
			
		||||
 | 
			
		||||
  /* Things that were loaded with a cache policy != NONE */
 | 
			
		||||
  GHashTable *keyed_cache; /* char * -> CoglTexture* */
 | 
			
		||||
  GHashTable *keyed_surface_cache; /* char * -> cairo_surface_t* */
 | 
			
		||||
 | 
			
		||||
  /* Presently this is used to de-duplicate requests for GIcons and async URIs. */
 | 
			
		||||
  GHashTable *outstanding_requests; /* char * -> AsyncTextureLoadData * */
 | 
			
		||||
@@ -145,6 +146,10 @@ st_texture_cache_init (StTextureCache *self)
 | 
			
		||||
 | 
			
		||||
  self->priv->keyed_cache = g_hash_table_new_full (g_str_hash, g_str_equal,
 | 
			
		||||
                                                   g_free, cogl_object_unref);
 | 
			
		||||
  self->priv->keyed_surface_cache = g_hash_table_new_full (g_str_hash,
 | 
			
		||||
                                                           g_str_equal,
 | 
			
		||||
                                                           g_free,
 | 
			
		||||
                                                           (GDestroyNotify) cairo_surface_destroy);
 | 
			
		||||
  self->priv->outstanding_requests = g_hash_table_new_full (g_str_hash, g_str_equal,
 | 
			
		||||
                                                            g_free, NULL);
 | 
			
		||||
  self->priv->file_monitors = g_hash_table_new_full (g_file_hash, (GEqualFunc) g_file_equal,
 | 
			
		||||
@@ -166,6 +171,7 @@ st_texture_cache_dispose (GObject *object)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_clear_pointer (&self->priv->keyed_cache, g_hash_table_destroy);
 | 
			
		||||
  g_clear_pointer (&self->priv->keyed_surface_cache, g_hash_table_destroy);
 | 
			
		||||
  g_clear_pointer (&self->priv->outstanding_requests, g_hash_table_destroy);
 | 
			
		||||
  g_clear_pointer (&self->priv->file_monitors, g_hash_table_destroy);
 | 
			
		||||
 | 
			
		||||
@@ -520,6 +526,8 @@ finish_texture_load (AsyncTextureLoadData *data,
 | 
			
		||||
    goto out;
 | 
			
		||||
 | 
			
		||||
  texdata = pixbuf_to_cogl_texture (pixbuf);
 | 
			
		||||
  if (!texdata)
 | 
			
		||||
    goto out;
 | 
			
		||||
 | 
			
		||||
  if (data->policy != ST_TEXTURE_CACHE_POLICY_NONE)
 | 
			
		||||
    {
 | 
			
		||||
@@ -772,13 +780,13 @@ st_texture_cache_load (StTextureCache       *cache,
 | 
			
		||||
  if (!texture)
 | 
			
		||||
    {
 | 
			
		||||
      texture = load (cache, key, data, error);
 | 
			
		||||
      if (texture)
 | 
			
		||||
      if (texture && policy == ST_TEXTURE_CACHE_POLICY_FOREVER)
 | 
			
		||||
        g_hash_table_insert (cache->priv->keyed_cache, g_strdup (key), texture);
 | 
			
		||||
      else
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  cogl_object_ref (texture);
 | 
			
		||||
  if (texture && policy == ST_TEXTURE_CACHE_POLICY_FOREVER)
 | 
			
		||||
    cogl_object_ref (texture);
 | 
			
		||||
 | 
			
		||||
  return texture;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -976,7 +984,7 @@ file_changed_cb (GFileMonitor      *monitor,
 | 
			
		||||
  char *key;
 | 
			
		||||
  guint file_hash;
 | 
			
		||||
 | 
			
		||||
  if (event_type != G_FILE_MONITOR_EVENT_CHANGED)
 | 
			
		||||
  if (event_type != G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  file_hash = g_file_hash (file);
 | 
			
		||||
@@ -986,7 +994,7 @@ file_changed_cb (GFileMonitor      *monitor,
 | 
			
		||||
  g_free (key);
 | 
			
		||||
 | 
			
		||||
  key = g_strdup_printf (CACHE_PREFIX_FILE_FOR_CAIRO "%u", file_hash);
 | 
			
		||||
  g_hash_table_remove (cache->priv->keyed_cache, key);
 | 
			
		||||
  g_hash_table_remove (cache->priv->keyed_surface_cache, key);
 | 
			
		||||
  g_free (key);
 | 
			
		||||
 | 
			
		||||
  g_signal_emit (cache, signals[TEXTURE_FILE_CHANGED], 0, file);
 | 
			
		||||
@@ -1273,6 +1281,9 @@ st_texture_cache_load_file_sync_to_cogl_texture (StTextureCache *cache,
 | 
			
		||||
      texdata = pixbuf_to_cogl_texture (pixbuf);
 | 
			
		||||
      g_object_unref (pixbuf);
 | 
			
		||||
 | 
			
		||||
      if (!texdata)
 | 
			
		||||
        goto out;
 | 
			
		||||
 | 
			
		||||
      if (policy == ST_TEXTURE_CACHE_POLICY_FOREVER)
 | 
			
		||||
        {
 | 
			
		||||
          cogl_object_ref (texdata);
 | 
			
		||||
@@ -1304,7 +1315,7 @@ st_texture_cache_load_file_sync_to_cairo_surface (StTextureCache        *cache,
 | 
			
		||||
 | 
			
		||||
  key = g_strdup_printf (CACHE_PREFIX_FILE_FOR_CAIRO "%u", g_file_hash (file));
 | 
			
		||||
 | 
			
		||||
  surface = g_hash_table_lookup (cache->priv->keyed_cache, key);
 | 
			
		||||
  surface = g_hash_table_lookup (cache->priv->keyed_surface_cache, key);
 | 
			
		||||
 | 
			
		||||
  if (surface == NULL)
 | 
			
		||||
    {
 | 
			
		||||
@@ -1318,7 +1329,8 @@ st_texture_cache_load_file_sync_to_cairo_surface (StTextureCache        *cache,
 | 
			
		||||
      if (policy == ST_TEXTURE_CACHE_POLICY_FOREVER)
 | 
			
		||||
        {
 | 
			
		||||
          cairo_surface_reference (surface);
 | 
			
		||||
          g_hash_table_insert (cache->priv->keyed_cache, g_strdup (key), surface);
 | 
			
		||||
          g_hash_table_insert (cache->priv->keyed_surface_cache,
 | 
			
		||||
                               g_strdup (key), surface);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
@@ -1413,3 +1425,11 @@ st_texture_cache_get_default (void)
 | 
			
		||||
    instance = g_object_new (ST_TYPE_TEXTURE_CACHE, NULL);
 | 
			
		||||
  return instance;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
st_texture_cache_rescan_icon_theme (StTextureCache *cache)
 | 
			
		||||
{
 | 
			
		||||
  StTextureCachePrivate *priv = cache->priv;
 | 
			
		||||
 | 
			
		||||
  return gtk_icon_theme_rescan_if_needed (priv->icon_theme);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -106,4 +106,6 @@ CoglTexture * st_texture_cache_load (StTextureCache       *cache,
 | 
			
		||||
                                     void                 *data,
 | 
			
		||||
                                     GError              **error);
 | 
			
		||||
 | 
			
		||||
gboolean st_texture_cache_rescan_icon_theme (StTextureCache *cache);
 | 
			
		||||
 | 
			
		||||
#endif /* __ST_TEXTURE_CACHE_H__ */
 | 
			
		||||
 
 | 
			
		||||
@@ -229,9 +229,9 @@ unpremultiply (ClutterColor *color)
 | 
			
		||||
{
 | 
			
		||||
  if (color->alpha != 0)
 | 
			
		||||
    {
 | 
			
		||||
      color->red = (color->red * 255 + 127) / color->alpha;
 | 
			
		||||
      color->green = (color->green * 255 + 127) / color->alpha;
 | 
			
		||||
      color->blue = (color->blue * 255 + 127) / color->alpha;
 | 
			
		||||
      color->red = MIN((color->red * 255 + 127) / color->alpha, 255);
 | 
			
		||||
      color->green = MIN((color->green * 255 + 127) / color->alpha, 255);
 | 
			
		||||
      color->blue = MIN((color->blue * 255 + 127) / color->alpha, 255);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -402,7 +402,7 @@ st_theme_node_lookup_corner (StThemeNode    *node,
 | 
			
		||||
    return COGL_INVALID_HANDLE;
 | 
			
		||||
 | 
			
		||||
  key = corner_to_string (&corner);
 | 
			
		||||
  texture = st_texture_cache_load (cache, key, ST_TEXTURE_CACHE_POLICY_NONE, load_corner, &corner, NULL);
 | 
			
		||||
  texture = st_texture_cache_load (cache, key, ST_TEXTURE_CACHE_POLICY_FOREVER, load_corner, &corner, NULL);
 | 
			
		||||
 | 
			
		||||
  if (texture)
 | 
			
		||||
    {
 | 
			
		||||
@@ -1414,6 +1414,32 @@ st_theme_node_load_background_image (StThemeNode *node)
 | 
			
		||||
  return node->background_texture != COGL_INVALID_HANDLE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
st_theme_node_invalidate_resources_for_file (StThemeNode *node,
 | 
			
		||||
                                             GFile       *file)
 | 
			
		||||
{
 | 
			
		||||
  StBorderImage *border_image;
 | 
			
		||||
  gboolean changed = FALSE;
 | 
			
		||||
  GFile *theme_file;
 | 
			
		||||
 | 
			
		||||
  theme_file = st_theme_node_get_background_image (node);
 | 
			
		||||
  if ((theme_file != NULL) && g_file_equal (theme_file, file))
 | 
			
		||||
    {
 | 
			
		||||
      st_theme_node_invalidate_background_image (node);
 | 
			
		||||
      changed = TRUE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  border_image = st_theme_node_get_border_image (node);
 | 
			
		||||
  theme_file = border_image ? st_border_image_get_file (border_image) : NULL;
 | 
			
		||||
  if ((theme_file != NULL) && g_file_equal (theme_file, file))
 | 
			
		||||
    {
 | 
			
		||||
      st_theme_node_invalidate_border_image (node);
 | 
			
		||||
      changed = TRUE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return changed;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void st_theme_node_prerender_shadow (StThemeNodePaintState *state);
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -2751,3 +2777,17 @@ st_theme_node_paint_state_invalidate (StThemeNodePaintState *state)
 | 
			
		||||
  state->alloc_width = 0;
 | 
			
		||||
  state->alloc_height = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
st_theme_node_paint_state_invalidate_for_file (StThemeNodePaintState *state,
 | 
			
		||||
                                               GFile                 *file)
 | 
			
		||||
{
 | 
			
		||||
  if (state->node != NULL &&
 | 
			
		||||
      st_theme_node_invalidate_resources_for_file (state->node, file))
 | 
			
		||||
    {
 | 
			
		||||
      st_theme_node_paint_state_invalidate (state);
 | 
			
		||||
      return TRUE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -2545,28 +2545,6 @@ st_theme_node_get_text_align(StThemeNode *node)
 | 
			
		||||
  return ST_TEXT_ALIGN_LEFT;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * st_theme_node_get_letter_spacing:
 | 
			
		||||
 * @node: a #StThemeNode
 | 
			
		||||
 *
 | 
			
		||||
 * Gets the value for the letter-spacing style property, in pixels.
 | 
			
		||||
 *
 | 
			
		||||
 * Return value: the value of the letter-spacing property, if
 | 
			
		||||
 *   found, or zero if such property has not been found.
 | 
			
		||||
 */
 | 
			
		||||
gdouble
 | 
			
		||||
st_theme_node_get_letter_spacing (StThemeNode *node)
 | 
			
		||||
{
 | 
			
		||||
  gdouble spacing = 0.;
 | 
			
		||||
 | 
			
		||||
  g_return_val_if_fail (ST_IS_THEME_NODE (node), spacing);
 | 
			
		||||
 | 
			
		||||
  ensure_properties (node);
 | 
			
		||||
 | 
			
		||||
  st_theme_node_lookup_length (node, "letter-spacing", FALSE, &spacing);
 | 
			
		||||
  return spacing;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
font_family_from_terms (CRTerm *term,
 | 
			
		||||
                        char  **family)
 | 
			
		||||
 
 | 
			
		||||
@@ -223,8 +223,6 @@ StTextDecoration st_theme_node_get_text_decoration (StThemeNode *node);
 | 
			
		||||
 | 
			
		||||
StTextAlign st_theme_node_get_text_align (StThemeNode *node);
 | 
			
		||||
 | 
			
		||||
double st_theme_node_get_letter_spacing (StThemeNode *node);
 | 
			
		||||
 | 
			
		||||
/* Font rule processing is pretty complicated, so we just hardcode it
 | 
			
		||||
 * under the standard font/font-family/font-size/etc names. This means
 | 
			
		||||
 * you can't have multiple separate styled fonts for a single item,
 | 
			
		||||
@@ -289,6 +287,9 @@ void st_theme_node_paint_state_free (StThemeNodePaintState *state);
 | 
			
		||||
void st_theme_node_paint_state_copy (StThemeNodePaintState *state,
 | 
			
		||||
                                     StThemeNodePaintState *other);
 | 
			
		||||
void st_theme_node_paint_state_invalidate (StThemeNodePaintState *state);
 | 
			
		||||
gboolean st_theme_node_paint_state_invalidate_for_file (StThemeNodePaintState *state,
 | 
			
		||||
                                                        GFile                 *file);
 | 
			
		||||
 | 
			
		||||
void st_theme_node_paint_state_set_node (StThemeNodePaintState *state,
 | 
			
		||||
                                         StThemeNode           *node);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -289,44 +289,17 @@ st_widget_texture_cache_changed (StTextureCache *cache,
 | 
			
		||||
{
 | 
			
		||||
  StWidget *actor = ST_WIDGET (user_data);
 | 
			
		||||
  StWidgetPrivate *priv = st_widget_get_instance_private (actor);
 | 
			
		||||
  StThemeNode *node = priv->theme_node;
 | 
			
		||||
  StBorderImage *border_image;
 | 
			
		||||
  gboolean changed = FALSE;
 | 
			
		||||
  GFile *theme_file;
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  if (node == NULL)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  theme_file = st_theme_node_get_background_image (node);
 | 
			
		||||
  if ((theme_file != NULL) && g_file_equal (theme_file, file))
 | 
			
		||||
  for (i = 0; i < G_N_ELEMENTS (priv->paint_states); i++)
 | 
			
		||||
    {
 | 
			
		||||
      st_theme_node_invalidate_background_image (node);
 | 
			
		||||
      changed = TRUE;
 | 
			
		||||
      StThemeNodePaintState *paint_state = &priv->paint_states[i];
 | 
			
		||||
      changed |= st_theme_node_paint_state_invalidate_for_file (paint_state, file);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  border_image = st_theme_node_get_border_image (node);
 | 
			
		||||
  theme_file = border_image ? st_border_image_get_file (border_image) : NULL;
 | 
			
		||||
  if ((theme_file != NULL) && g_file_equal (theme_file, file))
 | 
			
		||||
    {
 | 
			
		||||
      st_theme_node_invalidate_border_image (node);
 | 
			
		||||
      changed = TRUE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (changed)
 | 
			
		||||
    {
 | 
			
		||||
      /* If we prerender the background / border, we need to update
 | 
			
		||||
       * the paint state. We should probably implement a method to
 | 
			
		||||
       * the theme node to determine this, but for now, just wipe
 | 
			
		||||
       * the entire paint state.
 | 
			
		||||
       *
 | 
			
		||||
       * Use the existing state instead of a new one because it's
 | 
			
		||||
       * assumed the rest of the state will stay the same.
 | 
			
		||||
       */
 | 
			
		||||
      st_theme_node_paint_state_invalidate (current_paint_state (actor));
 | 
			
		||||
 | 
			
		||||
      if (clutter_actor_is_mapped (CLUTTER_ACTOR (actor)))
 | 
			
		||||
        clutter_actor_queue_redraw (CLUTTER_ACTOR (actor));
 | 
			
		||||
    }
 | 
			
		||||
  if (changed && clutter_actor_is_mapped (CLUTTER_ACTOR (actor)))
 | 
			
		||||
    clutter_actor_queue_redraw (CLUTTER_ACTOR (actor));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user