Compare commits

..

67 Commits

Author SHA1 Message Date
0221099e7e Bump version to 3.29.4
Update NEWS.
2018-07-18 17:46:36 +02:00
374caade47 inputMethod: Handle IBusInputContext::forward-key-press
The input method may hint that certain keycodes should be pressed/released
besides the textual information in ::commit. An example is hitting space
in some IMs to commit text, where both ::commit happens, and an space is
visibly inserted. In order to handle this properly, we must honor
::forward-key-press.

In order to cater for the case that a keypress is forwarded while handling
that same keypress in a physical keyboard, check the current event being
handled and just forward it as-is if it matches. This is necessary to
prevent state from being doubly set, and the second event silenced away.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/275

Closes: #275
2018-07-17 23:27:24 +00:00
a5937d1d6d Add systemd units
So that we can be started by systemd --user, instead of gnome-session.

There are three units:

  - gnome-shell.service: Start gnome-shell itself.
  - gnome-shell-x11.target, gnome-shell-wayland.target: Sync points for
    units that need to care if x11 or wayland is in use.
    gnome-settings-daemon will use these, for example.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/138
2018-07-17 18:10:06 +00:00
e36ba874a8 Stop using conditional catch statements
It is a mozilla extension that is going away in SpiderMonkey 60.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/151
2018-07-17 17:02:39 +00:00
22392d1328 loginManager: Get the session ID from logind if XDG_SESSION_ID unset
If we're started by systemd, we won't be in the user's display session.
However, this is still the session that will get locked & unlocked. Ask
logind what the 'display' or 'greeter' session is, and watch for the
Unlock signal for that session to know when to unlock.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/137
2018-07-17 17:44:18 +02:00
0dee82fb9f keyboard: Handle no-window case in FocusTracker
For windows, the cursor location needs to be adjusted by the frame
offsets. However we cannot assume that there is a window, as the
shell itself can have the key focus.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/414
2018-07-17 01:44:18 +02:00
68f00f397f Update Russian translation 2018-07-16 21:27:25 +00:00
905801b178 panel: Allow restoring maximized/tiled windows by touch
Maximized and tiled windows can be restored with a drag gesture,
not only from their titlebars, but also from any non-reactive
parts of the top bar above the window. Currently this only works
for actual pointer devices, extend the behavior to handle touch
as well.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/112
2018-07-14 18:38:16 +00:00
4a7082bb0f switcherPopup: Cancel window cycling with Tab
If the Escape key is used for a window/app cycler/switcher shortcut
(such as "Switch windows directly"), then there is no way to cancel
the switching/cycling operation with the keyboard.

This change allows cancelling such an operation by pressing the Tab
key, but only if Tab is not already being used by the current
switcher/cycler shortcut.

Closes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/315
2018-07-14 14:35:05 +00:00
2e90c5fa4b popupMenu: Don't handle key presses directly if there are modifiers
Key events involved in a keyboard shortcut are not completely consumed by
Mutter. That means that if the popupMenu is bound to a shortcut (e.g.
Alt<Space>) and the user keeps the keys pressed, the same key-event will be
delivered to the popupMenu. We can workaround this issue filtering out all the
events where a a modifier is down (except capslock).

Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/372
2018-07-14 14:04:18 +02:00
50e849a186 st-texture-cache: Obey cache policy in st_texture_cache_load
https://bugzilla.gnome.org/show_bug.cgi?id=663461
2018-07-13 20:50:08 +00:00
e7f2e92410 events: Re-use event messages where possible
Destroying and recreating the entire events list on every change is not only
wasteful, it also breaks the clear functionality as messages scheduled for
removal are replaced with "new" messages after the first message has been
removed.

Address both issues by keeping track of all messages and re-use them
whenever possible.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/325
2018-07-13 20:13:30 +00:00
b1b455ff1a st-adjustment: Mark all properties as EXPLICIT_NOTIFY
All adjustment setter functions take good care of avoiding emission of
notify:: when it's not needed. The set_property() implementation already
calls into the setter functions, so mark the properties as EXPLICITY_NOTIFY
in order to optimize notify:: emission away through g_object_set (rather
common from JS code).
2018-07-13 11:53:46 +00:00
ab4c72d758 st-box-layout: Queue relayout on adjustment changes
The actor allocation doesn't change per-se, but apply_transform()
will practically transform it. In order to have the paint volume
update accordingly, queue a relayout.
2018-07-13 11:53:46 +00:00
86a520b880 st: Clip StEntry to allocation
The default get_paint_volume() implementation will do the union
of children, and the child ClutterText paint volume may expand
beyond StEntry size when text overflows.

We actually want all content to be clipped to the StEntry, so
implement get_paint_volume() and tell it so.
2018-07-13 11:53:45 +00:00
4bf033a885 st: Make StScrollables' paint volume reflect the unconstrained view
And constrain it in StScrollView instead (instead of falling back to an
infinite paint volume, as the actor as paint/pick impls, but no
corresponding get_paint_volume one).

Fixes artifacts with the AppView (and possibly other places) when paint
volumes are aggressively cached.
2018-07-13 11:53:45 +00:00
e3ebc8d0c6 keyboard: Remove stale references to global.screen
(Re)introduced by the previous patch.
2018-07-11 18:46:49 +02:00
fc5ab44704 keyboard: Implement standalone FocusTracker
And stop using FocusCaretTracker for caret position purposes. This
new object uses 1) the text-input protocol in wayland and 2) Info
from IBusPanelService for X11 (which is meant to work for XIM too).

This drops the usage of AtspiEventListener for OSK purposes, which
is best to avoid.
2018-07-11 18:32:32 +02:00
d5e8f174d4 Bump version to 3.29.3
Update NEWS.
2018-07-09 19:05:55 +02:00
d9a1434ae9 workspaceThumbnail: Don't keep stale clones in list
If a clone gets destroyed before the corresponding MetaWindow is
removed from the workspace, we will still find it in the list of
clones and try to destroy it again. Avoid the resulting warnings
by updating the list of clones immediately when a clone is destroyed.

https://bugzilla.gnome.org/show_bug.cgi?id=791233
2018-07-09 13:00:35 +02:00
d0bdea3178 workspace: Don't keep stale clones in list
If a clone gets destroyed before the corresponding MetaWindow is
removed from the workspace, we will still find it in the list of
clones and try to destroy it again. Avoid the resulting warnings
by updating the list of clones immediately when a clone is destroyed.

https://bugzilla.gnome.org/show_bug.cgi?id=791233
2018-07-09 13:00:17 +02:00
ccadf6aca1 workspaceThumbnail: remove unused private win reference 2018-07-09 13:00:15 +02:00
266b0e9dd0 keyboard: remove global.screen
This is disabled code for now, but let's have it fixed once we'll use it
2018-07-08 17:43:15 +02:00
f7355f593d closeDialog: use {disable,enable}_unredirect_for_display
Remove leftover global.screen presency
2018-07-08 17:43:15 +02:00
a301820258 Update Catalan translation 2018-07-08 09:23:29 +02:00
47ea10b7c9 Remove usage of MetaScreen
Remove any usage of MetaScreen, as it has been removed from libmutter
in the API version 3. The corresponding functionality has been moved
into three different places: MetaDisplay, MetaX11Display (for X11
specific functionality) and MetaWorkspaceManager.

https://bugzilla.gnome.org/show_bug.cgi?id=759538
2018-07-06 19:56:19 +02:00
2c0376c150 workspaceThumbnail: Initialize signal handler ids to 0
They are used in conditions, so initialize them first.
2018-07-06 19:55:07 +02:00
ac58c4280b Update Occitan translation 2018-07-05 09:51:43 +00:00
e39d7152f2 st-private: Warn if creating shadow for unallocated actors 2018-06-29 11:00:25 +02:00
e522e2e804 st-icon: Create shadow pipeline only at paint
Don't try to allocate the shadow after allocation, just do it at paint
as it's done by other shadowed widgets
2018-06-29 10:43:12 +02:00
2ba26407f1 st-icon: Remove unused size values 2018-06-29 10:43:12 +02:00
996dd74157 layoutManager: Return null monitor if focusIndex is invalid
https://bugzilla.gnome.org/show_bug.cgi?id=788882
2018-06-28 17:05:30 +02:00
878946962d windowManager: Don't animate unmanaged windows on (un)minimization 2018-06-28 17:05:30 +02:00
84d2d3feb3 keyboard: Check monitor validity before deferencing it
Monitor could be invalid in headless mode.

https://bugzilla.gnome.org/show_bug.cgi?id=788882
2018-06-28 17:05:30 +02:00
19e864ed3b keyboard: Handle case where keyboardMonitor is unset
This may be the case where keyboardIndex is -1, which may be the
case where either the keyboard monitor hasn't been set yet, or
the keyboard is being unmanaged and meta_window_get_monitor
returns -1

https://bugzilla.gnome.org/show_bug.cgi?id=788882
2018-06-28 17:05:29 +02:00
c9bf72c5c4 windowMenu: Check if monitorIndex is valid before using it
Calling meta_window_get_monitor on an unmanaged window may return
-1, so we need to check the return value.

https://bugzilla.gnome.org/show_bug.cgi?id=788882
2018-06-28 16:29:07 +02:00
5fe349d5ba thunderbolt: Do not auto start boltd
The service is expected to be activated by systemd when a thunderbolt
device is plugged in, so no need to have it auto-started with the
session.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/54
2018-06-25 14:17:07 +00:00
1f03599d1c st-texture-cache: Save cairo surfaces to a different map
The default keyed_surface is meant to handle CoglTextures thus we can't
add cairo surfaces to it, as the DestroyNotify function won't handle them.

Then the quicker way is to just add another Hash table for handling
such types of textures, with proper destroy function.
2018-06-21 00:56:36 +02:00
a24999b7a3 st-texture-cache: Don't add NULL textures to cache
This might cause a crash when cleaning up the cache as the hash table has
cogl_object_unref as DestroyNotify function but that assumes that
the passed object is a valid CoglObject.

Fixes: #210
2018-06-21 00:48:54 +02:00
8237a1f6e0 Change "const" to "var"
These variables are in fact used from other modules, so gjs complains about them
being const.
2018-06-18 11:19:13 -04:00
f9dec475a1 Update Chinese (Taiwan) translation 2018-06-13 08:38:03 +00:00
68b01a8f56 theme: Use tabular figures where appropriate
In places where numbers appear in columns (like the calendar widget) or
where changing numbers would result in labels jiggling around due to
small width changes (like the clock), use the newly added
font-feature-settings support to request tabular figures.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/34
2018-06-08 13:27:57 -04:00
f56ba0877a st: Add support for font-feature-settings
Cantarell now supports tabular figures, which are useful in places
where digits should either align or not use different widths. In
order to allow elements to request the feature, add support for
the corresponding CSS property[0].

[0] https://www.w3.org/TR/css-fonts-3/#font-rend-desc

https://gitlab.gnome.org/GNOME/gnome-shell/issues/34
2018-06-08 18:45:07 +02:00
5ac6201d91 test-theme: Fix a comment 2018-06-08 17:39:13 +02:00
a21a22fdb5 appDisplay: Make middle-click like Ctrl+click
When middle-clicking an app icon on the Dash, it will always try to open
a new window of that app, even if the app doesn't support multiple
windows. Meanwhile, Ctrl+click on an app will only open a new window if
the app allows it.

This change prevents middle-clicks on app icons from opening new windows
for apps without multi-window support.

Closes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/316
2018-06-07 17:49:36 +00:00
a0fa50ac31 Update Scottish Gaelic translation
(cherry picked from commit 0ac0f7e85b)
2018-06-01 10:36:57 +00:00
b1dd746443 network: Keep key focus in dialog when removing networks
When the actor that has the key focus is destroyed, Clutter moves
the focus to the stage. In case the destroyed actor was inside a
ModalDialog, this breaks any keyboard interaction: keynav is broken
because the stage isn't in any focus chain, and access keys like
Escape because they are handled on the dialog's parent.

The only dialog that may destroy a child without recreating the dialog
buttons (and thus moving the key focus there) is the WirelessDialog,
fix it by keeping the key focus within the dialog when removing networks
from the list.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/76
2018-05-31 11:42:14 +00:00
c15e163eb1 network: Handle networks with no access points
This avoids a couple of warnings when encountering such a network.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/76
2018-05-31 11:42:14 +00:00
7a3927c168 screenshot: Store creation time in metadata
It's useful information, even when we are not using JPEG/Exif - at
least nautilus will show it in its image properties.

https://bugzilla.gnome.org/show_bug.cgi?id=790481
2018-05-31 11:36:27 +00:00
6eed4e31d7 workspace: Fall back to app name in window caption
Just like we did for the window list in app icons' context menu,
provide a fallback for window captions in the window picker rather
than showing blank items to the user.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/26
2018-05-31 11:27:44 +00:00
f0557ea05c appDisplay: Fall back to app name in icon menu
The app icon's context menu contains a list of open windows,
identified by their title. As we currently don't handle the
case where the app didn't set a title, we end up with empty
menu items which looks clearly broken. Fall back to the app's
name in that case.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/26
2018-05-31 11:27:43 +00:00
44894262f4 st-label: Unset clutter text instance on disposal
The instance is owned by the actor (being its child), and thus when the
disposal happens for the parent the text is disposed too, thus it's just
safer to nullify its reference so that we won't try to access to invalid
objects later, and this might be the case since the JS objects could be kept
around until they aren't finalized.

https://bugzilla.gnome.org/show_bug.cgi?id=788931
2018-05-29 02:28:26 +03:00
b03bcc85aa closeDialog: Periodically check for window to become responsive again
The close dialog for non-responding windows is closed automatically
when we detect that the window is responding again. However as we
currently only ping the window in response to certain user actions
(like focusing the window or opening the window menu), this can
easily go undetected.

Address this by periodically pinging the window while the close
dialog is shown.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/298
2018-05-25 18:23:55 +02:00
70057c6a55 closeDialog: Disable unredirection while showing
The dialog won't be visible when unredirection is in place (for example
while a fullscreen window is focused), so disable unredirection while
the dialog is up.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/298
2018-05-25 14:05:29 +00:00
86bd5b281d Bump version to 3.29.2
Update NEWS.
2018-05-24 18:54:29 +02:00
ad3e9ab205 docs: Clarify where style changes should be done
After the move to Gitlab, the gnome-shell-sass repository is more
exposed than it used to; clarify that it is not the place where
style changes should happen, but rather the corresponding subtree
in the gnome-shell repository.
2018-05-23 19:03:01 +02:00
02bbf409ea docs: Use Markdown
Markdown produces nicer output where supported, so use that instead
of plain ASCII formatting.
2018-05-23 19:03:01 +02:00
f56e4e177e docs: Remove old style HACKING
The information is outdated, the relevant documentation is all in
[the README](data/theme/README) nowadays.
2018-05-23 19:01:10 +02:00
fc26559f2c docs: Remove obsolete files
The canonical maintainership information is tracked in the project's
.doap file as for any other GNOME project, and the empty AUTHORS
file only existed to make autotools happy.
2018-05-23 19:01:10 +02:00
fdaddbd1e0 Improve notification documentation
Ref: https://gitlab.gnome.org/GNOME/gnome-shell/issues/294
2018-05-22 18:39:19 +02:00
04f61567ba Update Chinese (China) translation 2018-05-21 14:27:23 +00:00
a0785cdbc1 Update Swedish translation 2018-05-20 17:28:17 +00:00
94101e8bb8 magnifier.js: Fix zoom juddering
Make Zoom respond to the mouse silky-smoothly.

It was previously hard-coded to: 1000/50 = 20 FPS.

https://bugzilla.gnome.org/show_bug.cgi?id=682013
https://launchpad.net/bugs/1691675
2018-05-17 11:42:20 +08:00
f13dbf2f26 Update Galician translation 2018-05-15 22:36:45 +00:00
bae6f06e4e Update Galician translation 2018-05-15 21:58:21 +00:00
d8b9e23502 network: Update the icon in the panel whenever NM's state changes
Similar to what it's done when the main connection changes, we need
to make sure that the icon in the panel gets updated before calling
_syncConnectivity(), so that the icon gets always updated if needed,
regardless of whether there's an active connection or not.

This is needed because there's at least one case when an icon should
be shown when the computer is not connected to any network: when a
hotspot has been enabled, which can be useful even if there's not
an internet connection to share (e.g. to easily allow connecting
other devices to the computer.

Closes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/214
2018-05-15 09:15:43 +01:00
7d59eaa67e Update Indonesian translation 2018-05-12 03:59:42 +00:00
92 changed files with 3307 additions and 2182 deletions

View File

View File

@ -1,19 +1,16 @@
Coding guide
============
# Coding guide
Our goal is to have all JavaScript code in GNOME follow a consistent style. In
a dynamic language like JavaScript, it is essential to be rigorous about style
(and unit tests), or you rapidly end up with a spaghetti-code mess.
A quick note
------------
## A quick note
Life isn't fun if you can't break the rules. If a rule seems unnecessarily
restrictive while you're coding, ignore it, and let the patch reviewer decide
what to do.
Indentation and whitespace
--------------------------
## Indentation and whitespace
Use four-space indents. Braces are on the same line as their associated
statements. You should only omit braces if *both* sides of the statement are
@ -22,7 +19,7 @@ on one line.
* One space after the `function` keyword. No space between the function name
* in a declaration or a call. One space before the parens in the `if`
* statements, or `while`, or `for` loops.
```javascript
function foo(a, b) {
let bar;
@ -39,22 +36,20 @@ on one line.
print(20);
}
}
```
Semicolons
----------
## Semicolons
JavaScript allows omitting semicolons at the end of lines, but don't. Always
end statements with a semicolon.
js2-mode
--------
## js2-mode
If using Emacs, do not use js2-mode. It is outdated and hasn't worked for a
while. emacs now has a built-in JavaScript mode, js-mode, based on
espresso-mode. It is the de facto emacs mode for JavaScript.
File naming and creation
------------------------
## File naming and creation
For JavaScript files, use lowerCamelCase-style names, with a `.js` extension.
@ -67,14 +62,13 @@ library name followed by a dash, e.g. `shell-app-system.c`. Create a
`-private.h` header when you want to share code internally in the
library. These headers are not installed, distributed or introspected.
Imports
-------
## Imports
Use UpperCamelCase when importing modules to distinguish them from ordinary
variables, e.g.
```javascript
const GLib = imports.gi.GLib;
```
Imports should be categorized into one of two places. The top-most import block
should contain only "environment imports". These are either modules from
gobject-introspection or modules added by gjs itself.
@ -85,7 +79,7 @@ e.g. `imports.ui.popupMenu`.
Each import block should be sorted alphabetically. Don't import modules you
don't use.
```javascript
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const Lang = imports.lang;
@ -95,23 +89,22 @@ don't use.
const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
const Util = imports.misc.util;
```
The alphabetical ordering should be done independently of the location of the
location. Never reference `imports` in actual code.
Constants
---------
## Constants
We use CONSTANTS_CASE to define constants. All constants should be directly
under the imports:
```javascript
const MY_DBUS_INTERFACE = 'org.my.Interface';
```
Variable declaration
--------------------
## Variable declaration
Always use either `const` or `let` when defining a variable.
```javascript
// Iterating over an array
for (let i = 0; i < arr.length; ++i) {
let item = arr[i];
@ -121,17 +114,17 @@ Always use either `const` or `let` when defining a variable.
for (let prop in someobj) {
...
}
```
If you use "var" then the variable is added to function scope, not block scope.
See [What's new in JavaScript 1.7](https://developer.mozilla.org/en/JavaScript/New_in_JavaScript/1.7#Block_scope_with_let_%28Merge_into_let_Statement%29)
Classes
-------
## Classes
There are many approaches to classes in JavaScript. We use our own class framework
(sigh), which is built in gjs. The advantage is that it supports inheriting from
GObjects, although this feature isn't used very often in the Shell itself.
```javascript
var IconLabelMenuItem = new Lang.Class({
Name: 'IconLabelMenuItem',
Extends: PopupMenu.PopupMenuBaseItem,
@ -146,6 +139,7 @@ GObjects, although this feature isn't used very often in the Shell itself.
log("menu opened!");
}
});
```
* 'Name' is required. 'Extends' is optional. If you leave it out, you will
automatically inherit from Object.
@ -162,13 +156,12 @@ GObjects, although this feature isn't used very often in the Shell itself.
still a giant function call, even though it may resemble a more
conventional syntax.
GObject Introspection
---------------------
## GObject Introspection
GObject Introspection is a powerful feature that allows us to have native
bindings for almost any library built around GObject. If a library requires
you to inherit from a type to use it, you can do so:
```javascript
var MyClutterActor = new Lang.Class({
Name: 'MyClutterActor',
Extends: Clutter.Actor,
@ -188,9 +181,9 @@ you to inherit from a type to use it, you can do so:
alloc.x2, alloc.y2);
}
});
```
Translatable strings, `environment.js`
--------------------------------------
## Translatable strings, `environment.js`
We use gettext to translate the GNOME Shell into all the languages that GNOME
supports. The `gettext` function is aliased globally as `_`, you do not need to
@ -204,8 +197,7 @@ and "double quotes" for strings that the user may see. This allows us to
quickly find untranslated or mistranslated strings by grepping through the
sources for double quotes without a gettext call around them.
`actor` and `_delegate`
-----------------------
## `actor` and `_delegate`
gjs allows us to set so-called "expando properties" on introspected objects,
allowing us to treat them like any other. Because the Shell was built before
@ -214,7 +206,7 @@ that has a property called `actor`. We call this wrapper class the "delegate".
We sometimes use expando properties to set a property called `_delegate` on
the actor itself:
```javascript
var MyClass = new Lang.Class({
Name: 'MyClass',
@ -229,6 +221,7 @@ the actor itself:
actor.set_label("You clicked the button!");
}
});
```
The 'delegate' property is important for anything which trying to get the
delegate object from an associated actor. For instance, the drag and drop
@ -236,16 +229,14 @@ system calls the `handleDragOver` function on the delegate of a "drop target"
when the user drags an item over it. If you do not set the `_delegate`
property, your actor will not be able to be dropped onto.
Functional style
----------------
## Functional style
JavaScript Array objects offer a lot of common functional programming
capabilities such as forEach, map, filter and so on. You can use these when
they make sense, but please don't have a spaghetti mess of function programming
messed in a procedural style. Use your best judgment.
Closures
--------
## Closures
`this` will not be captured in a closure, it is relative to how the closure is
invoked, not to the value of this where the closure is created, because "this"
@ -254,15 +245,16 @@ variable that can be captured in closures.
All closures should be wrapped with Function.prototype.bind or use arrow
notation.
```javascript
const Lang = imports.lang;
let closure1 = () => { this._fnorbate(); };
let closure2 = this._fnorbate.bind(this);
```
A more realistic example would be connecting to a signal on a method of a
prototype:
```javascript
const Lang = imports.lang;
const FnorbLib = imports.fborbLib;
@ -276,19 +268,21 @@ prototype:
this._updateFnorb();
}
});
```
Object literal syntax
---------------------
## Object literal syntax
In JavaScript, these are equivalent:
```javascript
foo = { 'bar': 42 };
foo = { bar: 42 };
```
and so are these:
```javascript
var b = foo['bar'];
var b = foo.bar;
```
If your usage of an object is like an object, then you're defining "member
variables." For member variables, use the no-quotes no-brackets syntax: `{ bar:
@ -298,14 +292,13 @@ If your usage of an object is like a hash table (and thus conceptually the keys
can have special chars in them), don't use quotes, but use brackets: `{ bar: 42
}`, `foo['bar']`.
Getters, setters, and Tweener
-----------------------------
## Getters, setters, and Tweener
Getters and setters should be used when you are dealing with an API that is
designed around setting properties, like Tweener. If you want to animate an
arbitrary property, create a getter and setter, and use Tweener to animate the
property.
```javascript
var ANIMATION_TIME = 2000;
var MyClass = new Lang.Class({
@ -331,3 +324,4 @@ property.
{ position: 100,
time: ANIMATION_TIME,
transition: 'easeOutQuad' });
```

View File

@ -1,7 +0,0 @@
Owen Taylor
E-mail: otaylor@redhat.com
Userid: otaylor
Colin Walters
E-mail: walters@verbum.org
Userid: walters

50
NEWS
View File

@ -1,3 +1,53 @@
3.29.4
======
* Fix "Clear All" for calendar events [Florian; #325]
* Allow cancelling direct switch operations [Xavier; #315]
* Support being started by systemd --user [Iain; !137, !138]
* Support key event forwarding required by some input methods [Carlos; #275]
* Misc. bug fixes and cleanups [Jasper, Andrea, Florian; #663461, #372, !112,
#414, !151]
Contributors:
Andrea Azzarone, Carlos Garnacho, Xavier Johnson, Iain Lane, Florian Müllner,
Jasper St. Pierre
Translators:
Stas Solovey [ru]
3.29.3
======
* Save creation time in screenshot metadata [Florian; #790481]
* Improve consistency between ctrl- and middle-click on app icons [Xavier; #316]
* Add support for font-feature-settings CSS property [Ryan; #34]
* Adjust to MetaScreen removal [Jonas; #759538]
* Misc. bug fixes [Florian, Marco, Sam; #298, #788931, #26, #76, !54, #788882,
#791233]
Contributors:
Jonas Ådahl, Ryan Hendrickson, Xavier Johnson, Florian Müllner, Joe Rabinoff,
Sam Spilsbury, Marco Trevisan (Treviño)
Translators:
Gun Chleoc [gd], Yi-Jyun Pan [zh_TW], Cédric Valmary [oc], Jordi Mas [ca]
3.29.2
======
* Guard against untimely keyboard map changes [Carlos; #240]
* Fix icons in search provider results [Florian; #249]
* Fix blurriness of OSD under some resolutions [Silvère; #782011]
* Fix lagging pointer when zoomed [Daniel; #682013]
* Misc. bug fixes [Milan, Xiaoguang, Florian, Mario, Ole; #244, #787871,
#781471, #136, #214, #294]
Contributors:
Ole Jørgen Brønner, Milan Crha, Carlos Garnacho, Yussuf Khalil,
Silvère Latchurié, Florian Müllner, Mario Sanchez Prada, Ray Strode,
Daniel van Vugt, Xiaoguang Wang
Translators:
Rafael Fontenelle [pt_BR], Kukuh Syafaat [id], Marcos Lans [gl],
Anders Jonsson [sv], Mingcong Bai [zh_CN]
3.29.1
======
* Support icons in app-menu [Florian; #760985]

View File

@ -1,3 +1,4 @@
# GNOME Shell
GNOME Shell provides core user interface functions for the GNOME 3 desktop,
like switching to windows and launching applications. GNOME Shell takes
advantage of the capabilities of modern graphics hardware and introduces
@ -6,15 +7,14 @@ easy to use experience.
For more information about GNOME Shell, including instructions on how
to build GNOME Shell from source and how to get involved with the project,
see:
see the [project wiki][wiki]
https://wiki.gnome.org/Projects/GnomeShell
Bugs should be reported to the GNOME [bug tracking system][bug-tracker].
Bugs should be reported at http://bugzilla.gnome.org against the 'gnome-shell'
product.
License
=======
## License
GNOME Shell is distributed under the terms of the GNU General Public License,
version 2 or later. See the COPYING file for details.
version 2 or later. See the [COPYING][license] file for details.
[project-wiki]: https://wiki.gnome.org/Projects/GnomeShell
[bug-tracker]: https://gitlab.gnome.org/GNOME/gnome-shell/issues
[license]: COPYING

View File

@ -4,14 +4,14 @@ the extensions repository to provide good integration, letting the website
know which extensions are enabled and disabled, and allowing the website to
enable, disable and install them.
Bugs should be reported at http://bugzilla.gnome.org against the 'gnome-shell'
product.
Bugs should be reported to the GNOME [bug tracking system][bug-tracker].
License
=======
## License
The GNOME Shell Browser Plugin, like GNOME Shell itself is distributed under
the GNU General Public License, version 2 or later. The plugin also contains
header files from the "NPAPI SDK" project, tri-licensed under MPL 1.1, GPL 2.0
and LGPL 2.1. These headers are third-party sources and can be retrieved from:
http://code.google.com/p/npapi-sdk/
[bug-tracker]: https://gitlab.gnome.org/GNOME/gnome-shell/issues

View File

@ -0,0 +1,5 @@
[Unit]
Description=GNOME Shell (wayland sync point)
After=gnome-shell.service
BindsTo=gnome-shell.service
Conflicts=gnome-shell-x11.target

View File

@ -0,0 +1,5 @@
[Unit]
Description=GNOME Shell (x11 sync point)
After=gnome-shell.service
BindsTo=gnome-shell.service
Conflicts=gnome-shell-wayland.target

View File

@ -0,0 +1,11 @@
[Unit]
Description=GNOME Shell
Wants=gnome-session.service
After=graphical-session-pre.target gnome-session-bus.target
PartOf=graphical-session.target
[Service]
Type=dbus
ExecStart=@bindir@/gnome-shell
Restart=on-failure
BusName=org.gnome.Shell

View File

@ -93,6 +93,23 @@ schema = configure_file(
install_dir: schemadir
)
if have_systemd
unitconf = configuration_data()
unitconf.set('bindir', bindir)
unit = configure_file(
input: 'gnome-shell.service.in',
output: 'gnome-shell.service',
configuration: unitconf,
install_dir: systemduserunitdir
)
units = files('gnome-shell-wayland.target',
'gnome-shell-x11.target')
install_data(units, install_dir: systemduserunitdir)
endif
# for unit tests - gnome.compile_schemas() only looks in srcdir
custom_target('compile-schemas',
input: schema,

View File

@ -1,3 +0,0 @@
To generate the css files, from the project directory:
sass --sourcemap=none --update .

View File

@ -1,31 +0,0 @@
Summary
-------
* Do not edit the CSS directly, edit the source SCSS files and the CSS files will be generated
automatically when building with meson + ninja and left inside the build directory to be
incorporated into the gresource XML (you'll need to have sassc installed).
How to tweak the theme
----------------------
Adwaita is a complex theme, so to keep it maintainable it's written and processed in SASS, the
generated CSS is then transformed into a gresource file during gtk build and used at runtime in a
non-legible or editable form.
It is very likely your change will happen in the _common.scss file. That's where all the widget
selectors are defined. Here's a rundown of the "supporting" stylesheets, that are unlikely to be the
right place for a drive by stylesheet fix:
_colors.scss - global color definitions. We keep the number of defined colors to a necessary minimum,
most colors are derived from a handful of basics. It is an exact copy of the gtk+
counterpart. Light theme is used for the classic theme and dark is for GNOME3 shell
default.
_drawing.scss - drawing helper mixings/functions to allow easier definition of widget drawing under
specific context. This is why Adwaita isn't 15000 LOC.
_common.scss - actual definitions of style for each widget. This is where you are likely to add/remove
your changes.
You can read about SASS at http://sass-lang.com/documentation/. Once you make your changes to the
_common.scss file, you can run ninja to generate the final CSS files.

32
data/theme/README.md Normal file
View File

@ -0,0 +1,32 @@
## Summary
Do not edit the CSS directly, edit the source SCSS files and the CSS files
will be generated automatically when building with meson + ninja and left
inside the build directory to be incorporated into the gresource XML (you'll
need to have sassc installed).
## How to tweak the theme
Adwaita is a complex theme, so to keep it maintainable it's written and
processed in SASS, the generated CSS is then transformed into a gresource
file during gtk build and used at runtime in a non-legible or editable form.
It is very likely your change will happen in the [_common.scss][common] file.
That's where all the widget selectors are defined. Here's a rundown of
the "supporting" stylesheets, that are unlikely to be the right place
for a drive by stylesheet fix:
| File | Description |
| ------------------------ | ----------------- |
| [_colors.scss][colors] | global color definitions. We keep the number of defined colors to a necessary minimum, most colors are derived from a handful of basics. It is an exact copy of the gtk+ counterpart. Light theme is used for the classic theme and dark is for GNOME3 shell default. |
| [_drawing.scss][drawing] | drawing helper mixings/functions to allow easier definition of widget drawing under specific context. This is why Adwaita isn't 15000 LOC. |
| [_common.scss][common] | actual definitions of style for each widget. This is where you are likely to add/remove your changes. |
You can read about SASS on its [web page][sass-web]. Once you make your
changes to the [_common.scss][common] file, you can run ninja to generate the
final CSS files.
[common]: data/theme/gnome-shell-sass/_common.scss
[colors]: data/theme/gnome-shell-sass/_colors.scss
[drawing]: data/theme/gnome-shell-sass/_drawing.scss
[sass-web]: http://sass-lang.com/documentation/

View File

@ -1,6 +0,0 @@
--- Generating the css file ---
You need sass to generate the css file.
To generate them run from a command line in the project directory:
sass --sourcemap=none --update ./

View File

@ -1,7 +0,0 @@
GNOME Shell Sass is a project intended to allow the sharing of the theme sources in sass between gnome-shell and other projects like gnome-shell-extensions.
License
=======
GNOME Shell Sass is distributed under the terms of the GNU General Public License,
version 2 or later. See the COPYING file for details.

View File

@ -0,0 +1,16 @@
# GNOME Shell Sass
GNOME Shell Sass is a project intended to allow the sharing of the
theme sources in sass between gnome-shell and other projects like
gnome-shell-extensions.
Any changes should be done in the [GNOME Shell subtree][shell-subtree]
and not the stand-alone [gnome-shell-sass repository][sass-repo]. They
will then be synchronized periodically before releases.
## License
GNOME Shell Sass is distributed under the terms of the GNU General Public
License, version 2 or later. See the [COPYING][license] file for details.
[shell-subtree]: https://gitlab.gnome.org/GNOME/gnome-shell/tree/master/data/theme/gnome-shell-sass
[sass-repo]: https://gitlab.gnome.org/GNOME/gnome-shell-sass
[license]: COPYING

View File

@ -733,6 +733,7 @@ StScrollBar {
transition-duration: 500ms;
font-weight: bold;
height: 1.86em;
font-feature-settings: "tnum";
&.unlock-screen,
&.login-screen,
@ -958,6 +959,7 @@ StScrollBar {
padding: 0.1em;
margin: 2px;
border-radius: 1.4em;
font-feature-settings: "tnum";
&:hover,&:focus { background-color: lighten($bg_color,5%); }
&:active,&:selected {
color: lighten($selected_fg_color,5%);
@ -1867,6 +1869,7 @@ StScrollBar {
.screen-shield-clock-time {
font-size: 72pt;
text-shadow: 0px 2px 2px rgba(0,0,0,0.4);
font-feature-settings: "tnum";
}
.screen-shield-clock-date {

View File

@ -350,16 +350,19 @@ var ShellUserVerifier = new Lang.Class({
try {
this._clearUserVerifier();
this._userVerifier = client.open_reauthentication_channel_finish(result);
} catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
return;
} catch(e if e.matches(Gio.DBusError, Gio.DBusError.ACCESS_DENIED) &&
!this._reauthOnly) {
// Gdm emits org.freedesktop.DBus.Error.AccessDenied when there is
// no session to reauthenticate. Fall back to performing verification
// from this login session
client.get_user_verifier(this._cancellable, this._userVerifierGot.bind(this));
return;
} catch(e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return;
if (e.matches(Gio.DBusError, Gio.DBusError.ACCESS_DENIED) &&
!this._reauthOnly) {
// Gdm emits org.freedesktop.DBus.Error.AccessDenied when there
// is no session to reauthenticate. Fall back to performing
// verification from this login session
client.get_user_verifier(this._cancellable,
this._userVerifierGot.bind(this));
return;
}
this._reportInitError('Failed to open reauthentication channel', e);
return;
}
@ -374,9 +377,9 @@ var ShellUserVerifier = new Lang.Class({
try {
this._clearUserVerifier();
this._userVerifier = client.get_user_verifier_finish(result);
} catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
return;
} catch(e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return;
this._reportInitError('Failed to obtain user verifier', e);
return;
}
@ -434,9 +437,9 @@ var ShellUserVerifier = new Lang.Class({
(obj, result) => {
try {
obj.call_begin_verification_for_user_finish(result);
} catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
return;
} catch(e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return;
this._reportInitError('Failed to start verification for user', e);
return;
}
@ -449,9 +452,9 @@ var ShellUserVerifier = new Lang.Class({
(obj, result) => {
try {
obj.call_begin_verification_finish(result);
} catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
return;
} catch(e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return;
this._reportInitError('Failed to start verification', e);
return;
}

View File

@ -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

View File

@ -15,6 +15,8 @@ var InputMethod = new Lang.Class({
this._purpose = 0;
this._enabled = true;
this._currentFocus = null;
this._currentEvent = null;
this._doForwardEvent = false;
this._ibus = IBus.Bus.new_async();
this._ibus.connect('connected', this._onConnected.bind(this));
this._ibus.connect('disconnected', this._clear.bind(this));
@ -25,6 +27,9 @@ var InputMethod = new Lang.Class({
this._onSourceChanged.bind(this));
this._currentSource = this._inputSourceManager.currentSource;
let deviceManager = Clutter.DeviceManager.get_default();
this._virtualDevice = deviceManager.create_virtual_device(Clutter.InputDeviceType.KEYBOARD_DEVICE);
if (this._ibus.is_connected())
this._onConnected();
},
@ -64,6 +69,7 @@ var InputMethod = new Lang.Class({
this._context.connect('commit-text', this._onCommitText.bind(this));
this._context.connect('delete-surrounding-text', this._onDeleteSurroundingText.bind(this));
this._context.connect('update-preedit-text', this._onUpdatePreeditText.bind(this));
this._context.connect('forward-key-event', this._onForwardKeyEvent.bind(this));
this._updateCapabilities();
},
@ -96,6 +102,24 @@ var InputMethod = new Lang.Class({
this.set_preedit_text(str, pos);
},
_onForwardKeyEvent(context, keyval, keycode, state) {
let press = (state & IBus.ModifierType.RELEASE_MASK) == 0;
if (this._currentEvent) {
// If we are handling this same event in filter_key_press(),
// just let it go through, sending the same event again will
// be silenced away because the key counts as pressed.
if (this._currentEvent.get_key_symbol() == keyval &&
(this._currentEvent.type() == Clutter.EventType.KEY_PRESS) == press) {
this._doForwardEvent = true;
return;
}
}
this._virtualDevice.notify_key(Clutter.get_current_event_time(), keycode,
press ? Clutter.KeyState.PRESSED : Clutter.KeyState.RELEASED);
},
vfunc_focus_in(focus) {
this._currentFocus = focus;
if (this._context) {
@ -197,13 +221,23 @@ var InputMethod = new Lang.Class({
if (event.type() == Clutter.EventType.KEY_RELEASE)
state |= IBus.ModifierType.RELEASE_MASK;
this._currentEvent = event;
this._doForwardEvent = false;
this._context.process_key_event_async(event.get_key_symbol(),
event.get_key_code() - 8, // Convert XKB keycodes to evcodes
state, -1, null,
(context, res) => {
try {
let retval = context.process_key_event_async_finish(res);
if (this._doForwardEvent)
retval = false;
this.notify_key_event(event, retval);
this._doForwardEvent = false;
this._currentEvent = null;
} catch (e) {
log('Error processing key on IM: ' + e.message);
}

View File

@ -40,14 +40,24 @@ const SystemdLoginSessionIface = '<node> \
<signal name="Lock" /> \
<signal name="Unlock" /> \
<property name="Active" type="b" access="read" /> \
<property name="Class" type="s" access="read" /> \
<property name="Id" type="s" access="read" /> \
<method name="SetLockedHint"> \
<arg type="b" direction="in"/> \
</method> \
</interface> \
</node>';
const SystemdLoginUserIface = '<node> \
<interface name="org.freedesktop.login1.User"> \
<property name="Display" type="(so)" access="read" /> \
<property name="Sessions" type="a(so)" access="read" /> \
</interface> \
</node>';
const SystemdLoginManager = Gio.DBusProxy.makeProxyWrapper(SystemdLoginManagerIface);
const SystemdLoginSession = Gio.DBusProxy.makeProxyWrapper(SystemdLoginSessionIface);
const SystemdLoginUser = Gio.DBusProxy.makeProxyWrapper(SystemdLoginUserIface);
function haveSystemd() {
return GLib.access("/run/systemd/seats", 0) >= 0;
@ -109,6 +119,9 @@ var LoginManagerSystemd = new Lang.Class({
this._proxy = new SystemdLoginManager(Gio.DBus.system,
'org.freedesktop.login1',
'/org/freedesktop/login1');
this._userProxy = new SystemdLoginUser(Gio.DBus.system,
'org.freedesktop.login1',
'/org/freedesktop/login1/user/self');
this._proxy.connectSignal('PrepareForSleep',
this._prepareForSleep.bind(this));
},
@ -121,8 +134,31 @@ var LoginManagerSystemd = new Lang.Class({
let sessionId = GLib.getenv('XDG_SESSION_ID');
if (!sessionId) {
log('Unset XDG_SESSION_ID, getCurrentSessionProxy() called outside a user session.');
return;
log('Unset XDG_SESSION_ID, getCurrentSessionProxy() called outside a user session. Asking logind directly.');
let [session, objectPath] = this._userProxy.Display;
if (session) {
log(`Will monitor session ${session}`);
sessionId = session;
} else {
log('Failed to find "Display" session; are we the greeter?');
for (let [session, objectPath] of this._userProxy.Sessions) {
let sessionProxy = new SystemdLoginSession(Gio.DBus.system,
'org.freedesktop.login1',
objectPath);
log(`Considering ${session}, class=${sessionProxy.Class}`);
if (sessionProxy.Class == 'greeter') {
log(`Yes, will monitor session ${session}`);
sessionId = session;
break;
}
}
if (!sessionId) {
log('No, failed to get session from logind.');
return;
}
}
}
this._proxy.GetSessionRemote(sessionId, (result, error) => {

View File

@ -502,7 +502,8 @@ var CyclerPopup = new Lang.Class({
_finish() {
let window = this._items[this._selectedIndex];
let ws = window.get_workspace();
let activeWs = global.screen.get_active_workspace();
let workspaceManager = global.workspace_manager;
let activeWs = workspaceManager.get_active_workspace();
if (window.minimized) {
Main.wm.skipNextEffect(window.get_compositor_private());
@ -572,7 +573,14 @@ var WindowSwitcherPopup = new Lang.Class({
},
_getWindowList() {
let workspace = this._settings.get_boolean('current-workspace-only') ? global.screen.get_active_workspace() : null;
let workspace = null;
if (this._settings.get_boolean('current-workspace-only')) {
let workspaceManager = global.workspace_manager;
workspace = workspaceManager.get_active_workspace();
}
return getWindows(workspace);
},
@ -620,7 +628,14 @@ var WindowCyclerPopup = new Lang.Class({
},
_getWindows() {
let workspace = this._settings.get_boolean('current-workspace-only') ? global.screen.get_active_workspace() : null;
let workspace = null;
if (this._settings.get_boolean('current-workspace-only')) {
let workspaceManager = global.workspace_manager;
workspace = workspaceManager.get_active_workspace();
}
return getWindows(workspace);
},
@ -669,8 +684,14 @@ var AppSwitcher = new Lang.Class({
let windowTracker = Shell.WindowTracker.get_default();
let settings = new Gio.Settings({ schema_id: 'org.gnome.shell.app-switcher' });
let workspace = settings.get_boolean('current-workspace-only') ? global.screen.get_active_workspace()
: null;
let workspace = null;
if (settings.get_boolean('current-workspace-only')) {
let workspaceManager = global.workspace_manager;
workspace = workspaceManager.get_active_workspace();
}
let allWindows = global.display.get_tab_list(Meta.TabList.NORMAL, workspace);
// Construct the AppIcons, add to the popup

View File

@ -1778,10 +1778,11 @@ var AppIcon = new Lang.Class({
activate(button) {
let event = Clutter.get_current_event();
let modifiers = event ? event.get_state() : 0;
let openNewWindow = this.app.can_open_new_window () &&
modifiers & Clutter.ModifierType.CONTROL_MASK &&
this.app.state == Shell.AppState.RUNNING ||
button && button == 2;
let isMiddleButton = button && button == Clutter.BUTTON_MIDDLE;
let isCtrlPressed = (modifiers & Clutter.ModifierType.CONTROL_MASK) != 0;
let openNewWindow = this.app.can_open_new_window() &&
this.app.state == Shell.AppState.RUNNING &&
(isCtrlPressed || isMiddleButton);
if (this.app.state == Shell.AppState.STOPPED || openNewWindow)
this.animateLaunch();
@ -1861,7 +1862,8 @@ var AppIconMenu = new Lang.Class({
// Display the app windows menu items and the separator between windows
// of the current desktop and other windows.
let activeWorkspace = global.screen.get_active_workspace();
let workspaceManager = global.workspace_manager;
let activeWorkspace = workspaceManager.get_active_workspace();
let separatorShown = windows.length > 0 && windows[0].get_workspace() != activeWorkspace;
for (let i = 0; i < windows.length; i++) {
@ -1870,7 +1872,9 @@ var AppIconMenu = new Lang.Class({
this._appendSeparator();
separatorShown = true;
}
let item = this._appendMenuItem(window.title);
let title = window.title ? window.title
: this._source.app.get_name();
let item = this._appendMenuItem(title);
item.connect('activate', () => {
this.emit('activate-window', window);
});

View File

@ -240,7 +240,7 @@ var Background = new Lang.Class({
file: null,
style: null });
this.background = new Meta.Background({ meta_screen: global.screen });
this.background = new Meta.Background({ meta_display: global.display });
this.background._delegate = this;
this._settings = params.settings;
@ -499,12 +499,12 @@ var SystemBackground = new Lang.Class({
let file = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/noise-texture.png');
if (_systemBackground == null) {
_systemBackground = new Meta.Background({ meta_screen: global.screen });
_systemBackground = new Meta.Background({ meta_display: global.display });
_systemBackground.set_color(DEFAULT_BACKGROUND_COLOR);
_systemBackground.set_file(file, GDesktopEnums.BackgroundStyle.WALLPAPER);
}
this.actor = new Meta.BackgroundActor({ meta_screen: global.screen,
this.actor = new Meta.BackgroundActor({ meta_display: global.display,
monitor: 0,
background: _systemBackground });
@ -538,8 +538,10 @@ var BackgroundSource = new Lang.Class({
this._settings = new Gio.Settings({ schema_id: settingsSchema });
this._backgrounds = [];
this._monitorsChangedId = global.screen.connect('monitors-changed',
this._onMonitorsChanged.bind(this));
let monitorManager = Meta.MonitorManager.get();
this._monitorsChangedId =
monitorManager.connect('monitors-changed',
this._onMonitorsChanged.bind(this));
},
_onMonitorsChanged() {
@ -604,7 +606,8 @@ var BackgroundSource = new Lang.Class({
},
destroy() {
global.screen.disconnect(this._monitorsChangedId);
let monitorManager = Meta.MonitorManager.get();
monitorManager.disconnect(this._monitorsChangedId);
for (let monitorIndex in this._backgrounds) {
let background = this._backgrounds[monitorIndex];
@ -751,7 +754,7 @@ var BackgroundManager = new Lang.Class({
_createBackgroundActor() {
let background = this._backgroundSource.getBackground(this._monitorIndex);
let backgroundActor = new Meta.BackgroundActor({ meta_screen: global.screen,
let backgroundActor = new Meta.BackgroundActor({ meta_display: global.display,
monitor: this._monitorIndex,
background: background.background,
vignette: this._vignette,

View File

@ -821,6 +821,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 +877,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;

View File

@ -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,7 @@ var CloseDialog = new Lang.Class({
this.parent();
this._window = window;
this._dialog = null;
this._timeoutId = 0;
},
get window() {
@ -97,6 +100,14 @@ var CloseDialog = new Lang.Class({
if (this._dialog != null)
return;
Meta.disable_unredirect_for_display(global.display);
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._addWindowEffect();
this._initDialog();
@ -117,6 +128,11 @@ var CloseDialog = new Lang.Class({
if (this._dialog == null)
return;
Meta.enable_unredirect_for_display(global.display);
GLib.source_remove(this._timeoutId);
this._timeoutId = 0;
let dialog = this._dialog;
this._dialog = null;
this._removeWindowEffect();

View File

@ -85,9 +85,11 @@ var CtrlAltTabManager = new Lang.Class({
// And add the windows metacity would show in its Ctrl-Alt-Tab list
if (Main.sessionMode.hasWindows && !Main.overview.visible) {
let screen = global.screen;
let display = screen.get_display();
let windows = display.get_tab_list(Meta.TabList.DOCKS, screen.get_active_workspace ());
let display = global.display;
let workspaceManager = global.workspace_manager;
let activeWorkspace = workspaceManager.get_active_workspace();
let windows = display.get_tab_list(Meta.TabList.DOCKS,
activeWorkspace);
let windowTracker = Shell.WindowTracker.get_default();
let textureCache = St.TextureCache.get_default();
for (let i = 0; i < windows.length; i++) {
@ -131,7 +133,7 @@ var CtrlAltTabManager = new Lang.Class({
},
_focusWindows(timestamp) {
global.screen.focus_default_window(timestamp);
global.display.focus_default_window(timestamp);
}
});

View File

@ -280,7 +280,7 @@ var _Draggable = new Lang.Class({
this._touchSequence = sequence;
this._grabEvents();
global.screen.set_cursor(Meta.Cursor.DND_IN_DRAG);
global.display.set_cursor(Meta.Cursor.DND_IN_DRAG);
this._dragX = this._dragStartX = stageX;
this._dragY = this._dragStartY = stageY;
@ -412,7 +412,7 @@ var _Draggable = new Lang.Class({
if (motionFunc) {
let result = motionFunc(dragEvent);
if (result != DragMotionResult.CONTINUE) {
global.screen.set_cursor(DRAG_CURSOR_MAP[result]);
global.display.set_cursor(DRAG_CURSOR_MAP[result]);
return GLib.SOURCE_REMOVE;
}
}
@ -430,13 +430,13 @@ var _Draggable = new Lang.Class({
targY,
0);
if (result != DragMotionResult.CONTINUE) {
global.screen.set_cursor(DRAG_CURSOR_MAP[result]);
global.display.set_cursor(DRAG_CURSOR_MAP[result]);
return GLib.SOURCE_REMOVE;
}
}
target = target.get_parent();
}
global.screen.set_cursor(Meta.Cursor.DND_IN_DRAG);
global.display.set_cursor(Meta.Cursor.DND_IN_DRAG);
return GLib.SOURCE_REMOVE;
},
@ -509,7 +509,7 @@ var _Draggable = new Lang.Class({
}
this._dragInProgress = false;
global.screen.set_cursor(Meta.Cursor.DEFAULT);
global.display.set_cursor(Meta.Cursor.DEFAULT);
this.emit('drag-end', event.get_time(), true);
this._dragComplete();
return true;
@ -561,7 +561,7 @@ var _Draggable = new Lang.Class({
let [snapBackX, snapBackY, snapBackScale] = this._getRestoreLocation();
if (this._actorDestroyed) {
global.screen.set_cursor(Meta.Cursor.DEFAULT);
global.display.set_cursor(Meta.Cursor.DEFAULT);
if (!this._buttonDown)
this._dragComplete();
this.emit('drag-end', eventTime, false);
@ -620,7 +620,7 @@ var _Draggable = new Lang.Class({
if (!this._buttonDown)
this._dragComplete();
global.screen.set_cursor(Meta.Cursor.DEFAULT);
global.display.set_cursor(Meta.Cursor.DEFAULT);
},
_onAnimationComplete(dragActor, eventTime) {

View File

@ -27,9 +27,9 @@ var EdgeDragAction = new Lang.Class({
_getMonitorRect(x, y) {
let rect = new Meta.Rectangle({ x: x - 1, y: y - 1, width: 1, height: 1 });
let monitorIndex = global.screen.get_monitor_index_for_rect(rect);
let monitorIndex = global.display.get_monitor_index_for_rect(rect);
return global.screen.get_monitor_geometry(monitorIndex);
return global.display.get_monitor_geometry(monitorIndex);
},
vfunc_gesture_prepare(action, actor) {

View File

@ -697,7 +697,14 @@ var EndSessionDialog = new Lang.Class({
if (proxy.State == 'closing')
continue;
if (proxy.Id == GLib.getenv('XDG_SESSION_ID'))
let sessionId = GLib.getenv('XDG_SESSION_ID');
if (!sessionId)
this._loginManager.getCurrentSessionProxy(currentSessionProxy => {
sessionId = currentSessionProxy.Id;
log(`endSessionDialog: No XDG_SESSION_ID, fetched from logind: ${sessionId}`);
});
if (proxy.Id == sessionId)
continue;
let session = { user: this._userManager.get_user(userName),

View File

@ -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.display.connect('notify::focus-window', () => {
this._setCurrentWindow(global.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;
},
});

View File

@ -109,7 +109,7 @@ var MonitorConstraint = new Lang.Class({
if (!this._workareasChangedId) {
this._workareasChangedId =
global.screen.connect('workareas-changed', () => {
global.display.connect('workareas-changed', () => {
if (this._workArea)
this.actor.queue_relayout();
});
@ -120,7 +120,7 @@ var MonitorConstraint = new Lang.Class({
this._monitorsChangedId = 0;
if (this._workareasChangedId)
global.screen.disconnect(this._workareasChangedId);
global.display.disconnect(this._workareasChangedId);
this._workareasChangedId = 0;
}
@ -142,7 +142,8 @@ var MonitorConstraint = new Lang.Class({
let rect;
if (this._workArea) {
let ws = global.screen.get_workspace_by_index(0);
let workspaceManager = global.workspace_manager;
let ws = workspaceManager.get_workspace_by_index(0);
rect = ws.get_work_area_for_monitor(index);
} else {
rect = Main.layoutManager.monitors[index];
@ -164,7 +165,7 @@ var Monitor = new Lang.Class({
},
get inFullscreen() {
return global.screen.get_monitor_in_fullscreen(this.index);
return global.display.get_monitor_in_fullscreen(this.index);
}
})
@ -259,7 +260,7 @@ var LayoutManager = new Lang.Class({
global.stage.remove_actor(global.top_window_group);
this.uiGroup.add_actor(global.top_window_group);
let feedbackGroup = Meta.get_feedback_group_for_screen(global.screen);
let feedbackGroup = Meta.get_feedback_group_for_display(global.display);
global.stage.remove_actor(feedbackGroup);
this.uiGroup.add_actor(feedbackGroup);
@ -269,14 +270,19 @@ var LayoutManager = new Lang.Class({
this._bgManagers = [];
// Need to update struts on new workspaces when they are added
global.screen.connect('notify::n-workspaces',
this._queueUpdateRegions.bind(this));
global.screen.connect('restacked',
this._windowsRestacked.bind(this));
global.screen.connect('monitors-changed',
this._monitorsChanged.bind(this));
global.screen.connect('in-fullscreen-changed',
this._updateFullscreen.bind(this));
let workspaceManager = global.workspace_manager;
workspaceManager.connect('notify::n-workspaces',
this._queueUpdateRegions.bind(this));
let display = global.display;
display.connect('restacked',
this._windowsRestacked.bind(this));
display.connect('in-fullscreen-changed',
this._updateFullscreen.bind(this));
let monitorManager = Meta.MonitorManager.get();
monitorManager.connect('monitors-changed',
this._monitorsChanged.bind(this));
this._monitorsChanged();
// NVIDIA drivers don't preserve FBO contents across
@ -319,12 +325,12 @@ var LayoutManager = new Lang.Class({
},
_updateMonitors() {
let screen = global.screen;
let display = global.display;
this.monitors = [];
let nMonitors = screen.get_n_monitors();
let nMonitors = display.get_n_monitors();
for (let i = 0; i < nMonitors; i++)
this.monitors.push(new Monitor(i, screen.get_monitor_geometry(i)));
this.monitors.push(new Monitor(i, display.get_monitor_geometry(i)));
if (nMonitors == 0) {
this.primaryIndex = this.bottomIndex = -1;
@ -333,7 +339,7 @@ var LayoutManager = new Lang.Class({
} else {
// If there are monitors below the primary, then we need
// to split primary from bottom.
this.primaryIndex = this.bottomIndex = screen.get_primary_monitor();
this.primaryIndex = this.bottomIndex = display.get_primary_monitor();
for (let i = 0; i < this.monitors.length; i++) {
let monitor = this.monitors[i];
if (this._isAboveOrBelowPrimary(monitor)) {
@ -538,7 +544,7 @@ var LayoutManager = new Lang.Class({
},
get currentMonitor() {
let index = global.screen.get_current_monitor();
let index = global.display.get_current_monitor();
return this.monitors[index];
},
@ -557,6 +563,8 @@ var LayoutManager = new Lang.Class({
},
get focusMonitor() {
if (this.focusIndex < 0)
return null;
return this.monitors[this.focusIndex];
},
@ -909,7 +917,8 @@ var LayoutManager = new Lang.Class({
getWorkAreaForMonitor(monitorIndex) {
// Assume that all workspaces will have the same
// struts and pick the first one.
let ws = global.screen.get_workspace_by_index(0);
let workspaceManager = global.workspace_manager;
let ws = workspaceManager.get_workspace_by_index(0);
return ws.get_work_area_for_monitor(monitorIndex);
},
@ -919,7 +928,7 @@ var LayoutManager = new Lang.Class({
let [x, y] = actor.get_transformed_position();
let [w, h] = actor.get_transformed_size();
let rect = new Meta.Rectangle({ x: x, y: y, width: w, height: h });
return global.screen.get_monitor_index_for_rect(rect);
return global.display.get_monitor_index_for_rect(rect);
},
findMonitorForActor(actor) {
@ -1052,9 +1061,9 @@ var LayoutManager = new Lang.Class({
global.set_stage_input_region(rects);
this._isPopupWindowVisible = isPopupMenuVisible;
let screen = global.screen;
for (let w = 0; w < screen.n_workspaces; w++) {
let workspace = screen.get_workspace_by_index(w);
let workspaceManager = global.workspace_manager;
for (let w = 0; w < workspaceManager.n_workspaces; w++) {
let workspace = workspaceManager.get_workspace_by_index(w);
workspace.set_builtin_struts(struts);
}

View File

@ -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;
@ -62,7 +61,7 @@ var Magnifier = new Lang.Class({
this._zoomRegions = [];
// Create small clutter tree for the magnified mouse.
let cursorTracker = Meta.CursorTracker.get_for_screen(global.screen);
let cursorTracker = Meta.CursorTracker.get_for_display(global.display);
this._mouseSprite = new Clutter.Texture();
Shell.util_cursor_tracker_to_clutter(cursorTracker, this._mouseSprite);
this._cursorRoot = new Clutter.Actor();
@ -117,10 +116,10 @@ var Magnifier = new Lang.Class({
if (isActive != activate) {
if (activate) {
Meta.disable_unredirect_for_screen(global.screen);
Meta.disable_unredirect_for_display(global.display);
this.startTrackingMouse();
} else {
Meta.enable_unredirect_for_screen(global.screen);
Meta.enable_unredirect_for_display(global.display);
this.stopTrackingMouse();
}
}
@ -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));
}
},
/**

View File

@ -429,7 +429,7 @@ function pushModal(actor, params) {
log('pushModal: invocation of begin_modal failed');
return false;
}
Meta.disable_unredirect_for_screen(global.screen);
Meta.disable_unredirect_for_display(global.display);
}
modalCount += 1;
@ -528,7 +528,7 @@ function popModal(actor, timestamp) {
layoutManager.modalEnded();
global.end_modal(timestamp);
Meta.enable_unredirect_for_screen(global.screen);
Meta.enable_unredirect_for_display(global.display);
actionMode = Shell.ActionMode.NORMAL;
}
@ -556,14 +556,15 @@ function openRunDialog() {
* and switching out of the overview if it's currently active
*/
function activateWindow(window, time, workspaceNum) {
let activeWorkspaceNum = global.screen.get_active_workspace_index();
let workspaceManager = global.workspace_manager;
let activeWorkspaceNum = workspaceManager.get_active_workspace_index();
let windowWorkspaceNum = (workspaceNum !== undefined) ? workspaceNum : window.get_workspace().index();
if (!time)
time = global.get_current_time();
if (windowWorkspaceNum != activeWorkspaceNum) {
let workspace = global.screen.get_workspace_by_index(windowWorkspaceNum);
let workspace = workspaceManager.get_workspace_by_index(windowWorkspaceNum);
workspace.activate_with_focus(window, time);
} else {
window.activate(time);

View File

@ -27,6 +27,7 @@ function _fixMarkup(text, allowMarkup) {
// Support <b>, <i>, and <u>, escape anything else
// so it displays as raw markup.
// Ref: https://developer.gnome.org/notification-spec/#markup
_text = _text.replace(/<(?!\/?[biu]>)/g, '&lt;');
try {
@ -95,10 +96,10 @@ var URLHighlighter = new Lang.Class({
let urlId = this._findUrlAtPos(event);
if (urlId != -1 && !this._cursorChanged) {
global.screen.set_cursor(Meta.Cursor.POINTING_HAND);
global.display.set_cursor(Meta.Cursor.POINTING_HAND);
this._cursorChanged = true;
} else if (urlId == -1) {
global.screen.set_cursor(Meta.Cursor.DEFAULT);
global.display.set_cursor(Meta.Cursor.DEFAULT);
this._cursorChanged = false;
}
return Clutter.EVENT_PROPAGATE;
@ -109,7 +110,7 @@ var URLHighlighter = new Lang.Class({
if (this._cursorChanged) {
this._cursorChanged = false;
global.screen.set_cursor(Meta.Cursor.DEFAULT);
global.display.set_cursor(Meta.Cursor.DEFAULT);
}
return Clutter.EVENT_PROPAGATE;
});

View File

@ -315,10 +315,10 @@ var NotificationApplicationPolicy = new Lang.Class({
// You can add a secondary icon to the banner with 'secondaryGIcon'. There
// is no fallback for this icon.
//
// If @params contains 'bannerMarkup', with the value %true, then
// the corresponding element is assumed to use pango markup. If the
// parameter is not present for an element, then anything that looks
// like markup in that element will appear literally in the output.
// If @params contains 'bannerMarkup', with the value %true, a subset (<b>,
// <i> and <u>) of the markup in [1] will be interpreted within @banner. If
// the parameter is not present, then anything that looks like markup
// in @banner will appear literally in the output.
//
// If @params contains a 'clear' parameter with the value %true, then
// the content and the action area of the notification will be cleared.
@ -328,6 +328,8 @@ var NotificationApplicationPolicy = new Lang.Class({
// If @params contains 'soundName' or 'soundFile', the corresponding
// event sound is played when the notification is shown (if the policy for
// @source allows playing sounds).
//
// [1] https://developer.gnome.org/notification-spec/#markup
var Notification = new Lang.Class({
Name: 'Notification',
@ -915,7 +917,7 @@ var MessageTray = new Lang.Class({
Main.layoutManager.addChrome(this.actor, { affectsInputRegion: false });
Main.layoutManager.trackChrome(this._bannerBin, { affectsInputRegion: true });
global.screen.connect('in-fullscreen-changed', this._updateState.bind(this));
global.display.connect('in-fullscreen-changed', this._updateState.bind(this));
Main.sessionMode.connect('updated', this._sessionUpdated.bind(this));

View File

@ -116,7 +116,7 @@ var ModalDialog = new Lang.Class({
if (onPrimary)
this._monitorConstraint.primary = true;
else
this._monitorConstraint.index = global.screen.get_current_monitor();
this._monitorConstraint.index = global.display.get_current_monitor();
this.state = State.OPENING;

View File

@ -831,8 +831,10 @@ var GtkNotificationDaemon = new Lang.Class({
let source;
try {
source = this._ensureAppSource(appId);
} catch(e if e instanceof InvalidAppError) {
return;
} catch(e) {
if (e instanceof InvalidAppError)
return;
throw e;
}
notifications.forEach(([notificationId, notification]) => {
@ -863,9 +865,12 @@ var GtkNotificationDaemon = new Lang.Class({
let source;
try {
source = this._ensureAppSource(appId);
} catch(e if e instanceof InvalidAppError) {
invocation.return_dbus_error('org.gtk.Notifications.InvalidApp', 'The app by ID "%s" could not be found'.format(appId));
return;
} catch(e) {
if (e instanceof InvalidAppError) {
invocation.return_dbus_error('org.gtk.Notifications.InvalidApp', 'The app by ID "%s" could not be found'.format(appId));
return;
}
throw e;
}
let timestamp = GLib.DateTime.new_now_local().to_unix();

View File

@ -32,7 +32,7 @@ var OsdMonitorLabel = new Lang.Class({
Main.uiGroup.set_child_above_sibling(this._actor, null);
this._position();
Meta.disable_unredirect_for_screen(global.screen);
Meta.disable_unredirect_for_display(global.display);
},
_position() {
@ -48,7 +48,7 @@ var OsdMonitorLabel = new Lang.Class({
destroy() {
this._actor.destroy();
Meta.enable_unredirect_for_screen(global.screen);
Meta.enable_unredirect_for_display(global.display);
}
});

View File

@ -145,7 +145,7 @@ var OsdWindow = new Lang.Class({
return;
if (!this.actor.visible) {
Meta.disable_unredirect_for_screen(global.screen);
Meta.disable_unredirect_for_display(global.display);
this.actor.show();
this.actor.opacity = 0;
this.actor.get_parent().set_child_above_sibling(this.actor, null);
@ -179,7 +179,7 @@ var OsdWindow = new Lang.Class({
transition: 'easeOutQuad',
onComplete: () => {
this._reset();
Meta.enable_unredirect_for_screen(global.screen);
Meta.enable_unredirect_for_display(global.display);
}
});
return GLib.SOURCE_REMOVE;

View File

@ -157,7 +157,7 @@ var Overview = new Lang.Class({
Main.xdndHandler.connect('drag-begin', this._onDragBegin.bind(this));
Main.xdndHandler.connect('drag-end', this._onDragEnd.bind(this));
global.screen.connect('restacked', this._onRestacked.bind(this));
global.display.connect('restacked', this._onRestacked.bind(this));
this._windowSwitchTimeoutId = 0;
this._windowSwitchTimestamp = 0;
@ -286,7 +286,8 @@ var Overview = new Lang.Class({
DND.addDragMonitor(this._dragMonitor);
// Remember the workspace we started from
this._lastActiveWorkspaceIndex = global.screen.get_active_workspace_index();
let workspaceManager = global.workspace_manager;
this._lastActiveWorkspaceIndex = workspaceManager.get_active_workspace_index();
},
_onDragEnd(time) {
@ -296,7 +297,8 @@ var Overview = new Lang.Class({
// we have to go back to where we started and hide
// the overview
if (this._shown) {
global.screen.get_workspace_by_index(this._lastActiveWorkspaceIndex).activate(time);
let workspaceManager = global.workspace_manager;
workspaceManager.get_workspace_by_index(this._lastActiveWorkspaceIndex).activate(time);
this.hide();
}
this._resetWindowSwitchTimeout();
@ -317,9 +319,9 @@ var Overview = new Lang.Class({
let display = Gdk.Display.get_default();
let deviceManager = display.get_device_manager();
let pointer = deviceManager.get_client_pointer();
let [screen, pointerX, pointerY] = pointer.get_position();
let [gdkScreen, pointerX, pointerY] = pointer.get_position();
pointer.warp(screen, pointerX, pointerY);
pointer.warp(gdkScreen, pointerX, pointerY);
},
_onDragMotion(dragEvent) {
@ -550,7 +552,7 @@ var Overview = new Lang.Class({
this.visibleTarget = true;
this._activationTime = GLib.get_monotonic_time() / GLib.USEC_PER_SEC;
Meta.disable_unredirect_for_screen(global.screen);
Meta.disable_unredirect_for_display(global.display);
this.viewSelector.show();
this._overview.opacity = 0;
@ -635,7 +637,7 @@ var Overview = new Lang.Class({
_hideDone() {
// Re-enable unredirection
Meta.enable_unredirect_for_screen(global.screen);
Meta.enable_unredirect_for_display(global.display);
this.viewSelector.hide();
this._desktopFade.hide();

View File

@ -265,7 +265,8 @@ var AppMenuButton = new Lang.Class({
},
_findTargetApp() {
let workspace = global.screen.get_active_workspace();
let workspaceManager = global.workspace_manager;
let workspace = workspaceManager.get_active_workspace();
let tracker = Shell.WindowTracker.get_default();
let focusedApp = tracker.focus_app;
if (focusedApp && focusedApp.is_on_workspace(workspace))
@ -796,6 +797,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', () => {
@ -818,7 +820,7 @@ var Panel = new Lang.Class({
global.window_group.connect('actor-removed', this._onWindowActorRemoved.bind(this));
global.window_manager.connect('switch-workspace', this._updateSolidStyle.bind(this));
global.screen.connect('workareas-changed', () => { this.actor.queue_relayout(); });
global.display.connect('workareas-changed', () => { this.actor.queue_relayout(); });
this._updatePanel();
},
@ -939,8 +941,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;
@ -961,8 +968,7 @@ var Panel = new Lang.Class({
if (!allowDrag)
return Clutter.EVENT_PROPAGATE;
global.display.begin_grab_op(global.screen,
dragWindow,
global.display.begin_grab_op(dragWindow,
Meta.GrabOp.MOVING,
false, /* pointer grab */
true, /* frame action */
@ -977,7 +983,7 @@ var Panel = new Lang.Class({
_onKeyPress(actor, event) {
let symbol = event.get_key_symbol();
if (symbol == Clutter.KEY_Escape) {
global.screen.focus_default_window(event.get_time());
global.display.focus_default_window(event.get_time());
return Clutter.EVENT_STOP;
}
@ -1075,7 +1081,8 @@ var Panel = new Lang.Class({
return;
/* Get all the windows in the active workspace that are in the primary monitor and visible */
let activeWorkspace = global.screen.get_active_workspace();
let workspaceManager = global.workspace_manager;
let activeWorkspace = workspaceManager.get_active_workspace();
let windows = activeWorkspace.list_windows().filter(metaWindow => {
return metaWindow.is_on_primary_monitor() &&
metaWindow.showing_on_its_workspace() &&

View File

@ -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;

View File

@ -172,9 +172,10 @@ var RunDialog = new Lang.Class({
if (name.slice(0, text.length) == text)
results.push(name);
}
} catch (e if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND) &&
!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_DIRECTORY))) {
log(e);
} catch (e) {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND) &&
!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_DIRECTORY))
log(e);
} finally {
return results;
}

View File

@ -570,7 +570,7 @@ var ScreenShield = new Lang.Class({
this._shortLightbox.connect('shown', this._onShortLightboxShown.bind(this));
this.idleMonitor = Meta.IdleMonitor.get_core();
this._cursorTracker = Meta.CursorTracker.get_for_screen(global.screen);
this._cursorTracker = Meta.CursorTracker.get_for_display(global.display);
this._syncInhibitor();
},

View File

@ -56,7 +56,7 @@ var ScreencastService = new Lang.Class({
let recorder = this._recorders.get(sender);
if (!recorder) {
recorder = new Shell.Recorder({ stage: global.stage,
screen: global.screen });
display: global.display });
recorder._watchNameId =
Gio.bus_watch_name(Gio.BusType.SESSION, sender, 0, null,
this._onNameVanished.bind(this));

View File

@ -261,7 +261,7 @@ var SelectArea = new Lang.Class({
onUngrab: this._onUngrab.bind(this) }))
return;
global.screen.set_cursor(Meta.Cursor.CROSSHAIR);
global.display.set_cursor(Meta.Cursor.CROSSHAIR);
Main.uiGroup.set_child_above_sibling(this._group, null);
this._group.visible = true;
},
@ -330,7 +330,7 @@ var SelectArea = new Lang.Class({
},
_onUngrab() {
global.screen.set_cursor(Meta.Cursor.DEFAULT);
global.display.set_cursor(Meta.Cursor.DEFAULT);
this.emit('finished', this._result);
GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {

View File

@ -216,12 +216,14 @@ function _step(g, finish, onError) {
if (onError)
onError(err);
});
} catch (err if err instanceof StopIteration) {
if (finish)
finish();
} catch (err) {
if (onError)
onError(err);
if (err instanceof StopIteration) {
if (finish)
finish();
} else {
if (onError)
onError(err);
}
}
}

View File

@ -398,7 +398,7 @@ var InputSourceManager = new Lang.Class({
return true;
},
_switchInputSource(display, screen, window, binding) {
_switchInputSource(display, window, binding) {
if (this._mruSources.length < 2)
return;

View File

@ -995,8 +995,16 @@ var NMWirelessDialog = new Lang.Class({
else if (!oneHasConnection && twoHasConnection)
return 1;
let oneStrength = one.accessPoints[0].strength;
let twoStrength = two.accessPoints[0].strength;
let oneAp = one.accessPoints[0] || null;
let twoAp = two.accessPoints[0] || null;
if (oneAp != null && twoAp == null)
return -1;
else if (oneAp == null && twoAp != null)
return 1;
let oneStrength = oneAp.strength;
let twoStrength = twoAp.strength;
// place stronger connections first
if (oneStrength != twoStrength)
@ -1156,6 +1164,11 @@ var NMWirelessDialog = new Lang.Class({
Util.ensureActorVisibleInScrollView(this._scrollView, network.item.actor);
this._selectNetwork(network);
});
network.item.actor.connect('destroy', () => {
let keyFocus = global.stage.key_focus;
if (keyFocus && keyFocus.contains(network.item.actor))
this._itemBox.grab_key_focus();
});
},
});
@ -1944,6 +1957,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();
},

View File

@ -49,7 +49,6 @@ const BoltDeviceInterface = '<node> \
</interface> \
</node>';
const BoltClientProxy = Gio.DBusProxy.makeProxyWrapper(BoltClientInterface);
const BoltDeviceProxy = Gio.DBusProxy.makeProxyWrapper(BoltDeviceInterface);
/* */
@ -78,6 +77,7 @@ var AuthMode = {
ENABLED: 'enabled'
};
const BOLT_DBUS_CLIENT_IFACE = 'org.freedesktop.bolt1.Manager';
const BOLT_DBUS_NAME = 'org.freedesktop.bolt';
const BOLT_DBUS_PATH = '/org/freedesktop/bolt';
@ -87,22 +87,26 @@ var Client = new Lang.Class({
_init() {
this._proxy = null;
new BoltClientProxy(
Gio.DBus.system,
BOLT_DBUS_NAME,
BOLT_DBUS_PATH,
this._onProxyReady.bind(this)
);
let nodeInfo = Gio.DBusNodeInfo.new_for_xml(BoltClientInterface);
Gio.DBusProxy.new(Gio.DBus.system,
Gio.DBusProxyFlags.DO_NOT_AUTO_START,
nodeInfo.lookup_interface(BOLT_DBUS_CLIENT_IFACE),
BOLT_DBUS_NAME,
BOLT_DBUS_PATH,
BOLT_DBUS_CLIENT_IFACE,
null,
this._onProxyReady.bind(this));
this.probing = false;
},
_onProxyReady(proxy, error) {
if (error !== null) {
log('error creating bolt proxy: %s'.format(error.message));
return;
}
this._proxy = proxy;
_onProxyReady(o, res) {
try {
this._proxy = Gio.DBusProxy.new_finish(res);
} catch(e) {
log('error creating bolt proxy: %s'.format(e.message));
return;
}
this._propsChangedId = this._proxy.connect('g-properties-changed', this._onPropertiesChanged.bind(this));
this._deviceAddedId = this._proxy.connectSignal('DeviceAdded', this._onDeviceAdded.bind(this));

View File

@ -192,7 +192,9 @@ var SwitcherPopup = new Lang.Class({
if (this._keyPressHandler(keysym, action) != Clutter.EVENT_PROPAGATE)
return Clutter.EVENT_STOP;
if (keysym == Clutter.Escape)
// Note: pressing one of the below keys will destroy the popup only if
// that key is not used by the active popup's keyboard shortcut
if (keysym == Clutter.Escape || keysym == Clutter.Tab)
this.destroy();
return Clutter.EVENT_STOP;

View File

@ -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;
@ -200,12 +200,18 @@ var WorkspaceTracker = new Lang.Class({
let tracker = Shell.WindowTracker.get_default();
tracker.connect('startup-sequence-changed', this._queueCheckWorkspaces.bind(this));
global.screen.connect('notify::n-workspaces', this._nWorkspacesChanged.bind(this));
global.window_manager.connect('switch-workspace', this._queueCheckWorkspaces.bind(this));
let workspaceManager = global.workspace_manager;
workspaceManager.connect('notify::n-workspaces',
this._nWorkspacesChanged.bind(this));
global.window_manager.connect('switch-workspace',
this._queueCheckWorkspaces.bind(this));
global.screen.connect('window-entered-monitor', this._windowEnteredMonitor.bind(this));
global.screen.connect('window-left-monitor', this._windowLeftMonitor.bind(this));
global.screen.connect('restacked', this._windowsRestacked.bind(this));
global.display.connect('window-entered-monitor',
this._windowEnteredMonitor.bind(this));
global.display.connect('window-left-monitor',
this._windowLeftMonitor.bind(this));
global.display.connect('restacked',
this._windowsRestacked.bind(this));
this._workspaceSettings = this._getWorkspaceSettings();
this._workspaceSettings.connect('changed::dynamic-workspaces', this._queueCheckWorkspaces.bind(this));
@ -230,6 +236,7 @@ var WorkspaceTracker = new Lang.Class({
},
_checkWorkspaces() {
let workspaceManager = global.workspace_manager;
let i;
let emptyWorkspaces = [];
@ -257,7 +264,7 @@ var WorkspaceTracker = new Lang.Class({
let sequences = Shell.WindowTracker.get_default().get_startup_sequences();
for (i = 0; i < sequences.length; i++) {
let index = sequences[i].get_workspace();
if (index >= 0 && index <= global.screen.n_workspaces)
if (index >= 0 && index <= workspaceManager.n_workspaces)
emptyWorkspaces[index] = false;
}
@ -275,17 +282,17 @@ var WorkspaceTracker = new Lang.Class({
// If we don't have an empty workspace at the end, add one
if (!emptyWorkspaces[emptyWorkspaces.length -1]) {
global.screen.append_new_workspace(false, global.get_current_time());
workspaceManager.append_new_workspace(false, global.get_current_time());
emptyWorkspaces.push(false);
}
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
let activeWorkspaceIndex = workspaceManager.get_active_workspace_index();
emptyWorkspaces[activeWorkspaceIndex] = false;
// Delete other empty workspaces; do it from the end to avoid index changes
for (i = emptyWorkspaces.length - 2; i >= 0; i--) {
if (emptyWorkspaces[i])
global.screen.remove_workspace(this._workspaces[i], global.get_current_time());
workspaceManager.remove_workspace(this._workspaces[i], global.get_current_time());
}
this._checkWorkspacesId = 0;
@ -317,14 +324,14 @@ var WorkspaceTracker = new Lang.Class({
GLib.Source.set_name_by_id(id, '[gnome-shell] this._queueCheckWorkspaces');
},
_windowLeftMonitor(metaScreen, monitorIndex, metaWin) {
_windowLeftMonitor(metaDisplay, monitorIndex, metaWin) {
// If the window left the primary monitor, that
// might make that workspace empty
if (monitorIndex == Main.layoutManager.primaryIndex)
this._queueCheckWorkspaces();
},
_windowEnteredMonitor(metaScreen, monitorIndex, metaWin) {
_windowEnteredMonitor(metaDisplay, monitorIndex, metaWin) {
// If the window entered the primary monitor, that
// might make that workspace non-empty
if (monitorIndex == Main.layoutManager.primaryIndex)
@ -344,8 +351,9 @@ var WorkspaceTracker = new Lang.Class({
},
_nWorkspacesChanged() {
let workspaceManager = global.workspace_manager;
let oldNumWorkspaces = this._workspaces.length;
let newNumWorkspaces = global.screen.n_workspaces;
let newNumWorkspaces = workspaceManager.n_workspaces;
if (oldNumWorkspaces == newNumWorkspaces)
return false;
@ -356,7 +364,7 @@ var WorkspaceTracker = new Lang.Class({
// Assume workspaces are only added at the end
for (w = oldNumWorkspaces; w < newNumWorkspaces; w++)
this._workspaces[w] = global.screen.get_workspace_by_index(w);
this._workspaces[w] = workspaceManager.get_workspace_by_index(w);
for (w = oldNumWorkspaces; w < newNumWorkspaces; w++) {
let workspace = this._workspaces[w];
@ -370,7 +378,7 @@ var WorkspaceTracker = new Lang.Class({
let removedIndex;
let removedNum = oldNumWorkspaces - newNumWorkspaces;
for (let w = 0; w < oldNumWorkspaces; w++) {
let workspace = global.screen.get_workspace_by_index(w);
let workspace = workspaceManager.get_workspace_by_index(w);
if (this._workspaces[w] != workspace) {
removedIndex = w;
break;
@ -714,7 +722,7 @@ var WindowManager = new Lang.Class({
this._shellwm.connect('confirm-display-change', this._confirmDisplayChange.bind(this));
this._shellwm.connect('create-close-dialog', this._createCloseDialog.bind(this));
this._shellwm.connect('create-inhibit-shortcuts-dialog', this._createInhibitShortcutsDialog.bind(this));
global.screen.connect('restacked', this._syncStacking.bind(this));
global.display.connect('restacked', this._syncStacking.bind(this));
this._workspaceSwitcherPopup = null;
this._tilePreview = null;
@ -970,8 +978,8 @@ var WindowManager = new Lang.Class({
if (Main.sessionMode.hasWorkspaces)
this._workspaceTracker = new WorkspaceTracker(this);
global.screen.override_workspace_layout(Meta.ScreenCorner.TOPLEFT,
false, -1, 1);
global.workspace_manager.override_workspace_layout(Meta.DisplayCorner.TOPLEFT,
false, -1, 1);
let gesture = new WorkspaceSwitchAction();
gesture.connect('activated', this._actionSwitchWorkspace.bind(this));
@ -1001,7 +1009,9 @@ var WindowManager = new Lang.Class({
},
_actionSwitchWorkspace(action, direction) {
let newWs = global.screen.get_active_workspace().get_neighbor(direction);
let workspaceManager = global.workspace_manager;
let activeWorkspace = workspaceManager.get_active_workspace();
let newWs = activeWorkspace.get_neighbor(direction);
this.actionMoveWorkspace(newWs);
},
@ -1017,8 +1027,10 @@ var WindowManager = new Lang.Class({
_switchApp() {
let windows = global.get_window_actors().filter(actor => {
let win = actor.metaWindow;
let workspaceManager = global.workspace_manager;
let activeWorkspace = workspaceManager.get_active_workspace();
return (!win.is_override_redirect() &&
win.located_on_workspace(global.screen.get_active_workspace()));
win.located_on_workspace(activeWorkspace));
});
if (windows.length == 0)
@ -1042,10 +1054,12 @@ var WindowManager = new Lang.Class({
},
insertWorkspace(pos) {
let workspaceManager = global.workspace_manager;
if (!Meta.prefs_get_dynamic_workspaces())
return;
global.screen.append_new_workspace(false, global.get_current_time());
workspaceManager.append_new_workspace(false, global.get_current_time());
let windows = global.get_window_actors().map(a => a.meta_window);
@ -1069,9 +1083,9 @@ var WindowManager = new Lang.Class({
// If the new workspace was inserted before the active workspace,
// activate the workspace to which its windows went
let activeIndex = global.screen.get_active_workspace_index();
let activeIndex = workspaceManager.get_active_workspace_index();
if (activeIndex >= pos) {
let newWs = global.screen.get_workspace_by_index(activeIndex + 1);
let newWs = workspaceManager.get_workspace_by_index(activeIndex + 1);
this._blockAnimations = true;
newWs.activate(global.get_current_time());
this._blockAnimations = false;
@ -1173,6 +1187,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 +1266,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;
@ -1820,7 +1843,7 @@ var WindowManager = new Lang.Class({
this._windowMenuManager.showWindowMenuForWindow(window, menu, rect);
},
_startSwitcher(display, screen, window, binding) {
_startSwitcher(display, window, binding) {
let constructor = null;
switch (binding.get_name()) {
case 'switch-applications':
@ -1859,15 +1882,15 @@ var WindowManager = new Lang.Class({
tabPopup.destroy();
},
_startA11ySwitcher(display, screen, window, binding) {
_startA11ySwitcher(display, window, binding) {
Main.ctrlAltTabManager.popup(binding.is_reversed(), binding.get_name(), binding.get_mask());
},
_toggleAppMenu(display, screen, window, event, binding) {
_toggleAppMenu(display, window, event, binding) {
Main.panel.toggleAppMenu();
},
_toggleCalendar(display, screen, window, event, binding) {
_toggleCalendar(display, window, event, binding) {
Main.panel.toggleCalendar();
},
@ -1880,11 +1903,13 @@ var WindowManager = new Lang.Class({
OrigTweener.resumeAllTweens();
},
_showWorkspaceSwitcher(display, screen, window, binding) {
_showWorkspaceSwitcher(display, window, binding) {
let workspaceManager = display.get_workspace_manager();
if (!Main.sessionMode.hasWorkspaces)
return;
if (screen.n_workspaces == 1)
if (workspaceManager.n_workspaces == 1)
return;
let [action,,,target] = binding.get_name().split('-');
@ -1903,22 +1928,22 @@ var WindowManager = new Lang.Class({
if (target == 'last') {
direction = Meta.MotionDirection.DOWN;
newWs = screen.get_workspace_by_index(screen.n_workspaces - 1);
newWs = workspaceManager.get_workspace_by_index(workspaceManager.n_workspaces - 1);
} else if (isNaN(target)) {
// Prepend a new workspace dynamically
if (screen.get_active_workspace_index() == 0 &&
if (workspaceManager.get_active_workspace_index() == 0 &&
action == 'move' && target == 'up' && this._isWorkspacePrepended == false) {
this.insertWorkspace(0);
this._isWorkspacePrepended = true;
}
direction = Meta.MotionDirection[target.toUpperCase()];
newWs = screen.get_active_workspace().get_neighbor(direction);
newWs = workspaceManager.get_active_workspace().get_neighbor(direction);
} else if (target > 0) {
target--;
newWs = screen.get_workspace_by_index(target);
newWs = workspaceManager.get_workspace_by_index(target);
if (screen.get_active_workspace().index() > target)
if (workspaceManager.get_active_workspace().index() > target)
direction = Meta.MotionDirection.UP;
else
direction = Meta.MotionDirection.DOWN;
@ -1951,7 +1976,8 @@ var WindowManager = new Lang.Class({
if (!Main.sessionMode.hasWorkspaces)
return;
let activeWorkspace = global.screen.get_active_workspace();
let workspaceManager = global.workspace_manager;
let activeWorkspace = workspaceManager.get_active_workspace();
if (activeWorkspace != workspace)
workspace.activate(global.get_current_time());
@ -1961,7 +1987,8 @@ var WindowManager = new Lang.Class({
if (!Main.sessionMode.hasWorkspaces)
return;
let activeWorkspace = global.screen.get_active_workspace();
let workspaceManager = global.workspace_manager;
let activeWorkspace = workspaceManager.get_active_workspace();
if (activeWorkspace != workspace) {
// This won't have any effect for "always sticky" windows

View File

@ -126,16 +126,15 @@ var WindowMenu = new Lang.Class({
}
}
let screen = global.screen;
let nMonitors = screen.get_n_monitors();
if (nMonitors > 1) {
let display = global.display;
let nMonitors = display.get_n_monitors();
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);
display.get_monitor_neighbor_index(monitorIndex, dir);
if (upMonitorIndex != -1) {
this.addAction(_("Move to Monitor Up"), () => {
window.move_to_monitor(upMonitorIndex);
@ -144,7 +143,7 @@ var WindowMenu = new Lang.Class({
dir = Meta.ScreenDirection.DOWN;
let downMonitorIndex =
screen.get_monitor_neighbor_index(monitorIndex, dir);
display.get_monitor_neighbor_index(monitorIndex, dir);
if (downMonitorIndex != -1) {
this.addAction(_("Move to Monitor Down"), () => {
window.move_to_monitor(downMonitorIndex);
@ -153,7 +152,7 @@ var WindowMenu = new Lang.Class({
dir = Meta.ScreenDirection.LEFT;
let leftMonitorIndex =
screen.get_monitor_neighbor_index(monitorIndex, dir);
display.get_monitor_neighbor_index(monitorIndex, dir);
if (leftMonitorIndex != -1) {
this.addAction(_("Move to Monitor Left"), () => {
window.move_to_monitor(leftMonitorIndex);
@ -162,7 +161,7 @@ var WindowMenu = new Lang.Class({
dir = Meta.ScreenDirection.RIGHT;
let rightMonitorIndex =
screen.get_monitor_neighbor_index(monitorIndex, dir);
display.get_monitor_neighbor_index(monitorIndex, dir);
if (rightMonitorIndex != -1) {
this.addAction(_("Move to Monitor Right"), () => {
window.move_to_monitor(rightMonitorIndex);

View File

@ -447,12 +447,13 @@ var WindowOverlay = new Lang.Class({
this.border = new St.Bin({ style_class: 'window-clone-border' });
let title = new St.Label({ style_class: 'window-caption',
text: metaWindow.title });
text: this._getCaption() });
title.clutter_text.ellipsize = Pango.EllipsizeMode.END;
windowClone.actor.label_actor = title;
this._updateCaptionId = metaWindow.connect('notify::title', w => {
this.title.text = w.title;
this.title.text = this._getCaption();
this.relayout(false);
});
@ -565,6 +566,16 @@ var WindowOverlay = new Lang.Class({
}
},
_getCaption() {
let metaWindow = this._windowClone.metaWindow;
if (metaWindow.title)
return metaWindow.title;
let tracker = Shell.WindowTracker.get_default();
let app = tracker.get_window_app(metaWindow);
return app.get_name();
},
_animateOverlayActor(actor, x, y, width, height) {
let params = { x: x,
y: y,
@ -1145,10 +1156,10 @@ var Workspace = new Lang.Class({
this._windowRemovedId = this.metaWorkspace.connect('window-removed',
this._windowRemoved.bind(this));
}
this._windowEnteredMonitorId = global.screen.connect('window-entered-monitor',
this._windowEnteredMonitor.bind(this));
this._windowLeftMonitorId = global.screen.connect('window-left-monitor',
this._windowLeftMonitor.bind(this));
this._windowEnteredMonitorId = global.display.connect('window-entered-monitor',
this._windowEnteredMonitor.bind(this));
this._windowLeftMonitorId = global.display.connect('window-left-monitor',
this._windowLeftMonitor.bind(this));
this._repositionWindowsId = 0;
this.leavingOverview = false;
@ -1294,7 +1305,8 @@ var Workspace = new Lang.Class({
let area = padArea(this._actualGeometry, padding);
let slots = strategy.computeWindowSlots(layout, area);
let currentWorkspace = global.screen.get_active_workspace();
let workspaceManager = global.workspace_manager;
let currentWorkspace = workspaceManager.get_active_workspace();
let isOnCurrentWorkspace = this.metaWorkspace == null || this.metaWorkspace == currentWorkspace;
for (let i = 0; i < slots.length; i++) {
@ -1431,34 +1443,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
@ -1557,13 +1561,13 @@ var Workspace = new Lang.Class({
this._doRemoveWindow(metaWin);
},
_windowEnteredMonitor(metaScreen, monitorIndex, metaWin) {
_windowEnteredMonitor(metaDisplay, monitorIndex, metaWin) {
if (monitorIndex == this.monitorIndex) {
this._doAddWindow(metaWin);
}
},
_windowLeftMonitor(metaScreen, monitorIndex, metaWin) {
_windowLeftMonitor(metaDisplay, monitorIndex, metaWin) {
if (monitorIndex == this.monitorIndex) {
this._doRemoveWindow(metaWin);
}
@ -1588,7 +1592,9 @@ var Workspace = new Lang.Class({
if (this._windows.length == 0)
return;
if (this.metaWorkspace != null && this.metaWorkspace != global.screen.get_active_workspace())
let workspaceManager = global.workspace_manager;
let activeWorkspace = workspaceManager.get_active_workspace();
if (this.metaWorkspace != null && this.metaWorkspace != activeWorkspace)
return;
// Special case maximized windows, since it doesn't make sense
@ -1644,7 +1650,9 @@ var Workspace = new Lang.Class({
this._repositionWindowsId = 0;
}
if (this.metaWorkspace != null && this.metaWorkspace != global.screen.get_active_workspace())
let workspaceManager = global.workspace_manager;
let activeWorkspace = workspaceManager.get_active_workspace();
if (this.metaWorkspace != null && this.metaWorkspace != activeWorkspace)
return;
// Special case maximized windows, since it doesn't make sense
@ -1714,7 +1722,8 @@ var Workspace = new Lang.Class({
},
zoomFromOverview() {
let currentWorkspace = global.screen.get_active_workspace();
let workspaceManager = global.workspace_manager;
let currentWorkspace = workspaceManager.get_active_workspace();
this.leavingOverview = true;
@ -1782,8 +1791,8 @@ var Workspace = new Lang.Class({
this.metaWorkspace.disconnect(this._windowAddedId);
this.metaWorkspace.disconnect(this._windowRemovedId);
}
global.screen.disconnect(this._windowEnteredMonitorId);
global.screen.disconnect(this._windowLeftMonitorId);
global.display.disconnect(this._windowEnteredMonitorId);
global.display.disconnect(this._windowLeftMonitorId);
if (this._repositionWindowsId > 0) {
Mainloop.source_remove(this._repositionWindowsId);
@ -1848,6 +1857,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 +1881,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];
@ -2004,7 +2027,8 @@ var Workspace = new Lang.Class({
if (metaWindow.get_monitor() != this.monitorIndex)
metaWindow.move_to_monitor(this.monitorIndex);
let index = this.metaWorkspace ? this.metaWorkspace.index() : global.screen.get_active_workspace_index();
let workspaceManager = global.workspace_manager;
let index = this.metaWorkspace ? this.metaWorkspace.index() : workspaceManager.get_active_workspace_index();
metaWindow.change_workspace_by_index(index, false);
return true;
} else if (source.shellWorkspaceLaunch) {

View File

@ -47,9 +47,12 @@ var WorkspaceSwitcherPopup = new Lang.Class({
this.actor.hide();
this._globalSignals = [];
this._globalSignals.push(global.screen.connect('workspace-added', this._redisplay.bind(this)));
this._globalSignals.push(global.screen.connect('workspace-removed', this._redisplay.bind(this)));
let workspaceManager = global.workspace_manager;
this._workspaceManagerSignals = [];
this._workspaceManagerSignals.push(workspaceManager.connect('workspace-added',
this._redisplay.bind(this)));
this._workspaceManagerSignals.push(workspaceManager.connect('workspace-removed',
this._redisplay.bind(this)));
},
_getPreferredHeight(actor, forWidth, alloc) {
@ -68,11 +71,12 @@ var WorkspaceSwitcherPopup = new Lang.Class({
height += childNaturalHeight * workArea.width / workArea.height;
}
let spacing = this._itemSpacing * (global.screen.n_workspaces - 1);
let workspaceManager = global.workspace_manager;
let spacing = this._itemSpacing * (workspaceManager.n_workspaces - 1);
height += spacing;
height = Math.min(height, availHeight);
this._childHeight = (height - spacing) / global.screen.n_workspaces;
this._childHeight = (height - spacing) / workspaceManager.n_workspaces;
alloc.min_size = height;
alloc.natural_size = height;
@ -104,9 +108,11 @@ var WorkspaceSwitcherPopup = new Lang.Class({
},
_redisplay() {
let workspaceManager = global.workspace_manager;
this._list.destroy_all_children();
for (let i = 0; i < global.screen.n_workspaces; i++) {
for (let i = 0; i < workspaceManager.n_workspaces; i++) {
let indicator = null;
if (i == this._activeWorkspaceIndex && this._direction == Meta.MotionDirection.UP)
@ -164,8 +170,9 @@ var WorkspaceSwitcherPopup = new Lang.Class({
Mainloop.source_remove(this._timeoutId);
this._timeoutId = 0;
for (let i = 0; i < this._globalSignals.length; i++)
global.screen.disconnect(this._globalSignals[i]);
let workspaceManager = global.workspace_manager;
for (let i = 0; i < this._workspaceManagerSignals.length; i++)
workspaceManager.disconnect(this._workspaceManagerSignals[i]);
this.actor.destroy();

View File

@ -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 */
@ -241,7 +241,7 @@ var WindowClone = new Lang.Class({
Signals.addSignalMethods(WindowClone.prototype);
const ThumbnailState = {
var ThumbnailState = {
NEW : 0,
ANIMATING_IN : 1,
NORMAL: 2,
@ -304,9 +304,9 @@ var WorkspaceThumbnail = new Lang.Class({
this._windowAdded.bind(this));
this._windowRemovedId = this.metaWorkspace.connect('window-removed',
this._windowRemoved.bind(this));
this._windowEnteredMonitorId = global.screen.connect('window-entered-monitor',
this._windowEnteredMonitor.bind(this));
this._windowLeftMonitorId = global.screen.connect('window-left-monitor',
this._windowEnteredMonitorId = global.display.connect('window-entered-monitor',
this._windowEnteredMonitor.bind(this));
this._windowLeftMonitorId = global.display.connect('window-left-monitor',
this._windowLeftMonitor.bind(this));
this.state = ThumbnailState.NORMAL;
@ -372,18 +372,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) {
@ -455,13 +446,13 @@ var WorkspaceThumbnail = new Lang.Class({
this._doRemoveWindow(metaWin);
},
_windowEnteredMonitor(metaScreen, monitorIndex, metaWin) {
_windowEnteredMonitor(metaDisplay, monitorIndex, metaWin) {
if (monitorIndex == this.monitorIndex) {
this._doAddWindow(metaWin);
}
},
_windowLeftMonitor(metaScreen, monitorIndex, metaWin) {
_windowLeftMonitor(metaDisplay, monitorIndex, metaWin) {
if (monitorIndex == this.monitorIndex) {
this._doRemoveWindow(metaWin);
}
@ -487,8 +478,8 @@ var WorkspaceThumbnail = new Lang.Class({
this.metaWorkspace.disconnect(this._windowAddedId);
this.metaWorkspace.disconnect(this._windowRemovedId);
global.screen.disconnect(this._windowEnteredMonitorId);
global.screen.disconnect(this._windowLeftMonitorId);
global.display.disconnect(this._windowEnteredMonitorId);
global.display.disconnect(this._windowLeftMonitorId);
for (let i = 0; i < this._allWindows.length; i++)
this._allWindows[i].disconnect(this._minimizedChangedIds[i]);
@ -535,6 +526,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,12 +541,24 @@ 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;
// a click on the already current workspace should go back to the main view
if (this.metaWorkspace == global.screen.get_active_workspace())
let workspaceManager = global.workspace_manager;
let activeWorkspace = workspaceManager.get_active_workspace();
if (this.metaWorkspace == activeWorkspace)
Main.overview.hide();
else
this.metaWorkspace.activate(time);
@ -674,12 +680,19 @@ var ThumbnailsBox = new Lang.Class({
this._updateSwitcherVisibility.bind(this));
Main.layoutManager.connect('monitors-changed', this._rebuildThumbnails.bind(this));
this._switchWorkspaceNotifyId = 0;
this._nWorkspacesNotifyId = 0;
this._syncStackingId = 0;
this._workareasChangedId = 0;
},
_updateSwitcherVisibility() {
let workspaceManager = global.workspace_manager;
this.actor.visible =
this._settings.get_boolean('dynamic-workspaces') ||
global.screen.n_workspaces > 1;
workspaceManager.n_workspaces > 1;
},
_activateThumbnailAtPoint(stageX, stageY, time) {
@ -837,7 +850,8 @@ var ThumbnailsBox = new Lang.Class({
// to open its first window within some time, as tracked by Shell.WindowTracker.
// Here, we only add a very brief timeout to avoid the _immediate_ removal of the
// workspace while we wait for the startup sequence to load.
Main.wm.keepWorkspaceAlive(global.screen.get_workspace_by_index(newWorkspaceIndex),
let workspaceManager = global.workspace_manager;
Main.wm.keepWorkspaceAlive(workspaceManager.get_workspace_by_index(newWorkspaceIndex),
WORKSPACE_KEEP_ALIVE_TIME);
}
@ -856,18 +870,21 @@ var ThumbnailsBox = new Lang.Class({
},
_createThumbnails() {
let workspaceManager = global.workspace_manager;
this._switchWorkspaceNotifyId =
global.window_manager.connect('switch-workspace',
this._activeWorkspaceChanged.bind(this));
this._nWorkspacesNotifyId =
global.screen.connect('notify::n-workspaces',
this._workspacesChanged.bind(this));
workspaceManager.connect('notify::n-workspaces',
this._workspacesChanged.bind(this));
this._syncStackingId =
Main.overview.connect('windows-restacked',
this._syncStacking.bind(this));
this._workareasChangedId =
global.screen.connect('workareas-changed', this._rebuildThumbnails.bind(this));
global.display.connect('workareas-changed',
this._rebuildThumbnails.bind(this));
this._targetScale = 0;
this._scale = 0;
@ -878,7 +895,7 @@ var ThumbnailsBox = new Lang.Class({
for (let key in ThumbnailState)
this._stateCounts[ThumbnailState[key]] = 0;
this.addThumbnails(0, global.screen.n_workspaces);
this.addThumbnails(0, workspaceManager.n_workspaces);
this._updateSwitcherVisibility();
},
@ -892,7 +909,8 @@ var ThumbnailsBox = new Lang.Class({
this._switchWorkspaceNotifyId = 0;
}
if (this._nWorkspacesNotifyId > 0) {
global.screen.disconnect(this._nWorkspacesNotifyId);
let workspaceManager = global.workspace_manager;
workspaceManager.disconnect(this._nWorkspacesNotifyId);
this._nWorkspacesNotifyId = 0;
}
@ -902,7 +920,7 @@ var ThumbnailsBox = new Lang.Class({
}
if (this._workareasChangedId > 0) {
global.screen.disconnect(this._workareasChangedId);
global.display.disconnect(this._workareasChangedId);
this._workareasChangedId = 0;
}
@ -922,9 +940,10 @@ var ThumbnailsBox = new Lang.Class({
_workspacesChanged() {
let validThumbnails =
this._thumbnails.filter(t => t.state <= ThumbnailState.NORMAL);
let workspaceManager = global.workspace_manager;
let oldNumWorkspaces = validThumbnails.length;
let newNumWorkspaces = global.screen.n_workspaces;
let active = global.screen.get_active_workspace_index();
let newNumWorkspaces = workspaceManager.n_workspaces;
let active = workspaceManager.get_active_workspace_index();
if (newNumWorkspaces > oldNumWorkspaces) {
this.addThumbnails(oldNumWorkspaces, newNumWorkspaces - oldNumWorkspaces);
@ -932,7 +951,7 @@ var ThumbnailsBox = new Lang.Class({
let removedIndex;
let removedNum = oldNumWorkspaces - newNumWorkspaces;
for (let w = 0; w < oldNumWorkspaces; w++) {
let metaWorkspace = global.screen.get_workspace_by_index(w);
let metaWorkspace = workspaceManager.get_workspace_by_index(w);
if (this._thumbnails[w].metaWorkspace != metaWorkspace) {
removedIndex = w;
break;
@ -946,10 +965,12 @@ var ThumbnailsBox = new Lang.Class({
},
addThumbnails(start, count) {
let workspaceManager = global.workspace_manager;
if (!this._ensurePorthole())
return;
for (let k = start; k < start + count; k++) {
let metaWorkspace = global.screen.get_workspace_by_index(k);
let metaWorkspace = workspaceManager.get_workspace_by_index(k);
let thumbnail = new WorkspaceThumbnail(metaWorkspace);
thumbnail.setPorthole(this._porthole.x, this._porthole.y,
this._porthole.width, this._porthole.height);
@ -1135,10 +1156,11 @@ var ThumbnailsBox = new Lang.Class({
return;
}
let workspaceManager = global.workspace_manager;
let themeNode = this.actor.get_theme_node();
let spacing = themeNode.get_length('spacing');
let nWorkspaces = global.screen.n_workspaces;
let nWorkspaces = workspaceManager.n_workspaces;
let totalSpacing = (nWorkspaces - 1) * spacing;
alloc.min_size = totalSpacing;
@ -1152,10 +1174,11 @@ var ThumbnailsBox = new Lang.Class({
return;
}
let workspaceManager = global.workspace_manager;
let themeNode = this.actor.get_theme_node();
let spacing = this.actor.get_theme_node().get_length('spacing');
let nWorkspaces = global.screen.n_workspaces;
let nWorkspaces = workspaceManager.n_workspaces;
let totalSpacing = (nWorkspaces - 1) * spacing;
let avail = forHeight - totalSpacing;
@ -1186,6 +1209,7 @@ var ThumbnailsBox = new Lang.Class({
if (this._thumbnails.length == 0) // not visible
return;
let workspaceManager = global.workspace_manager;
let themeNode = this.actor.get_theme_node();
let portholeWidth = this._porthole.width;
@ -1193,7 +1217,7 @@ var ThumbnailsBox = new Lang.Class({
let spacing = themeNode.get_length('spacing');
// Compute the scale we'll need once everything is updated
let nWorkspaces = global.screen.n_workspaces;
let nWorkspaces = workspaceManager.n_workspaces;
let totalSpacing = (nWorkspaces - 1) * spacing;
let avail = (box.y2 - box.y1) - totalSpacing;
@ -1227,7 +1251,8 @@ var ThumbnailsBox = new Lang.Class({
let indicatorY1 = this._indicatorY;
let indicatorY2;
// when not animating, the workspace position overrides this._indicatorY
let indicatorWorkspace = !this._animatingIndicator ? global.screen.get_active_workspace() : null;
let activeWorkspace = workspaceManager.get_active_workspace();
let indicatorWorkspace = !this._animatingIndicator ? activeWorkspace : null;
let indicatorThemeNode = this._indicator.get_theme_node();
let indicatorTopFullBorder = indicatorThemeNode.get_padding(St.Side.TOP) + indicatorThemeNode.get_border_width(St.Side.TOP);
@ -1318,7 +1343,8 @@ var ThumbnailsBox = new Lang.Class({
_activeWorkspaceChanged(wm, from, to, direction) {
let thumbnail;
let activeWorkspace = global.screen.get_active_workspace();
let workspaceManager = global.workspace_manager;
let activeWorkspace = workspaceManager.get_active_workspace();
for (let i = 0; i < this._thumbnails.length; i++) {
if (this._thumbnails[i].metaWorkspace == activeWorkspace) {
thumbnail = this._thumbnails[i];

View File

@ -91,25 +91,29 @@ var WorkspacesView = new Lang.Class({
Extends: WorkspacesViewBase,
_init(monitorIndex) {
let workspaceManager = global.workspace_manager;
this.parent(monitorIndex);
this._animating = false; // tweening
this._scrolling = false; // swipe-scrolling
this._animatingScroll = false; // programatically updating the adjustment
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
let activeWorkspaceIndex = workspaceManager.get_active_workspace_index();
this.scrollAdjustment = new St.Adjustment({ value: activeWorkspaceIndex,
lower: 0,
page_increment: 1,
page_size: 1,
step_increment: 0,
upper: global.screen.n_workspaces });
upper: workspaceManager.n_workspaces });
this.scrollAdjustment.connect('notify::value',
this._onScroll.bind(this));
this._workspaces = [];
this._updateWorkspaces();
this._updateWorkspacesId = global.screen.connect('notify::n-workspaces', this._updateWorkspaces.bind(this));
this._updateWorkspacesId =
workspaceManager.connect('notify::n-workspaces',
this._updateWorkspaces.bind(this));
this._overviewShownId =
Main.overview.connect('shown', () => {
@ -138,7 +142,8 @@ var WorkspacesView = new Lang.Class({
},
getActiveWorkspace() {
let active = global.screen.get_active_workspace_index();
let workspaceManager = global.workspace_manager;
let active = workspaceManager.get_active_workspace_index();
return this._workspaces[active];
},
@ -169,7 +174,8 @@ var WorkspacesView = new Lang.Class({
},
_scrollToActive() {
let active = global.screen.get_active_workspace_index();
let workspaceManager = global.workspace_manager;
let active = workspaceManager.get_active_workspace_index();
this._updateWorkspaceActors(true);
this._updateScrollAdjustment(active);
@ -178,7 +184,8 @@ var WorkspacesView = new Lang.Class({
// Update workspace actors parameters
// @showAnimation: iff %true, transition between states
_updateWorkspaceActors(showAnimation) {
let active = global.screen.get_active_workspace_index();
let workspaceManager = global.workspace_manager;
let active = workspaceManager.get_active_workspace_index();
this._animating = showAnimation;
@ -214,7 +221,8 @@ var WorkspacesView = new Lang.Class({
},
_updateVisibility() {
let active = global.screen.get_active_workspace_index();
let workspaceManager = global.workspace_manager;
let active = workspaceManager.get_active_workspace_index();
for (let w = 0; w < this._workspaces.length; w++) {
let workspace = this._workspaces[w];
@ -246,13 +254,14 @@ var WorkspacesView = new Lang.Class({
},
_updateWorkspaces() {
let newNumWorkspaces = global.screen.n_workspaces;
let workspaceManager = global.workspace_manager;
let newNumWorkspaces = workspaceManager.n_workspaces;
this.scrollAdjustment.upper = newNumWorkspaces;
let needsUpdate = false;
for (let j = 0; j < newNumWorkspaces; j++) {
let metaWorkspace = global.screen.get_workspace_by_index(j);
let metaWorkspace = workspaceManager.get_workspace_by_index(j);
let workspace;
if (j >= this._workspaces.length) { /* added */
@ -290,7 +299,8 @@ var WorkspacesView = new Lang.Class({
this.scrollAdjustment.run_dispose();
Main.overview.disconnect(this._overviewShownId);
global.window_manager.disconnect(this._switchWorkspaceNotifyId);
global.screen.disconnect(this._updateWorkspacesId);
let workspaceManager = global.workspace_manager;
workspaceManager.disconnect(this._updateWorkspacesId);
},
startSwipeScroll() {
@ -311,7 +321,8 @@ var WorkspacesView = new Lang.Class({
if (this._animatingScroll)
return;
let active = global.screen.get_active_workspace_index();
let workspaceManager = global.workspace_manager;
let active = workspaceManager.get_active_workspace_index();
let current = Math.round(adj.value);
if (active != current) {
@ -593,7 +604,7 @@ var WorkspacesDisplay = new Lang.Class({
_getMonitorIndexForEvent(event) {
let [x, y] = event.get_coords();
let rect = new Meta.Rectangle({ x: x, y: y, width: 1, height: 1 });
return global.screen.get_monitor_index_for_rect(rect);
return global.display.get_monitor_index_for_rect(rect);
},
_getPrimaryView() {
@ -679,7 +690,8 @@ var WorkspacesDisplay = new Lang.Class({
this._getMonitorIndexForEvent(event) != this._primaryIndex)
return Clutter.EVENT_PROPAGATE;
let activeWs = global.screen.get_active_workspace();
let workspaceManager = global.workspace_manager;
let activeWs = workspaceManager.get_active_workspace();
let ws;
switch (event.get_scroll_direction()) {
case Clutter.ScrollDirection.UP:
@ -698,7 +710,8 @@ var WorkspacesDisplay = new Lang.Class({
_onKeyPressEvent(actor, event) {
if (!this.actor.mapped)
return Clutter.EVENT_PROPAGATE;
let activeWs = global.screen.get_active_workspace();
let workspaceManager = global.workspace_manager;
let activeWs = workspaceManager.get_active_workspace();
let ws;
switch (event.get_key_symbol()) {
case Clutter.KEY_Page_Up:

View File

@ -1,12 +1,12 @@
project('gnome-shell', 'c',
version: '3.29.1',
version: '3.29.4',
meson_version: '>= 0.42.0',
license: 'GPLv2+'
)
# We depend on a specific version of the libmutter API. The mutter variants of
# the Cogl and Clutter libraries also use this API version.
mutter_api_version = '2'
mutter_api_version = '3'
clutter_pc = 'mutter-clutter-' + mutter_api_version
cogl_pc = 'mutter-cogl-' + mutter_api_version
@ -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.29.4'
polkit_req = '>= 0.100'
schemas_req = '>= 3.21.3'
startup_req = '>= 0.11'
@ -59,6 +59,13 @@ servicedir = join_paths(datadir, 'dbus-1', 'services')
plugindir = get_variable('BROWSER_PLUGIN_DIR', mozplugindir)
# XXX: Once https://github.com/systemd/systemd/issues/9595 is fixed and we can
# depend on this version, replace with something like:
# systemduserunitdir = systemd_dep.get_pkgconfig_variable('systemduserunitdir',
# define_variable: ['prefix', prefix])
# and uncomment systemd_dep below
systemduserunitdir = join_paths(libdir, 'systemd', 'user')
keybindings_dep = dependency('gnome-keybindings', required: false)
if keybindings_dep.found()
keysdir = keybindings_dep.get_pkgconfig_variable('keysdir')
@ -117,10 +124,12 @@ else
endif
if get_option('systemd')
systemd_dep = dependency('libsystemd')
have_systemd = systemd_dep.found()
libsystemd_dep = dependency('libsystemd')
# XXX: see systemduserunitdir
# systemd_dep = dependency('systemd')
have_systemd = true
else
systemd_dep = []
libsystemd_dep = []
have_systemd = false
endif

View File

@ -10,7 +10,7 @@ msgid ""
msgstr ""
"Project-Id-Version: HEAD\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-shell/issues\n"
"POT-Creation-Date: 2018-03-10 12:32+0000\n"
"POT-Creation-Date: 2018-04-13 19:54+0000\n"
"PO-Revision-Date: 2018-03-10 21:24+0100\n"
"Last-Translator: Robert Antoni Buj Gelonch <rbuj@fedoraproject.org>\n"
"Language-Team: Catalan <tradgnome@softcatala.org>\n"
@ -349,7 +349,7 @@ msgid "There was an error loading the preferences dialog for %s:"
msgstr "S'ha produït un error en carregar el diàleg de preferències de %s:"
#: js/gdm/authPrompt.js:147 js/ui/audioDeviceSelection.js:71
#: js/ui/components/networkAgent.js:117 js/ui/components/polkitAgent.js:148
#: js/ui/components/networkAgent.js:117 js/ui/components/polkitAgent.js:153
#: js/ui/endSessionDialog.js:482 js/ui/extensionDownloader.js:197
#: js/ui/shellMountOperation.js:343 js/ui/status/network.js:919
msgid "Cancel"
@ -669,12 +669,12 @@ msgstr "Afegeix als preferits"
msgid "Show Details"
msgstr "Mostra els detalls"
#: js/ui/appFavorites.js:138
#: js/ui/appFavorites.js:140
#, javascript-format
msgid "%s has been added to your favorites."
msgstr "S'ha afegit %s als preferits."
#: js/ui/appFavorites.js:172
#: js/ui/appFavorites.js:174
#, javascript-format
msgid "%s has been removed from your favorites."
msgstr "S'ha suprimit %s dels preferits."
@ -869,7 +869,7 @@ msgstr "S'ha desconnectat un dispositiu extern"
msgid "Open with %s"
msgstr "Obre amb %s"
#: js/ui/components/keyring.js:107 js/ui/components/polkitAgent.js:284
#: js/ui/components/keyring.js:107 js/ui/components/polkitAgent.js:295
msgid "Password:"
msgstr "Contrasenya:"
@ -957,15 +957,15 @@ msgstr "Cal introduir una contrasenya per connectar-vos a «%s»."
msgid "Network Manager"
msgstr "Gestor de connexions de xarxa"
#: js/ui/components/polkitAgent.js:43
#: js/ui/components/polkitAgent.js:48
msgid "Authentication Required"
msgstr "Cal autenticació"
#: js/ui/components/polkitAgent.js:71
#: js/ui/components/polkitAgent.js:76
msgid "Administrator"
msgstr "Administrador"
#: js/ui/components/polkitAgent.js:151
#: js/ui/components/polkitAgent.js:156
msgid "Authenticate"
msgstr "Autentica"
@ -973,7 +973,7 @@ msgstr "Autentica"
#. * requested authentication was not gained; this can happen
#. * because of an authentication error (like invalid password),
#. * for instance.
#: js/ui/components/polkitAgent.js:270 js/ui/shellMountOperation.js:327
#: js/ui/components/polkitAgent.js:281 js/ui/shellMountOperation.js:327
msgid "Sorry, that didnt work. Please try again."
msgstr "No ha funcionat. Torneu-ho a provar."
@ -1021,7 +1021,7 @@ msgstr "Afegeix rellotges del món…"
msgid "World Clocks"
msgstr "Rellotges del món"
#: js/ui/dateMenu.js:225
#: js/ui/dateMenu.js:227
msgid "Weather"
msgstr "El temps"
@ -1029,7 +1029,7 @@ msgstr "El temps"
#. 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:289
#: js/ui/dateMenu.js:291
#, javascript-format
msgid "%s all day."
msgstr "%s tot el dia."
@ -1038,7 +1038,7 @@ msgstr "%s tot el dia."
#. 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:295
#: js/ui/dateMenu.js:297
#, javascript-format
msgid "%s, then %s later."
msgstr "%s, llavors %s més tard."
@ -1047,30 +1047,30 @@ msgstr "%s, llavors %s més tard."
#. 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:301
#: js/ui/dateMenu.js:303
#, javascript-format
msgid "%s, then %s, followed by %s later."
msgstr "%s, llavors %s, seguit per %s més tard."
#: js/ui/dateMenu.js:312
#: js/ui/dateMenu.js:314
msgid "Select a location…"
msgstr "Trieu una ubicació…"
#: js/ui/dateMenu.js:315
#: js/ui/dateMenu.js:317
msgid "Loading…"
msgstr "S'està carregant…"
#. Translators: %s is a temperature with unit, e.g. "23℃"
#: js/ui/dateMenu.js:321
#: js/ui/dateMenu.js:323
#, javascript-format
msgid "Feels like %s."
msgstr "Sensació tèrmica de %s."
#: js/ui/dateMenu.js:324
#: js/ui/dateMenu.js:326
msgid "Go online for weather information"
msgstr "Vés en línia per a informació sobre el temps"
#: js/ui/dateMenu.js:326
#: js/ui/dateMenu.js:328
msgid "Weather information is currently unavailable"
msgstr "La informació sobre el temps no està disponible"
@ -1990,16 +1990,17 @@ msgid ""
"New device has been detected while you were away. Please disconnect and "
"reconnect the device to start using it."
msgstr ""
"El nou dispositiu s'ha detectat mentre estàveu absents. Desconnecteu i torneu a connectar el dispositiu per a començar a utilitzar-lo."
"El nou dispositiu s'ha detectat mentre estàveu absents. Desconnecteu i "
"torneu a connectar el dispositiu per a començar a utilitzar-lo."
#: js/ui/status/thunderbolt.js:356
msgid "Thunderbolt authorization error"
msgstr "S'ha produït un error d'autorització a Thunderbolt"
#: js/ui/status/thunderbolt.js:357
#, javascript-format
msgid "Could not authorize the thunderbolt device: %s"
msgstr "No s'ha pogut autoritzar el dispositiu thunderbolt: %s"
#, javascript-format
msgid "Could not authorize the Thunderbolt device: %s"
msgstr "No s'ha pogut autoritzar el dispositiu Thunderbolt: %s"
#: js/ui/status/volume.js:128
msgid "Volume changed"

757
po/gd.po

File diff suppressed because it is too large Load Diff

418
po/gl.po

File diff suppressed because it is too large Load Diff

368
po/id.po

File diff suppressed because it is too large Load Diff

1589
po/oc.po

File diff suppressed because it is too large Load Diff

View File

@ -12,14 +12,14 @@
# Valery Kirichenko <valera5505@gmail.com>, 2014.
# Yuri Myasoedov <ymyasoedov@yandex.ru>, 2012, 2013, 2014.
# Ivan Komaritsyn <vantu5z@mail.ru>, 2015.
# Stas Solovey <whats_up@tut.by>, 2011, 2013, 2014, 2015, 2016, 2017.
# Stas Solovey <whats_up@tut.by>, 2011, 2013, 2014, 2015, 2016, 2017, 2018.
#
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 18:31+0000\n"
"PO-Revision-Date: 2018-04-19 23:31+0300\n"
"POT-Creation-Date: 2018-04-19 20:33+0000\n"
"PO-Revision-Date: 2018-07-17 00:25+0300\n"
"Last-Translator: Stas Solovey <whats_up@tut.by>\n"
"Language-Team: Русский <gnome-cyr@gnome.org>\n"
"Language: ru\n"
@ -28,7 +28,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
"X-Generator: Poedit 2.0.6\n"
"X-Generator: Poedit 2.0.9\n"
#: data/50-gnome-shell-system.xml:6
msgid "System"
@ -364,20 +364,20 @@ msgctxt "button"
msgid "Sign In"
msgstr "Войти"
#: js/gdm/loginDialog.js:315
#: js/gdm/loginDialog.js:319
msgid "Choose Session"
msgstr "Выбрать сеанс"
#. translators: this message is shown below the user list on the
#. login screen. It can be activated to reveal an entry for
#. manually entering the username.
#: js/gdm/loginDialog.js:458
#: js/gdm/loginDialog.js:462
msgid "Not listed?"
msgstr "Нет в списке?"
#. Translators: this message is shown below the username entry field
#. to clue the user in on how to login to the local network realm
#: js/gdm/loginDialog.js:887
#: js/gdm/loginDialog.js:891
#, javascript-format
msgid "(e.g., user or %s)"
msgstr "(например, пользователь или %s)"
@ -385,12 +385,12 @@ msgstr "(например, пользователь или %s)"
#. TTLS and PEAP are actually much more complicated, but this complication
#. is not visible here since we only care about phase2 authentication
#. (and don't even care of which one)
#: js/gdm/loginDialog.js:892 js/ui/components/networkAgent.js:243
#: js/gdm/loginDialog.js:896 js/ui/components/networkAgent.js:243
#: js/ui/components/networkAgent.js:261
msgid "Username: "
msgstr "Имя пользователя: "
#: js/gdm/loginDialog.js:1228
#: js/gdm/loginDialog.js:1234
msgid "Login Window"
msgstr "Окно входа в систему"
@ -2053,7 +2053,7 @@ msgstr "Ошибка авторизации Thunderbolt"
#: js/ui/status/thunderbolt.js:357
#, javascript-format
msgid "Could not authorize the thunderbolt device: %s"
msgid "Could not authorize the Thunderbolt device: %s"
msgstr "Не удалось авторизовать устройство Thunderbolt: %s"
#: js/ui/status/volume.js:128

View File

@ -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-02-21 14:13+0000\n"
"PO-Revision-Date: 2018-02-22 15:56+0100\n"
"POT-Creation-Date: 2018-04-13 19:54+0000\n"
"PO-Revision-Date: 2018-05-20 19:24+0200\n"
"Last-Translator: Anders Jonsson <anders.jonsson@norsjovallen.se>\n"
"Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
"Language: sv\n"
@ -20,7 +20,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 2.0.6\n"
"X-Generator: Poedit 2.0.7\n"
#: data/50-gnome-shell-system.xml:6
msgid "System"
@ -332,7 +332,7 @@ msgid "There was an error loading the preferences dialog for %s:"
msgstr "Det uppstod ett fel vid inläsning av inställningsdialogen för %s:"
#: js/gdm/authPrompt.js:147 js/ui/audioDeviceSelection.js:71
#: js/ui/components/networkAgent.js:117 js/ui/components/polkitAgent.js:148
#: js/ui/components/networkAgent.js:117 js/ui/components/polkitAgent.js:153
#: js/ui/endSessionDialog.js:482 js/ui/extensionDownloader.js:197
#: js/ui/shellMountOperation.js:343 js/ui/status/network.js:919
msgid "Cancel"
@ -652,12 +652,12 @@ msgstr "Lägg till som favorit"
msgid "Show Details"
msgstr "Visa detaljer"
#: js/ui/appFavorites.js:138
#: js/ui/appFavorites.js:140
#, javascript-format
msgid "%s has been added to your favorites."
msgstr "%s har lagts till i dina favoriter."
#: js/ui/appFavorites.js:172
#: js/ui/appFavorites.js:174
#, javascript-format
msgid "%s has been removed from your favorites."
msgstr "%s har tagits bort från dina favoriter."
@ -852,7 +852,7 @@ msgstr "Extern disk frånkopplad"
msgid "Open with %s"
msgstr "Öppna med %s"
#: js/ui/components/keyring.js:107 js/ui/components/polkitAgent.js:284
#: js/ui/components/keyring.js:107 js/ui/components/polkitAgent.js:295
msgid "Password:"
msgstr "Lösenord:"
@ -940,15 +940,15 @@ msgstr "Ett lösenord krävs för att ansluta till ”%s”."
msgid "Network Manager"
msgstr "Nätverkshanterare"
#: js/ui/components/polkitAgent.js:43
#: js/ui/components/polkitAgent.js:48
msgid "Authentication Required"
msgstr "Autentisering krävs"
#: js/ui/components/polkitAgent.js:71
#: js/ui/components/polkitAgent.js:76
msgid "Administrator"
msgstr "Administratör"
#: js/ui/components/polkitAgent.js:151
#: js/ui/components/polkitAgent.js:156
msgid "Authenticate"
msgstr "Autentisera"
@ -956,7 +956,7 @@ msgstr "Autentisera"
#. * requested authentication was not gained; this can happen
#. * because of an authentication error (like invalid password),
#. * for instance.
#: js/ui/components/polkitAgent.js:270 js/ui/shellMountOperation.js:327
#: js/ui/components/polkitAgent.js:281 js/ui/shellMountOperation.js:327
msgid "Sorry, that didnt work. Please try again."
msgstr "Tyvärr, det fungerade inte. Försök igen."
@ -1004,7 +1004,7 @@ msgstr "Lägg till världsklockor…"
msgid "World Clocks"
msgstr "Världsklockor"
#: js/ui/dateMenu.js:225
#: js/ui/dateMenu.js:227
msgid "Weather"
msgstr "Väder"
@ -1012,7 +1012,7 @@ msgstr "Väder"
#. 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:289
#: js/ui/dateMenu.js:291
#, javascript-format
msgid "%s all day."
msgstr "%s hela dagen."
@ -1021,7 +1021,7 @@ msgstr "%s hela dagen."
#. 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:295
#: js/ui/dateMenu.js:297
#, javascript-format
msgid "%s, then %s later."
msgstr "%s, sedan %s senare."
@ -1030,30 +1030,30 @@ msgstr "%s, sedan %s senare."
#. 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:301
#: js/ui/dateMenu.js:303
#, javascript-format
msgid "%s, then %s, followed by %s later."
msgstr "%s, sedan %s, följt av %s senare."
#: js/ui/dateMenu.js:312
#: js/ui/dateMenu.js:314
msgid "Select a location…"
msgstr "Välj en plats…"
#: js/ui/dateMenu.js:315
#: js/ui/dateMenu.js:317
msgid "Loading…"
msgstr "Läser in…"
#. Translators: %s is a temperature with unit, e.g. "23℃"
#: js/ui/dateMenu.js:321
#: js/ui/dateMenu.js:323
#, javascript-format
msgid "Feels like %s."
msgstr "Känns som %s."
#: js/ui/dateMenu.js:324
#: js/ui/dateMenu.js:326
msgid "Go online for weather information"
msgstr "Anslut till nätet för väderinformation"
#: js/ui/dateMenu.js:326
#: js/ui/dateMenu.js:328
msgid "Weather information is currently unavailable"
msgstr "Väderinformation är för närvarande inte tillgänglig"
@ -1953,16 +1953,16 @@ msgstr "Vänteläge"
msgid "Power Off"
msgstr "Stäng av"
#: js/ui/status/thunderbolt.js:272
#: js/ui/status/thunderbolt.js:294
msgid "Thunderbolt"
msgstr "Thunderbolt"
#. we are done
#: js/ui/status/thunderbolt.js:328
#: js/ui/status/thunderbolt.js:350
msgid "Unknown Thunderbolt device"
msgstr "Okänd Thunderbolt-enhet"
#: js/ui/status/thunderbolt.js:329
#: js/ui/status/thunderbolt.js:351
msgid ""
"New device has been detected while you were away. Please disconnect and "
"reconnect the device to start using it."
@ -1970,13 +1970,13 @@ msgstr ""
"En ny enhet har upptäckts medan du var borta. Koppla från och anslut enheten "
"igen för att börja använda den."
#: js/ui/status/thunderbolt.js:334
#: js/ui/status/thunderbolt.js:356
msgid "Thunderbolt authorization error"
msgstr "Thunderbolt-auktoriseringsfel"
#: js/ui/status/thunderbolt.js:335
#: js/ui/status/thunderbolt.js:357
#, javascript-format
msgid "Could not authorize the thunderbolt device: %s"
msgid "Could not authorize the Thunderbolt device: %s"
msgstr "Kunde inte auktorisera Thunderbolt-enheten: %s"
#: js/ui/status/volume.js:128

View File

@ -23,16 +23,16 @@ 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-03-05 21:11+0000\n"
"PO-Revision-Date: 2018-02-15 01:42+0800\n"
"Last-Translator: Dingzhong Chen <wsxy162@gmail.com>\n"
"POT-Creation-Date: 2018-04-13 19:54+0000\n"
"PO-Revision-Date: 2018-05-10 12:11-0500\n"
"Last-Translator: Mingcong Bai <jeffbai@aosc.xyz>\n"
"Language-Team: Chinese (simplified) <i18n-zh@googlegroups.com>\n"
"Language: zh_CN\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Gtranslator 2.91.7\n"
"X-Generator: Poedit 2.0.6\n"
#: data/50-gnome-shell-system.xml:6
msgid "System"
@ -320,7 +320,7 @@ msgid "There was an error loading the preferences dialog for %s:"
msgstr "载入 %s 的首选项对话框时出错:"
#: js/gdm/authPrompt.js:147 js/ui/audioDeviceSelection.js:71
#: js/ui/components/networkAgent.js:117 js/ui/components/polkitAgent.js:148
#: js/ui/components/networkAgent.js:117 js/ui/components/polkitAgent.js:153
#: js/ui/endSessionDialog.js:482 js/ui/extensionDownloader.js:197
#: js/ui/shellMountOperation.js:343 js/ui/status/network.js:919
msgid "Cancel"
@ -631,12 +631,12 @@ msgstr "添加到收藏夹"
msgid "Show Details"
msgstr "显示细节"
#: js/ui/appFavorites.js:138
#: js/ui/appFavorites.js:140
#, javascript-format
msgid "%s has been added to your favorites."
msgstr "%s 已经添加到了您的收藏夹。"
#: js/ui/appFavorites.js:172
#: js/ui/appFavorites.js:174
#, javascript-format
msgid "%s has been removed from your favorites."
msgstr "%s 已经从您的收藏夹移除。"
@ -829,7 +829,7 @@ msgstr "外部驱动器已断开"
msgid "Open with %s"
msgstr "使用 %s 打开"
#: js/ui/components/keyring.js:107 js/ui/components/polkitAgent.js:284
#: js/ui/components/keyring.js:107 js/ui/components/polkitAgent.js:295
msgid "Password:"
msgstr "密码:"
@ -915,15 +915,15 @@ msgstr "连接到“%s”需要密码。"
msgid "Network Manager"
msgstr "网络管理器"
#: js/ui/components/polkitAgent.js:43
#: js/ui/components/polkitAgent.js:48
msgid "Authentication Required"
msgstr "需要认证"
#: js/ui/components/polkitAgent.js:71
#: js/ui/components/polkitAgent.js:76
msgid "Administrator"
msgstr "管理员"
#: js/ui/components/polkitAgent.js:151
#: js/ui/components/polkitAgent.js:156
msgid "Authenticate"
msgstr "认证"
@ -932,7 +932,7 @@ msgstr "认证"
#. * requested authentication was not gained; this can happen
#. * because of an authentication error (like invalid password),
#. * for instance.
#: js/ui/components/polkitAgent.js:270 js/ui/shellMountOperation.js:327
#: js/ui/components/polkitAgent.js:281 js/ui/shellMountOperation.js:327
msgid "Sorry, that didnt work. Please try again."
msgstr "抱歉,认证失败。请重试。"
@ -980,7 +980,7 @@ msgstr "添加世界时钟…"
msgid "World Clocks"
msgstr "世界时钟"
#: js/ui/dateMenu.js:225
#: js/ui/dateMenu.js:227
msgid "Weather"
msgstr "天气"
@ -988,7 +988,7 @@ msgstr "天气"
#. 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:289
#: js/ui/dateMenu.js:291
#, javascript-format
msgid "%s all day."
msgstr "全天%s。"
@ -997,7 +997,7 @@ msgstr "全天%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:295
#: js/ui/dateMenu.js:297
#, javascript-format
msgid "%s, then %s later."
msgstr "%s转%s。"
@ -1006,30 +1006,30 @@ msgstr "%s转%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:301
#: js/ui/dateMenu.js:303
#, javascript-format
msgid "%s, then %s, followed by %s later."
msgstr "%s转%s随后转%s。"
#: js/ui/dateMenu.js:312
#: js/ui/dateMenu.js:314
msgid "Select a location…"
msgstr "选择地点…"
#: js/ui/dateMenu.js:315
#: js/ui/dateMenu.js:317
msgid "Loading…"
msgstr "正在载入…"
#. Translators: %s is a temperature with unit, e.g. "23℃"
#: js/ui/dateMenu.js:321
#: js/ui/dateMenu.js:323
#, javascript-format
msgid "Feels like %s."
msgstr "体感温度 %s。"
#: js/ui/dateMenu.js:324
#: js/ui/dateMenu.js:326
msgid "Go online for weather information"
msgstr "通过互联网查看天气信息"
#: js/ui/dateMenu.js:326
#: js/ui/dateMenu.js:328
msgid "Weather information is currently unavailable"
msgstr "天气信息目前不可用"
@ -1930,7 +1930,7 @@ msgstr "Thunderbolt 授权错误"
#: js/ui/status/thunderbolt.js:357
#, javascript-format
msgid "Could not authorize the thunderbolt device: %s"
msgid "Could not authorize the Thunderbolt device: %s"
msgstr "无法授权 Thunderbolt 设备:%s"
#: js/ui/status/volume.js:128

View File

@ -8,8 +8,8 @@ msgid ""
msgstr ""
"Project-Id-Version: gnome-shell 3.3.90\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-shell/issues\n"
"POT-Creation-Date: 2018-03-05 21:11+0000\n"
"PO-Revision-Date: 2018-03-10 20:30+0800\n"
"POT-Creation-Date: 2018-06-08 17:30+0000\n"
"PO-Revision-Date: 2018-06-09 11:17+0800\n"
"Last-Translator: Chao-Hsiung Liao <j_h_liau@yahoo.com.tw>\n"
"Language-Team: Chinese (Taiwan) <zh-l10n@lists.linux.org.tw>\n"
"Language: zh_TW\n"
@ -17,7 +17,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Poedit 2.0.6\n"
"X-Generator: Poedit 2.0.8\n"
#: data/50-gnome-shell-system.xml:6
msgid "System"
@ -308,7 +308,7 @@ msgid "There was an error loading the preferences dialog for %s:"
msgstr "載入 %s 的偏好設定對話盒時發生錯誤:"
#: js/gdm/authPrompt.js:147 js/ui/audioDeviceSelection.js:71
#: js/ui/components/networkAgent.js:117 js/ui/components/polkitAgent.js:148
#: js/ui/components/networkAgent.js:117 js/ui/components/polkitAgent.js:153
#: js/ui/endSessionDialog.js:482 js/ui/extensionDownloader.js:197
#: js/ui/shellMountOperation.js:343 js/ui/status/network.js:919
msgid "Cancel"
@ -328,20 +328,20 @@ msgctxt "button"
msgid "Sign In"
msgstr "登入"
#: js/gdm/loginDialog.js:315
#: js/gdm/loginDialog.js:319
msgid "Choose Session"
msgstr "選擇工作階段"
#. translators: this message is shown below the user list on the
#. login screen. It can be activated to reveal an entry for
#. manually entering the username.
#: js/gdm/loginDialog.js:458
#: js/gdm/loginDialog.js:462
msgid "Not listed?"
msgstr "沒有列出來?"
#. Translators: this message is shown below the username entry field
#. to clue the user in on how to login to the local network realm
#: js/gdm/loginDialog.js:887
#: js/gdm/loginDialog.js:891
#, javascript-format
msgid "(e.g., user or %s)"
msgstr "(例如: user 或 %s)"
@ -349,12 +349,12 @@ msgstr "(例如: user 或 %s)"
#. TTLS and PEAP are actually much more complicated, but this complication
#. is not visible here since we only care about phase2 authentication
#. (and don't even care of which one)
#: js/gdm/loginDialog.js:892 js/ui/components/networkAgent.js:243
#: js/gdm/loginDialog.js:896 js/ui/components/networkAgent.js:243
#: js/ui/components/networkAgent.js:261
msgid "Username: "
msgstr "使用者名稱:"
#: js/gdm/loginDialog.js:1228
#: js/gdm/loginDialog.js:1234
msgid "Login Window"
msgstr "登入視窗"
@ -601,32 +601,32 @@ msgstr "常用"
msgid "All"
msgstr "全部"
#: js/ui/appDisplay.js:1886
#: js/ui/appDisplay.js:1889
msgid "New Window"
msgstr "新視窗"
#: js/ui/appDisplay.js:1900
#: js/ui/appDisplay.js:1903
msgid "Launch using Dedicated Graphics Card"
msgstr "使用獨立顯卡啟動"
#: js/ui/appDisplay.js:1927 js/ui/dash.js:285
#: js/ui/appDisplay.js:1930 js/ui/dash.js:285
msgid "Remove from Favorites"
msgstr "自喜好中移除"
#: js/ui/appDisplay.js:1933
#: js/ui/appDisplay.js:1936
msgid "Add to Favorites"
msgstr "加入喜好"
#: js/ui/appDisplay.js:1943
#: js/ui/appDisplay.js:1946
msgid "Show Details"
msgstr "顯示詳細資訊"
#: js/ui/appFavorites.js:138
#: js/ui/appFavorites.js:140
#, javascript-format
msgid "%s has been added to your favorites."
msgstr "%s 已加入您的喜好中。"
#: js/ui/appFavorites.js:172
#: js/ui/appFavorites.js:174
#, javascript-format
msgid "%s has been removed from your favorites."
msgstr "%s 已經從您的喜好中移除。"
@ -787,22 +787,22 @@ msgid "Clear All"
msgstr "全部清除"
#. Translators: %s is an application name
#: js/ui/closeDialog.js:44
#: js/ui/closeDialog.js:47
#, javascript-format
msgid "“%s” is not responding."
msgstr "「%s」沒有回應。"
#: js/ui/closeDialog.js:45
#: js/ui/closeDialog.js:48
msgid ""
"You may choose to wait a short while for it to continue or force the "
"application to quit entirely."
msgstr "您可以選擇再等一下讓它繼續,或是強制讓應用程式立刻退出。"
#: js/ui/closeDialog.js:61
#: js/ui/closeDialog.js:64
msgid "Force Quit"
msgstr "強制退出"
#: js/ui/closeDialog.js:64
#: js/ui/closeDialog.js:67
msgid "Wait"
msgstr "等待"
@ -819,7 +819,7 @@ msgstr "外部裝置已拔除"
msgid "Open with %s"
msgstr "用 %s 開啟"
#: js/ui/components/keyring.js:107 js/ui/components/polkitAgent.js:284
#: js/ui/components/keyring.js:107 js/ui/components/polkitAgent.js:297
msgid "Password:"
msgstr "密碼: "
@ -856,18 +856,18 @@ msgstr "私密金鑰密碼:"
msgid "Service: "
msgstr "服務:"
#: js/ui/components/networkAgent.js:292 js/ui/components/networkAgent.js:659
#: js/ui/components/networkAgent.js:292 js/ui/components/networkAgent.js:664
msgid "Authentication required by wireless network"
msgstr "無線網路所需要的核對"
#: js/ui/components/networkAgent.js:293 js/ui/components/networkAgent.js:660
#: js/ui/components/networkAgent.js:293 js/ui/components/networkAgent.js:665
#, javascript-format
msgid ""
"Passwords or encryption keys are required to access the wireless network "
"“%s”."
msgstr "需要密碼或是加密金鑰來存取無線網路「%s」。"
#: js/ui/components/networkAgent.js:297 js/ui/components/networkAgent.js:663
#: js/ui/components/networkAgent.js:297 js/ui/components/networkAgent.js:668
msgid "Wired 802.1X authentication"
msgstr "有線網路 802.1X 核對"
@ -875,15 +875,15 @@ msgstr "有線網路 802.1X 核對"
msgid "Network name: "
msgstr "網路名稱:"
#: js/ui/components/networkAgent.js:304 js/ui/components/networkAgent.js:667
#: js/ui/components/networkAgent.js:304 js/ui/components/networkAgent.js:672
msgid "DSL authentication"
msgstr "DSL 核對"
#: js/ui/components/networkAgent.js:311 js/ui/components/networkAgent.js:673
#: js/ui/components/networkAgent.js:311 js/ui/components/networkAgent.js:678
msgid "PIN code required"
msgstr "需要 PIN 碼"
#: js/ui/components/networkAgent.js:312 js/ui/components/networkAgent.js:674
#: js/ui/components/networkAgent.js:312 js/ui/components/networkAgent.js:679
msgid "PIN code is needed for the mobile broadband device"
msgstr "這個行動寬頻裝置需要 PIN 碼"
@ -891,29 +891,29 @@ msgstr "這個行動寬頻裝置需要 PIN 碼"
msgid "PIN: "
msgstr "PIN "
#: js/ui/components/networkAgent.js:320 js/ui/components/networkAgent.js:680
#: js/ui/components/networkAgent.js:320 js/ui/components/networkAgent.js:685
msgid "Mobile broadband network password"
msgstr "行動寬頻網路密碼"
#: js/ui/components/networkAgent.js:321 js/ui/components/networkAgent.js:664
#: js/ui/components/networkAgent.js:668 js/ui/components/networkAgent.js:681
#: js/ui/components/networkAgent.js:321 js/ui/components/networkAgent.js:669
#: js/ui/components/networkAgent.js:673 js/ui/components/networkAgent.js:686
#, javascript-format
msgid "A password is required to connect to “%s”."
msgstr "連線至「%s」需要密碼。"
#: js/ui/components/networkAgent.js:648 js/ui/status/network.js:1691
#: js/ui/components/networkAgent.js:653 js/ui/status/network.js:1704
msgid "Network Manager"
msgstr "網路管理員"
#: js/ui/components/polkitAgent.js:43
#: js/ui/components/polkitAgent.js:48
msgid "Authentication Required"
msgstr "要求核對"
#: js/ui/components/polkitAgent.js:71
#: js/ui/components/polkitAgent.js:76
msgid "Administrator"
msgstr "管理員"
#: js/ui/components/polkitAgent.js:151
#: js/ui/components/polkitAgent.js:156
msgid "Authenticate"
msgstr "核對"
@ -921,7 +921,7 @@ msgstr "核對"
#. * requested authentication was not gained; this can happen
#. * because of an authentication error (like invalid password),
#. * for instance.
#: js/ui/components/polkitAgent.js:270 js/ui/shellMountOperation.js:327
#: js/ui/components/polkitAgent.js:283 js/ui/shellMountOperation.js:327
msgid "Sorry, that didnt work. Please try again."
msgstr "抱歉,那沒有作用。請再試一次。"
@ -969,7 +969,7 @@ msgstr "加入世界時鐘…"
msgid "World Clocks"
msgstr "世界時鐘"
#: js/ui/dateMenu.js:225
#: js/ui/dateMenu.js:227
msgid "Weather"
msgstr "天氣"
@ -977,7 +977,7 @@ msgstr "天氣"
#. 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:289
#: js/ui/dateMenu.js:291
#, javascript-format
msgid "%s all day."
msgstr "全天%s。"
@ -986,7 +986,7 @@ msgstr "全天%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:295
#: js/ui/dateMenu.js:297
#, javascript-format
msgid "%s, then %s later."
msgstr "%s較晚%s。"
@ -995,30 +995,30 @@ msgstr "%s較晚%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:301
#: js/ui/dateMenu.js:303
#, javascript-format
msgid "%s, then %s, followed by %s later."
msgstr "%s然後%s接著較晚%s。"
#: js/ui/dateMenu.js:312
#: js/ui/dateMenu.js:314
msgid "Select a location…"
msgstr "選擇位置…"
#: js/ui/dateMenu.js:315
#: js/ui/dateMenu.js:317
msgid "Loading…"
msgstr "載入中…"
#. Translators: %s is a temperature with unit, e.g. "23℃"
#: js/ui/dateMenu.js:321
#: js/ui/dateMenu.js:323
#, javascript-format
msgid "Feels like %s."
msgstr "體感溫度 %s。"
#: js/ui/dateMenu.js:324
#: js/ui/dateMenu.js:326
msgid "Go online for weather information"
msgstr "上線以取得天氣資訊"
#: js/ui/dateMenu.js:326
#: js/ui/dateMenu.js:328
msgid "Weather information is currently unavailable"
msgstr "天氣資訊目前不可使用"
@ -1239,13 +1239,13 @@ msgid "Leave On"
msgstr "離開"
#: js/ui/kbdA11yDialog.js:59 js/ui/status/bluetooth.js:143
#: js/ui/status/network.js:1281
#: js/ui/status/network.js:1294
msgid "Turn On"
msgstr "開啟"
#: js/ui/kbdA11yDialog.js:67 js/ui/status/bluetooth.js:143
#: js/ui/status/network.js:154 js/ui/status/network.js:337
#: js/ui/status/network.js:1281 js/ui/status/network.js:1396
#: js/ui/status/network.js:1294 js/ui/status/network.js:1409
#: js/ui/status/nightLight.js:47 js/ui/status/rfkill.js:90
#: js/ui/status/rfkill.js:117
msgid "Turn Off"
@ -1307,7 +1307,7 @@ msgstr "檢示來源"
msgid "Web Page"
msgstr "網頁"
#: js/ui/messageTray.js:1493
#: js/ui/messageTray.js:1495
msgid "System Information"
msgstr "系統資訊"
@ -1622,7 +1622,7 @@ msgid "<unknown>"
msgstr "<不明>"
#. Translators: %s is a network identifier
#: js/ui/status/network.js:441 js/ui/status/network.js:1310
#: js/ui/status/network.js:441 js/ui/status/network.js:1323
#, javascript-format
msgid "%s Off"
msgstr "%s 關閉"
@ -1648,7 +1648,7 @@ msgid "%s Disconnecting"
msgstr "%s 正在斷線"
#. Translators: %s is a network identifier
#: js/ui/status/network.js:459 js/ui/status/network.js:1302
#: js/ui/status/network.js:459 js/ui/status/network.js:1315
#, javascript-format
msgid "%s Connecting"
msgstr "正連線到 %s"
@ -1688,7 +1688,7 @@ msgid "Mobile Broadband Settings"
msgstr "行動寬頻設定值"
#. Translators: %s is a network identifier
#: js/ui/status/network.js:578 js/ui/status/network.js:1307
#: js/ui/status/network.js:578 js/ui/status/network.js:1320
#, javascript-format
msgid "%s Hardware Disabled"
msgstr "%s 硬體已停用"
@ -1744,78 +1744,78 @@ msgstr "沒有網路"
msgid "Use hardware switch to turn off"
msgstr "使用硬體開關來關閉"
#: js/ui/status/network.js:1173
#: js/ui/status/network.js:1186
msgid "Select Network"
msgstr "選擇網路"
#: js/ui/status/network.js:1179
#: js/ui/status/network.js:1192
msgid "Wi-Fi Settings"
msgstr "Wi-Fi 設定值"
#. Translators: %s is a network identifier
#: js/ui/status/network.js:1298
#: js/ui/status/network.js:1311
#, javascript-format
msgid "%s Hotspot Active"
msgstr "%s 熱點有效"
#. Translators: %s is a network identifier
#: js/ui/status/network.js:1313
#: js/ui/status/network.js:1326
#, javascript-format
msgid "%s Not Connected"
msgstr "%s 未連線"
#: js/ui/status/network.js:1413
#: js/ui/status/network.js:1426
msgid "connecting…"
msgstr "連線中…"
#. Translators: this is for network connections that require some kind of key or password
#: js/ui/status/network.js:1416
#: js/ui/status/network.js:1429
msgid "authentication required"
msgstr "要求核對"
#: js/ui/status/network.js:1418
#: js/ui/status/network.js:1431
msgid "connection failed"
msgstr "連線失敗"
#: js/ui/status/network.js:1472
#: js/ui/status/network.js:1485
msgid "VPN Settings"
msgstr "VPN 設定值"
#: js/ui/status/network.js:1485
#: js/ui/status/network.js:1498
msgid "VPN"
msgstr "VPN"
#: js/ui/status/network.js:1495
#: js/ui/status/network.js:1508
msgid "VPN Off"
msgstr "VPN 關閉"
#: js/ui/status/network.js:1559 js/ui/status/rfkill.js:93
#: js/ui/status/network.js:1572 js/ui/status/rfkill.js:93
msgid "Network Settings"
msgstr "網路設定值"
#: js/ui/status/network.js:1588
#: js/ui/status/network.js:1601
#, javascript-format
msgid "%s Wired Connection"
msgid_plural "%s Wired Connections"
msgstr[0] "%s 個有線網路連線"
#: js/ui/status/network.js:1592
#: js/ui/status/network.js:1605
#, javascript-format
msgid "%s Wi-Fi Connection"
msgid_plural "%s Wi-Fi Connections"
msgstr[0] "%s 個 Wi-Fi 連線"
#: js/ui/status/network.js:1596
#: js/ui/status/network.js:1609
#, javascript-format
msgid "%s Modem Connection"
msgid_plural "%s Modem Connections"
msgstr[0] "%s 個數據機連線"
#: js/ui/status/network.js:1728
#: js/ui/status/network.js:1741
msgid "Connection failed"
msgstr "連線失敗"
#: js/ui/status/network.js:1729
#: js/ui/status/network.js:1742
msgid "Activation of network connection failed"
msgstr "啟動網路連線失敗"
@ -1918,7 +1918,7 @@ msgstr "Thunderbolt 授權錯誤"
#: js/ui/status/thunderbolt.js:357
#, javascript-format
msgid "Could not authorize the thunderbolt device: %s"
msgid "Could not authorize the Thunderbolt device: %s"
msgstr "無法授權該 Thunderbolt 裝置:%s"
#: js/ui/status/volume.js:128

View File

@ -167,22 +167,19 @@ gnome_shell_plugin_init (GnomeShellPlugin *shell_plugin)
static gboolean
gnome_shell_plugin_has_swap_event (GnomeShellPlugin *shell_plugin)
{
MetaPlugin *plugin = META_PLUGIN (shell_plugin);
CoglDisplay *cogl_display =
cogl_context_get_display (shell_plugin->cogl_context);
CoglRenderer *renderer = cogl_display_get_renderer (cogl_display);
const char * (* query_extensions_string) (Display *dpy, int screen);
Bool (* query_extension) (Display *dpy, int *error, int *event);
MetaScreen *screen;
Display *xdisplay;
int screen_number;
const char *glx_extensions;
/* We will only get swap events if Cogl is using GLX */
if (cogl_renderer_get_winsys_id (renderer) != COGL_WINSYS_ID_GLX)
return FALSE;
screen = meta_plugin_get_screen (plugin);
xdisplay = clutter_x11_get_default_display ();
query_extensions_string =
@ -194,9 +191,8 @@ gnome_shell_plugin_has_swap_event (GnomeShellPlugin *shell_plugin)
&shell_plugin->glx_error_base,
&shell_plugin->glx_event_base);
glx_extensions =
query_extensions_string (xdisplay,
meta_screen_get_screen_number (screen));
screen_number = XDefaultScreen (xdisplay);
glx_extensions = query_extensions_string (xdisplay, screen_number);
return strstr (glx_extensions, "GLX_INTEL_swap_event") != NULL;
}

View File

@ -53,7 +53,7 @@ gnome_shell_deps = [
canberra_dep, canberra_gtk_dep,
polkit_dep,
gcr_dep,
systemd_dep
libsystemd_dep
]
gnome_shell_deps += nm_deps

View File

@ -7,6 +7,8 @@
#include <glib/gi18n-lib.h>
#include <meta/display.h>
#include <meta/meta-workspace-manager.h>
#include <meta/meta-x11-display.h>
#include "shell-app-private.h"
#include "shell-enum-types.h"
@ -358,6 +360,17 @@ find_most_recent_transient_on_same_workspace (MetaDisplay *display,
return result;
}
static MetaWorkspace *
get_active_workspace (void)
{
ShellGlobal *global = shell_global_get ();
MetaDisplay *display = shell_global_get_display (global);
MetaWorkspaceManager *workspace_manager =
meta_display_get_workspace_manager (display);
return meta_workspace_manager_get_active_workspace (workspace_manager);
}
/**
* shell_app_activate_window:
* @app: a #ShellApp
@ -391,9 +404,8 @@ shell_app_activate_window (ShellApp *app,
{
GSList *windows_reversed, *iter;
ShellGlobal *global = shell_global_get ();
MetaScreen *screen = shell_global_get_screen (global);
MetaDisplay *display = meta_screen_get_display (screen);
MetaWorkspace *active = meta_screen_get_active_workspace (screen);
MetaDisplay *display = shell_global_get_display (global);
MetaWorkspace *active = get_active_workspace ();
MetaWorkspace *workspace = meta_window_get_workspace (window);
guint32 last_user_timestamp = meta_display_get_last_user_time (display);
MetaWindow *most_recent_transient;
@ -686,7 +698,7 @@ shell_app_get_windows (ShellApp *app)
{
CompareWindowsData data;
data.app = app;
data.active_workspace = meta_screen_get_active_workspace (shell_global_get_screen (shell_global_get ()));
data.active_workspace = get_active_workspace ();
app->running_state->windows = g_slist_sort_with_data (app->running_state->windows, shell_app_compare_windows, &data);
app->running_state->window_sort_stale = FALSE;
}
@ -922,11 +934,11 @@ shell_app_on_skip_taskbar_changed (MetaWindow *window,
}
static void
shell_app_on_ws_switch (MetaScreen *screen,
int from,
int to,
MetaMotionDirection direction,
gpointer data)
shell_app_on_ws_switch (MetaWorkspaceManager *workspace_manager,
int from,
int to,
MetaMotionDirection direction,
gpointer data)
{
ShellApp *app = SHELL_APP (data);
@ -1115,12 +1127,12 @@ _shell_app_handle_startup_sequence (ShellApp *app,
*/
if (starting && shell_app_get_state (app) == SHELL_APP_STATE_STOPPED)
{
MetaScreen *screen = shell_global_get_screen (shell_global_get ());
MetaDisplay *display = meta_screen_get_display (screen);
MetaDisplay *display = shell_global_get_display (shell_global_get ());
MetaX11Display *x11_display = meta_display_get_x11_display (display);
shell_app_state_transition (app, SHELL_APP_STATE_STARTING);
meta_display_focus_the_no_focus_window (display, screen,
sn_startup_sequence_get_timestamp (sequence));
meta_x11_display_focus_the_no_focus_window (x11_display,
sn_startup_sequence_get_timestamp (sequence));
app->started_on_workspace = sn_startup_sequence_get_workspace (sequence);
}
@ -1190,37 +1202,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 +1254,7 @@ shell_app_launch (ShellApp *app,
#else
NULL, NULL,
#endif
(GDesktopAppLaunchCallback) wait_pid,
app,
wait_pid, NULL,
error);
g_object_unref (context);
@ -1316,15 +1302,17 @@ shell_app_get_app_info (ShellApp *app)
static void
create_running_state (ShellApp *app)
{
MetaScreen *screen;
MetaDisplay *display = shell_global_get_display (shell_global_get ());
MetaWorkspaceManager *workspace_manager =
meta_display_get_workspace_manager (display);
g_assert (app->running_state == NULL);
screen = shell_global_get_screen (shell_global_get ());
app->running_state = g_slice_new0 (ShellAppRunningState);
app->running_state->refcount = 1;
app->running_state->workspace_switch_id =
g_signal_connect (screen, "workspace-switched", G_CALLBACK(shell_app_on_ws_switch), app);
g_signal_connect (workspace_manager, "workspace-switched",
G_CALLBACK (shell_app_on_ws_switch), app);
app->running_state->session = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
g_assert (app->running_state->session != NULL);
@ -1375,7 +1363,9 @@ shell_app_update_app_menu (ShellApp *app,
static void
unref_running_state (ShellAppRunningState *state)
{
MetaScreen *screen;
MetaDisplay *display = shell_global_get_display (shell_global_get ());
MetaWorkspaceManager *workspace_manager =
meta_display_get_workspace_manager (display);
g_assert (state->refcount > 0);
@ -1383,8 +1373,7 @@ unref_running_state (ShellAppRunningState *state)
if (state->refcount > 0)
return;
screen = shell_global_get_screen (shell_global_get ());
g_signal_handler_disconnect (screen, state->workspace_switch_id);
g_signal_handler_disconnect (workspace_manager, state->workspace_switch_id);
g_clear_object (&state->application_proxy);

View File

@ -28,6 +28,8 @@
#include <meta/meta-shaped-texture.h>
#include <meta/meta-cursor-tracker.h>
#include <meta/meta-settings.h>
#include <meta/meta-workspace-manager.h>
#include <meta/meta-x11-display.h>
#ifdef HAVE_SYSTEMD
#include <systemd/sd-journal.h>
@ -60,9 +62,10 @@ struct _ShellGlobal {
Window stage_xwindow;
MetaDisplay *meta_display;
MetaWorkspaceManager *workspace_manager;
GdkDisplay *gdk_display;
MetaX11Display *x11_display;
Display *xdisplay;
MetaScreen *meta_screen;
char *session_mode;
@ -96,8 +99,8 @@ enum {
PROP_0,
PROP_SESSION_MODE,
PROP_SCREEN,
PROP_DISPLAY,
PROP_WORKSPACE_MANAGER,
PROP_SCREEN_WIDTH,
PROP_SCREEN_HEIGHT,
PROP_STAGE,
@ -163,17 +166,17 @@ shell_global_get_property(GObject *object,
case PROP_SESSION_MODE:
g_value_set_string (value, shell_global_get_session_mode (global));
break;
case PROP_SCREEN:
g_value_set_object (value, global->meta_screen);
break;
case PROP_DISPLAY:
g_value_set_object (value, global->meta_display);
break;
case PROP_WORKSPACE_MANAGER:
g_value_set_object (value, global->workspace_manager);
break;
case PROP_SCREEN_WIDTH:
{
int width, height;
meta_screen_get_size (global->meta_screen, &width, &height);
meta_display_get_size (global->meta_display, &width, &height);
g_value_set_int (value, width);
}
break;
@ -181,7 +184,7 @@ shell_global_get_property(GObject *object,
{
int width, height;
meta_screen_get_size (global->meta_screen, &width, &height);
meta_display_get_size (global->meta_display, &width, &height);
g_value_set_int (value, height);
}
break;
@ -189,10 +192,10 @@ shell_global_get_property(GObject *object,
g_value_set_object (value, global->stage);
break;
case PROP_WINDOW_GROUP:
g_value_set_object (value, meta_get_window_group_for_screen (global->meta_screen));
g_value_set_object (value, meta_get_window_group_for_display (global->meta_display));
break;
case PROP_TOP_WINDOW_GROUP:
g_value_set_object (value, meta_get_top_window_group_for_screen (global->meta_screen));
g_value_set_object (value, meta_get_top_window_group_for_display (global->meta_display));
break;
case PROP_WINDOW_MANAGER:
g_value_set_object (value, global->wm);
@ -370,13 +373,6 @@ shell_global_class_init (ShellGlobalClass *klass)
"The session mode to use",
"user",
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (gobject_class,
PROP_SCREEN,
g_param_spec_object ("screen",
"Screen",
"Metacity screen object for the shell",
META_TYPE_SCREEN,
G_PARAM_READABLE));
g_object_class_install_property (gobject_class,
PROP_SCREEN_WIDTH,
@ -401,6 +397,14 @@ shell_global_class_init (ShellGlobalClass *klass)
META_TYPE_DISPLAY,
G_PARAM_READABLE));
g_object_class_install_property (gobject_class,
PROP_WORKSPACE_MANAGER,
g_param_spec_object ("workspace-manager",
"Workspace manager",
"Workspace manager",
META_TYPE_WORKSPACE_MANAGER,
G_PARAM_READABLE));
g_object_class_install_property (gobject_class,
PROP_STAGE,
g_param_spec_object ("stage",
@ -564,7 +568,7 @@ focus_window_changed (MetaDisplay *display,
/* If the stage window became unfocused, drop the key focus
* on Clutter's side. */
if (!meta_stage_is_focused (global->meta_screen))
if (!meta_stage_is_focused (global->meta_display))
clutter_stage_set_key_focus (global->stage, NULL);
}
@ -594,14 +598,14 @@ sync_stage_window_focus (ShellGlobal *global)
actor = get_key_focused_actor (global);
/* An actor got key focus and the stage needs to be focused. */
if (actor != NULL && !meta_stage_is_focused (global->meta_screen))
meta_focus_stage_window (global->meta_screen,
if (actor != NULL && !meta_stage_is_focused (global->meta_display))
meta_focus_stage_window (global->meta_display,
get_current_time_maybe_roundtrip (global));
/* An actor dropped key focus. Focus the default window. */
else if (actor == NULL && meta_stage_is_focused (global->meta_screen))
meta_screen_focus_default_window (global->meta_screen,
get_current_time_maybe_roundtrip (global));
else if (actor == NULL && meta_stage_is_focused (global->meta_display))
meta_display_focus_default_window (global->meta_display,
get_current_time_maybe_roundtrip (global));
}
static void
@ -616,12 +620,12 @@ focus_actor_changed (ClutterStage *stage,
static void
sync_input_region (ShellGlobal *global)
{
MetaScreen *screen = global->meta_screen;
MetaDisplay *display = global->meta_display;
if (global->has_modal)
meta_set_stage_input_region (screen, None);
meta_set_stage_input_region (display, None);
else
meta_set_stage_input_region (screen, global->input_region);
meta_set_stage_input_region (display, global->input_region);
}
/**
@ -675,17 +679,6 @@ shell_global_get_stage (ShellGlobal *global)
return global->stage;
}
/**
* shell_global_get_screen:
*
* Return value: (transfer none): The default #MetaScreen
*/
MetaScreen *
shell_global_get_screen (ShellGlobal *global)
{
return global->meta_screen;
}
/**
* shell_global_get_display:
*
@ -712,7 +705,7 @@ shell_global_get_window_actors (ShellGlobal *global)
g_return_val_if_fail (SHELL_IS_GLOBAL (global), NULL);
for (l = meta_get_window_actors (global->meta_screen); l; l = l->next)
for (l = meta_get_window_actors (global->meta_display); l; l = l->next)
if (!meta_window_actor_is_destroyed (l->data))
filtered = g_list_prepend (filtered, l->data);
@ -838,13 +831,15 @@ entry_cursor_func (StEntry *entry,
{
ShellGlobal *global = user_data;
meta_screen_set_cursor (global->meta_screen, use_ibeam ? META_CURSOR_IBEAM : META_CURSOR_DEFAULT);
meta_display_set_cursor (global->meta_display,
use_ibeam ? META_CURSOR_IBEAM : META_CURSOR_DEFAULT);
}
void
_shell_global_set_plugin (ShellGlobal *global,
MetaPlugin *plugin)
{
MetaDisplay *display;
MetaBackend *backend;
MetaSettings *settings;
@ -854,13 +849,15 @@ _shell_global_set_plugin (ShellGlobal *global,
global->plugin = plugin;
global->wm = shell_wm_new (plugin);
global->meta_screen = meta_plugin_get_screen (plugin);
global->meta_display = meta_screen_get_display (global->meta_screen);
global->xdisplay = meta_display_get_xdisplay (global->meta_display);
display = meta_plugin_get_display (plugin);
global->meta_display = display;
global->workspace_manager = meta_display_get_workspace_manager (display);
global->x11_display = meta_display_get_x11_display (display);
global->xdisplay = meta_x11_display_get_xdisplay (global->x11_display);
global->gdk_display = gdk_x11_lookup_xdisplay (global->xdisplay);
global->stage = CLUTTER_STAGE (meta_get_stage_for_screen (global->meta_screen));
global->stage = CLUTTER_STAGE (meta_get_stage_for_display (display));
if (meta_is_wayland_compositor ())
{
@ -972,13 +969,13 @@ shell_global_end_modal (ShellGlobal *global,
/* If the stage window is unfocused, ensure that there's no
* actor focused on Clutter's side. */
if (!meta_stage_is_focused (global->meta_screen))
if (!meta_stage_is_focused (global->meta_display))
clutter_stage_set_key_focus (global->stage, NULL);
/* An actor dropped key focus. Focus the default window. */
else if (get_key_focused_actor (global) && meta_stage_is_focused (global->meta_screen))
meta_screen_focus_default_window (global->meta_screen,
get_current_time_maybe_roundtrip (global));
else if (get_key_focused_actor (global) && meta_stage_is_focused (global->meta_display))
meta_display_focus_default_window (global->meta_display,
get_current_time_maybe_roundtrip (global));
sync_input_region (global);
}
@ -1159,9 +1156,8 @@ shell_global_reexec_self (ShellGlobal *global)
*/
pre_exec_close_fds ();
meta_display_unmanage_screen (shell_global_get_display (global),
shell_global_get_screen (global),
shell_global_get_current_time (global));
meta_display_close (shell_global_get_display (global),
shell_global_get_current_time (global));
execvp (arr->pdata[0], (char**)arr->pdata);
g_warning ("failed to reexec: %s", g_strerror (errno));
@ -1246,7 +1242,7 @@ shell_global_notify_error (ShellGlobal *global,
*/
void shell_global_init_xdnd (ShellGlobal *global)
{
Window output_window = meta_get_overlay_window (global->meta_screen);
Window output_window = meta_get_overlay_window (global->meta_display);
long xdnd_version = 5;
XChangeProperty (global->xdisplay, global->stage_xwindow,
@ -1284,7 +1280,7 @@ shell_global_get_pointer (ShellGlobal *global,
ClutterModifierType raw_mods;
MetaCursorTracker *tracker;
tracker = meta_cursor_tracker_get_for_screen (global->meta_screen);
tracker = meta_cursor_tracker_get_for_display (global->meta_display);
meta_cursor_tracker_get_pointer (tracker, x, y, &raw_mods);
*mods = raw_mods & CLUTTER_MODIFIER_MASK;
@ -1432,7 +1428,12 @@ shell_global_create_app_launch_context (ShellGlobal *global,
gdk_app_launch_context_set_timestamp (context, timestamp);
if (workspace < 0)
workspace = meta_screen_get_active_workspace_index (global->meta_screen);
{
MetaWorkspaceManager *workspace_manager = global->workspace_manager;
workspace =
meta_workspace_manager_get_active_workspace_index (workspace_manager);
}
gdk_app_launch_context_set_desktop (context, workspace);
return (GAppLaunchContext *)context;

View File

@ -16,7 +16,6 @@ G_DECLARE_FINAL_TYPE (ShellGlobal, shell_global, SHELL, GLOBAL, GObject)
ShellGlobal *shell_global_get (void);
ClutterStage *shell_global_get_stage (ShellGlobal *global);
MetaScreen *shell_global_get_screen (ShellGlobal *global);
MetaDisplay *shell_global_get_display (ShellGlobal *global);
GList *shell_global_get_window_actors (ShellGlobal *global);
GSettings *shell_global_get_settings (ShellGlobal *global);

View File

@ -15,8 +15,8 @@
#include <gdk/gdk.h>
#include <cogl/cogl.h>
#include <meta/screen.h>
#include <meta/meta-cursor-tracker.h>
#include <meta/display.h>
#include <meta/compositor-mutter.h>
#include "shell-global.h"
@ -112,7 +112,7 @@ static void recorder_remove_redraw_timeout (ShellRecorder *recorder);
enum {
PROP_0,
PROP_SCREEN,
PROP_DISPLAY,
PROP_STAGE,
PROP_FRAMERATE,
PROP_PIPELINE,
@ -670,12 +670,12 @@ recorder_set_stage (ShellRecorder *recorder,
}
static void
recorder_set_screen (ShellRecorder *recorder,
MetaScreen *screen)
recorder_set_display (ShellRecorder *recorder,
MetaDisplay *display)
{
MetaCursorTracker *tracker;
tracker = meta_cursor_tracker_get_for_screen (screen);
tracker = meta_cursor_tracker_get_for_display (display);
if (tracker == recorder->cursor_tracker)
return;
@ -760,8 +760,8 @@ shell_recorder_set_property (GObject *object,
switch (prop_id)
{
case PROP_SCREEN:
recorder_set_screen (recorder, g_value_get_object (value));
case PROP_DISPLAY:
recorder_set_display (recorder, g_value_get_object (value));
break;
case PROP_STAGE:
recorder_set_stage (recorder, g_value_get_object (value));
@ -825,11 +825,11 @@ shell_recorder_class_init (ShellRecorderClass *klass)
gobject_class->set_property = shell_recorder_set_property;
g_object_class_install_property (gobject_class,
PROP_SCREEN,
g_param_spec_object ("screen",
"Screen",
"Screen to record",
META_TYPE_SCREEN,
PROP_DISPLAY,
g_param_spec_object ("display",
"Display",
"Display to record",
META_TYPE_DISPLAY,
G_PARAM_WRITABLE));
g_object_class_install_property (gobject_class,
@ -1551,7 +1551,7 @@ shell_recorder_record (ShellRecorder *recorder,
recorder_add_update_pointer_timeout (recorder);
/* Disable unredirection while we are recoring */
meta_disable_unredirect_for_screen (shell_global_get_screen (shell_global_get ()));
meta_disable_unredirect_for_display (shell_global_get_display (shell_global_get ()));
/* Set up repaint hook */
recorder->repaint_hook_id = clutter_threads_add_repaint_func(recorder_repaint_hook, recorder->stage, NULL);
@ -1602,7 +1602,7 @@ shell_recorder_close (ShellRecorder *recorder)
recorder->state = RECORDER_STATE_CLOSED;
/* Reenable after the recording */
meta_enable_unredirect_for_screen (shell_global_get_screen (shell_global_get ()));
meta_enable_unredirect_for_display (shell_global_get_display (shell_global_get ()));
/* Release the refcount we took when we started recording */
g_object_unref (recorder);

View File

@ -31,6 +31,8 @@ struct _ShellScreenshotPrivate
char *filename;
char *filename_used;
GDateTime *datetime;
cairo_surface_t *image;
cairo_rectangle_int_t screenshot_area;
@ -72,8 +74,9 @@ on_screenshot_written (GObject *source,
g_clear_pointer (&priv->image, cairo_surface_destroy);
g_clear_pointer (&priv->filename, g_free);
g_clear_pointer (&priv->filename_used, g_free);
g_clear_pointer (&priv->datetime, g_date_time_unref);
meta_enable_unredirect_for_screen (shell_global_get_screen (priv->global));
meta_enable_unredirect_for_display (shell_global_get_display (priv->global));
}
/* called in an I/O thread */
@ -175,6 +178,7 @@ write_screenshot_thread (GTask *result,
GOutputStream *stream;
ShellScreenshot *screenshot = SHELL_SCREENSHOT (object);
ShellScreenshotPrivate *priv;
char *creation_time;
g_assert (screenshot != NULL);
@ -193,14 +197,18 @@ write_screenshot_thread (GTask *result,
0, 0,
cairo_image_surface_get_width (priv->image),
cairo_image_surface_get_height (priv->image));
creation_time = g_date_time_format (priv->datetime, "%c");
if (gdk_pixbuf_save_to_stream (pixbuf, stream, "png", NULL, NULL,
"tEXt::Software", "gnome-screenshot", NULL))
"tEXt::Software", "gnome-screenshot",
"tEXt::Creation Time", creation_time,
NULL))
status = CAIRO_STATUS_SUCCESS;
else
status = CAIRO_STATUS_WRITE_ERROR;
g_object_unref (pixbuf);
g_free (creation_time);
}
@ -241,6 +249,7 @@ do_grab_screenshot (ShellScreenshot *screenshot,
n_captures,
x, y,
width, height);
priv->datetime = g_date_time_new_now_local ();
for (i = 0; i < n_captures; i++)
cairo_surface_destroy (captures[i].image);
@ -306,19 +315,19 @@ static void
grab_screenshot (ClutterActor *stage,
ShellScreenshot *screenshot)
{
MetaScreen *screen;
MetaDisplay *display;
MetaCursorTracker *tracker;
int width, height;
GTask *result;
GSettings *settings;
ShellScreenshotPrivate *priv = screenshot->priv;
screen = shell_global_get_screen (priv->global);
meta_screen_get_size (screen, &width, &height);
display = shell_global_get_display (priv->global);
meta_display_get_size (display, &width, &height);
do_grab_screenshot (screenshot, CLUTTER_STAGE (stage), 0, 0, width, height);
if (meta_screen_get_n_monitors (screen) > 1)
if (meta_display_get_n_monitors (display) > 1)
{
cairo_region_t *screen_region = cairo_region_create ();
cairo_region_t *stage_region;
@ -327,10 +336,11 @@ grab_screenshot (ClutterActor *stage,
int i;
cairo_t *cr;
for (i = meta_screen_get_n_monitors (screen) - 1; i >= 0; i--)
for (i = meta_display_get_n_monitors (display) - 1; i >= 0; i--)
{
meta_screen_get_monitor_geometry (screen, i, &monitor_rect);
cairo_region_union_rectangle (screen_region, (const cairo_rectangle_int_t *) &monitor_rect);
meta_display_get_monitor_geometry (display, i, &monitor_rect);
cairo_region_union_rectangle (screen_region,
(const cairo_rectangle_int_t *) &monitor_rect);
}
stage_rect.x = 0;
@ -365,7 +375,7 @@ grab_screenshot (ClutterActor *stage,
if (priv->include_cursor &&
!g_settings_get_boolean (settings, MAGNIFIER_ACTIVE_KEY))
{
tracker = meta_cursor_tracker_get_for_screen (screen);
tracker = meta_cursor_tracker_get_for_display (display);
_draw_cursor_image (tracker, priv->image, priv->screenshot_area);
}
g_object_unref (settings);
@ -404,9 +414,8 @@ grab_window_screenshot (ClutterActor *stage,
ShellScreenshotPrivate *priv = screenshot->priv;
GTask *result;
GSettings *settings;
MetaScreen *screen = shell_global_get_screen (priv->global);
MetaDisplay *display = shell_global_get_display (priv->global);
MetaCursorTracker *tracker;
MetaDisplay *display = meta_screen_get_display (screen);
MetaWindow *window = meta_display_get_focus_window (display);
ClutterActor *window_actor;
gfloat actor_x, actor_y;
@ -432,11 +441,12 @@ grab_window_screenshot (ClutterActor *stage,
stex = META_SHAPED_TEXTURE (meta_window_actor_get_texture (META_WINDOW_ACTOR (window_actor)));
priv->image = meta_shaped_texture_get_image (stex, &clip);
priv->datetime = g_date_time_new_now_local ();
settings = g_settings_new (A11Y_APPS_SCHEMA);
if (priv->include_cursor && !g_settings_get_boolean (settings, MAGNIFIER_ACTIVE_KEY))
{
tracker = meta_cursor_tracker_get_for_screen (screen);
tracker = meta_cursor_tracker_get_for_display (display);
_draw_cursor_image (tracker, priv->image, priv->screenshot_area);
}
g_object_unref (settings);
@ -480,7 +490,7 @@ shell_screenshot_screenshot (ShellScreenshot *screenshot,
stage = CLUTTER_ACTOR (shell_global_get_stage (priv->global));
meta_disable_unredirect_for_screen (shell_global_get_screen (priv->global));
meta_disable_unredirect_for_display (shell_global_get_display (priv->global));
g_signal_connect_after (stage, "paint", G_CALLBACK (grab_screenshot), (gpointer)screenshot);
@ -529,7 +539,7 @@ shell_screenshot_screenshot_area (ShellScreenshot *screenshot,
stage = CLUTTER_ACTOR (shell_global_get_stage (priv->global));
meta_disable_unredirect_for_screen (shell_global_get_screen (shell_global_get ()));
meta_disable_unredirect_for_display (shell_global_get_display (shell_global_get ()));
g_signal_connect_after (stage, "paint", G_CALLBACK (grab_area_screenshot), (gpointer)screenshot);
@ -557,9 +567,8 @@ shell_screenshot_screenshot_window (ShellScreenshot *screenshot,
ShellScreenshotCallback callback)
{
ShellScreenshotPrivate *priv = screenshot->priv;
MetaScreen *screen = shell_global_get_screen (priv->global);
MetaDisplay *display = shell_global_get_display (priv->global);
ClutterActor *stage;
MetaDisplay *display = meta_screen_get_display (screen);
MetaWindow *window = meta_display_get_focus_window (display);
if (priv->filename != NULL || !window) {
@ -575,7 +584,7 @@ shell_screenshot_screenshot_window (ShellScreenshot *screenshot,
stage = CLUTTER_ACTOR (shell_global_get_stage (priv->global));
meta_disable_unredirect_for_screen (shell_global_get_screen (shell_global_get ()));
meta_disable_unredirect_for_display (shell_global_get_display (shell_global_get ()));
g_signal_connect_after (stage, "paint", G_CALLBACK (grab_window_screenshot), (gpointer)screenshot);

View File

@ -210,16 +210,13 @@ shell_tray_manager_style_changed (StWidget *theme_widget,
void
shell_tray_manager_manage_screen (ShellTrayManager *manager,
MetaScreen *screen,
StWidget *theme_widget)
{
GdkDisplay *display;
GdkScreen *gdk_screen;
int screen_number;
display = gdk_display_get_default ();
screen_number = meta_screen_get_screen_number (screen);
gdk_screen = gdk_display_get_screen (display, screen_number);
gdk_screen = gdk_display_get_default_screen (display);
na_tray_manager_manage_screen (manager->priv->na_manager, gdk_screen);

View File

@ -14,7 +14,6 @@ G_DECLARE_FINAL_TYPE (ShellTrayManager, shell_tray_manager,
ShellTrayManager *shell_tray_manager_new (void);
void shell_tray_manager_manage_screen (ShellTrayManager *manager,
MetaScreen *screen,
StWidget *theme_widget);
G_END_DECLS

View File

@ -13,6 +13,7 @@
#include <meta/group.h>
#include <meta/util.h>
#include <meta/window.h>
#include <meta/meta-workspace-manager.h>
#define SN_API_NOT_YET_FROZEN 1
#include <libsn/sn.h>
@ -587,13 +588,16 @@ shell_window_tracker_on_window_removed (MetaWorkspace *workspace,
static void
load_initial_windows (ShellWindowTracker *tracker)
{
GList *workspaces, *iter;
MetaScreen *screen = shell_global_get_screen (shell_global_get ());
workspaces = meta_screen_get_workspaces (screen);
MetaDisplay *display = shell_global_get_display (shell_global_get ());
MetaWorkspaceManager *workspace_manager =
meta_display_get_workspace_manager (display);
GList *workspaces;
GList *l;
for (iter = workspaces; iter; iter = iter->next)
workspaces = meta_workspace_manager_get_workspaces (workspace_manager);
for (l = workspaces; l; l = l->next)
{
MetaWorkspace *workspace = iter->data;
MetaWorkspace *workspace = l->data;
GList *windows = meta_workspace_list_windows (workspace);
GList *window_iter;
@ -608,18 +612,18 @@ load_initial_windows (ShellWindowTracker *tracker)
}
static void
shell_window_tracker_on_n_workspaces_changed (MetaScreen *screen,
GParamSpec *pspec,
gpointer user_data)
shell_window_tracker_on_n_workspaces_changed (MetaWorkspaceManager *workspace_manager,
GParamSpec *pspec,
gpointer user_data)
{
ShellWindowTracker *self = SHELL_WINDOW_TRACKER (user_data);
GList *workspaces, *iter;
GList *workspaces;
GList *l;
workspaces = meta_screen_get_workspaces (screen);
for (iter = workspaces; iter; iter = iter->next)
workspaces = meta_workspace_manager_get_workspaces (workspace_manager);
for (l = workspaces; l; l = l->next)
{
MetaWorkspace *workspace = iter->data;
MetaWorkspace *workspace = l->data;
/* This pair of disconnect/connect is idempotent if we were
* already connected, while ensuring we get connected for
@ -642,20 +646,20 @@ shell_window_tracker_on_n_workspaces_changed (MetaScreen *screen,
static void
init_window_tracking (ShellWindowTracker *self)
{
MetaDisplay *display;
MetaScreen *screen = shell_global_get_screen (shell_global_get ());
MetaDisplay *display = shell_global_get_display (shell_global_get ());
MetaWorkspaceManager *workspace_manager =
meta_display_get_workspace_manager (display);
g_signal_connect (screen, "notify::n-workspaces",
g_signal_connect (workspace_manager, "notify::n-workspaces",
G_CALLBACK (shell_window_tracker_on_n_workspaces_changed), self);
display = meta_screen_get_display (screen);
g_signal_connect (display, "notify::focus-window",
G_CALLBACK (on_focus_window_changed), self);
shell_window_tracker_on_n_workspaces_changed (screen, NULL, self);
shell_window_tracker_on_n_workspaces_changed (workspace_manager, NULL, self);
}
static void
on_startup_sequence_changed (MetaScreen *screen,
on_startup_sequence_changed (MetaDisplay *display,
SnStartupSequence *sequence,
ShellWindowTracker *self)
{
@ -671,14 +675,13 @@ on_startup_sequence_changed (MetaScreen *screen,
static void
shell_window_tracker_init (ShellWindowTracker *self)
{
MetaScreen *screen;
MetaDisplay *display = shell_global_get_display (shell_global_get ());
self->window_to_app = g_hash_table_new_full (g_direct_hash, g_direct_equal,
NULL, (GDestroyNotify) g_object_unref);
screen = shell_global_get_screen (shell_global_get ());
g_signal_connect (G_OBJECT (screen), "startup-sequence-changed",
g_signal_connect (display, "startup-sequence-changed",
G_CALLBACK (on_startup_sequence_changed), self);
load_initial_windows (self);
@ -795,8 +798,9 @@ GSList *
shell_window_tracker_get_startup_sequences (ShellWindowTracker *self)
{
ShellGlobal *global = shell_global_get ();
MetaScreen *screen = shell_global_get_screen (global);
return meta_screen_get_startup_sequences (screen);
MetaDisplay *display = shell_global_get_display (global);
return meta_display_get_startup_sequences (display);
}
/* sn_startup_sequence_ref returns void, so make a
@ -906,11 +910,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:

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -905,6 +905,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 +929,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;

View File

@ -56,12 +56,15 @@ struct _StIconPrivate
CoglPipeline *shadow_pipeline;
StShadow *shadow_spec;
ClutterSize shadow_size;
};
G_DEFINE_TYPE_WITH_PRIVATE (StIcon, st_icon, ST_TYPE_WIDGET)
static void st_icon_update (StIcon *icon);
static gboolean st_icon_update_icon_size (StIcon *icon);
static void st_icon_update_shadow_pipeline (StIcon *icon);
static void st_icon_clear_shadow_pipeline (StIcon *icon);
#define DEFAULT_ICON_SIZE 48
@ -158,20 +161,20 @@ st_icon_dispose (GObject *gobject)
static void
st_icon_paint (ClutterActor *actor)
{
StIconPrivate *priv = ST_ICON (actor)->priv;
StIcon *icon = ST_ICON (actor);
StIconPrivate *priv = icon->priv;
st_widget_paint_background (ST_WIDGET (actor));
if (priv->icon_texture)
{
st_icon_update_shadow_pipeline (icon);
if (priv->shadow_pipeline)
{
ClutterActorBox allocation;
float width, height;
clutter_actor_get_allocation_box (priv->icon_texture, &allocation);
clutter_actor_box_get_size (&allocation, &width, &height);
_st_paint_shadow_with_opacity (priv->shadow_spec,
priv->shadow_pipeline,
&allocation,
@ -189,7 +192,7 @@ st_icon_style_changed (StWidget *widget)
StThemeNode *theme_node = st_widget_get_theme_node (widget);
StIconPrivate *priv = self->priv;
g_clear_pointer (&priv->shadow_pipeline, cogl_object_unref);
st_icon_clear_shadow_pipeline (self);
g_clear_pointer (&priv->shadow_spec, st_shadow_unref);
priv->shadow_spec = st_theme_node_get_shadow (theme_node, "icon-shadow");
@ -268,21 +271,49 @@ st_icon_init (StIcon *self)
}
static void
st_icon_update_shadow_pipeline (StIcon *icon)
st_icon_clear_shadow_pipeline (StIcon *icon)
{
StIconPrivate *priv = icon->priv;
g_clear_pointer (&priv->shadow_pipeline, cogl_object_unref);
clutter_size_init (&priv->shadow_size, 0, 0);
}
if (priv->shadow_spec)
priv->shadow_pipeline = _st_create_shadow_pipeline_from_actor (priv->shadow_spec, priv->icon_texture);
static void
st_icon_update_shadow_pipeline (StIcon *icon)
{
StIconPrivate *priv = icon->priv;
if (priv->icon_texture && priv->shadow_spec)
{
ClutterActorBox box;
float width, height;
clutter_actor_get_allocation_box (CLUTTER_ACTOR (icon), &box);
clutter_actor_box_get_size (&box, &width, &height);
if (priv->shadow_pipeline == NULL ||
priv->shadow_size.width != width ||
priv->shadow_size.height != height)
{
st_icon_clear_shadow_pipeline (icon);
priv->shadow_pipeline =
_st_create_shadow_pipeline_from_actor (priv->shadow_spec,
priv->icon_texture);
if (priv->shadow_pipeline)
clutter_size_init (&priv->shadow_size, width, height);
}
}
}
static void
on_pixbuf_changed (ClutterTexture *texture,
StIcon *icon)
{
st_icon_update_shadow_pipeline (icon);
st_icon_clear_shadow_pipeline (icon);
clutter_actor_queue_redraw (CLUTTER_ACTOR (icon));
}
static void
@ -307,7 +338,7 @@ st_icon_finish_update (StIcon *icon)
/* Remove the temporary ref we added */
g_object_unref (priv->icon_texture);
st_icon_update_shadow_pipeline (icon);
st_icon_clear_shadow_pipeline (icon);
/* "pixbuf-change" is actually a misnomer for "texture-changed" */
g_signal_connect_object (priv->icon_texture, "pixbuf-change",

View File

@ -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);

View File

@ -117,6 +117,7 @@ _st_set_text_from_style (ClutterText *text,
const PangoFontDescription *font;
StTextAlign align;
gdouble spacing;
gchar *font_features;
st_theme_node_get_foreground_color (theme_node, &color);
clutter_text_set_color (text, &color);
@ -151,6 +152,13 @@ _st_set_text_from_style (ClutterText *text,
pango_attr_list_insert (attribs, letter_spacing);
}
font_features = st_theme_node_get_font_features (theme_node);
if (font_features)
{
pango_attr_list_insert (attribs, pango_attr_font_features_new (font_features));
g_free (font_features);
}
clutter_text_set_attributes (text, attribs);
if (attribs)
@ -424,6 +432,8 @@ _st_create_shadow_pipeline_from_actor (StShadow *shadow_spec,
CoglPipeline *shadow_pipeline = NULL;
float width, height;
g_return_val_if_fail (clutter_actor_has_allocation (actor), NULL);
clutter_actor_get_size (actor, &width, &height);
if (width == 0 || height == 0)

View File

@ -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;

View File

@ -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;
}
@ -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

View File

@ -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)
{

View File

@ -3019,6 +3019,39 @@ st_theme_node_get_font (StThemeNode *node)
return node->font_desc;
}
gchar *
st_theme_node_get_font_features (StThemeNode *node)
{
int i;
ensure_properties (node);
for (i = node->n_properties - 1; i >= 0; i--)
{
CRDeclaration *decl = node->properties[i];
if (strcmp (decl->property->stryng->str, "font-feature-settings") == 0)
{
CRTerm *term = decl->value;
if (!term->next && term->type == TERM_IDENT)
{
gchar *ident = term->content.str->stryng->str;
if (strcmp (ident, "inherit") == 0)
break;
if (strcmp (ident, "normal") == 0)
return NULL;
}
return (gchar *)cr_term_to_string (term);
}
}
return node->parent_node ? st_theme_node_get_font_features (node->parent_node) : NULL;
}
/**
* st_theme_node_get_border_image:
* @node: a #StThemeNode

View File

@ -232,6 +232,8 @@ double st_theme_node_get_letter_spacing (StThemeNode *node);
*/
const PangoFontDescription *st_theme_node_get_font (StThemeNode *node);
gchar *st_theme_node_get_font_features (StThemeNode *node);
StBorderImage *st_theme_node_get_border_image (StThemeNode *node);
StShadow *st_theme_node_get_box_shadow (StThemeNode *node);
StShadow *st_theme_node_get_text_shadow (StThemeNode *node);

View File

@ -59,6 +59,24 @@ assert_font (StThemeNode *node,
g_free (value);
}
static void
assert_font_features (StThemeNode *node,
const char *node_description,
const char *expected)
{
char *value = st_theme_node_get_font_features (node);
if (g_strcmp0 (expected, value) != 0)
{
g_print ("%s: %s.font-feature-settings: expected: %s, got: %s\n",
test, node_description, expected, value);
fail = TRUE;
}
if (value)
g_free (value);
}
static char *
text_decoration_to_string (StTextDecoration decoration)
{
@ -396,7 +414,7 @@ test_background (void)
/* text1 inherits the background image but not the color */
assert_background_color (text1, "text1", 0x00000000);
assert_background_image (text1, "text1", "st/some-background.png");
/* text1 inherits inherits both, but then background: none overrides both */
/* text2 inherits both, but then background: none overrides both */
assert_background_color (text2, "text2", 0x00000000);
assert_background_image (text2, "text2", NULL);
/* background-image property */
@ -413,6 +431,22 @@ test_font (void)
assert_font (text3, "text3", "serif Bold Oblique Small-Caps 24px");
}
static void
test_font_features (void)
{
test = "font_features";
/* group1 has font-feature-settings: "tnum" */
assert_font_features (group1, "group1", "\"tnum\"");
/* text2 should inherit from group1 */
assert_font_features (text2, "text2", "\"tnum\"");
/* group2 has font-feature-settings: "tnum", "zero" */
assert_font_features (group2, "group2", "\"tnum\", \"zero\"");
/* text3 should inherit from group2 using the inherit keyword */
assert_font_features (text3, "text3", "\"tnum\", \"zero\"");
/* text4 has font-feature-settings: normal */
assert_font_features (text4, "text4", NULL);
}
static void
test_pseudo_class (void)
{
@ -554,6 +588,7 @@ main (int argc, char **argv)
test_border ();
test_background ();
test_font ();
test_font_features ();
test_pseudo_class ();
test_inline_style ();

View File

@ -13,6 +13,8 @@ stage {
margin-left: 1in;
background: #ff0000 url('some-background.png');
font-feature-settings: "tnum";
}
#text1 {
@ -35,6 +37,7 @@ ClutterTexture.special-text {
#group2 {
font: italic 12px serif;
font-feature-settings: "tnum", "zero";
}
#text3 {
@ -42,6 +45,11 @@ ClutterTexture.special-text {
font-weight: bold;
font-style: oblique;
font-size: 200%;
font-feature-settings: "pnum";
}
#text4 {
font-feature-settings: normal;
}
ClutterTexture {
@ -60,6 +68,10 @@ stage > #text2 {
color: #ff0000;
}
#group2 > #text3 {
font-feature-settings: inherit;
}
#group2 {
background-image: url('other-background.png');
padding: 1px 2px 3px 4px;