Compare commits

..

69 Commits

Author SHA1 Message Date
13ec3169a6 Bump version to 3.28.4
Update NEWS.
2019-05-14 17:28:08 +00:00
8702d6647b 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).

(cherry picked from commit b1b455ff1a)

Closes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/1270
2019-05-08 15:29:54 +08:00
5703a25e2b dialog: Really set ellipsize mode in subtitle and body
Dialog's subtitle or body could not be properly wrapped, while it's ellipsized
when the text's width doesn't exceed the container size.

Clutter text has an `ellipsize` property, however in dialog's subtitle and body
we have been setting the `ellipsize-mode` property to Pango.EllipsizeMode.NONE
that is not present in the underlying GObject.

Not being an error in javascript, gjs didn't warn us about this, while at the
same time the St.Label's default Pango.EllipsizeMode.END was used.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/922

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/531


(cherry picked from commit 3121c9aa29)
2019-05-03 21:32:24 +00:00
09fbb4a127 windowManager: listen actively to windows being destroyed during WS switch
Prevents gjs from dealing with already dispose()d objects.

Closes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/539

(cherry-picked from b087752b55)
2019-05-02 14:27:53 -05:00
4c7b20e584 dnd: Only handle touch events in wayland
There are serveral issues around touch passive grab and touch/pointer doubly
handling to use these on X11, so we stick to single-touch/pointer there.

Cherry picked from commit 60ccdc2deb

Closes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/1015
2019-03-13 18:26:32 +00:00
b3045cb964 closeDialog: Untrack chrome when window loses focus
On X11, reactive chrome must be added to the input region in order
to work as expected. However that region works independently from
any window stacking, with the result that the unresponsive-app dialog
currently blocks all input in the "covered" area, even in windows
stacked above the unresponsive window.

The correct fix would be to track the unobscured parts of the dialog
and set the input region from that, but that's quite cumbersome. So
instead, only track chrome when the corresponding window is focused
(or the dialog itself of course).

https://gitlab.gnome.org/GNOME/gnome-shell/issues/273
2019-01-24 16:47:33 +01:00
c41175af45 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
2019-01-24 16:47:33 +01:00
7b1544a7a2 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
2019-01-24 16:47:33 +01:00
a0f1ac87e9 messageTray: Fix sloppy backport
Commit 8111286463 was cherry-picked without accounting for the
screen/display API difference between 3-30 and 3-28.
2019-01-24 16:47:33 +01:00
1045b35c8b ibusManager: Don't pass undefined callback to ibus
Since commit 551e827841, we don't always pass a callback parameter.
However passing it on as undefined to ibus doesn't work, as gjs doesn't
accept that as a valid callback value and throw an error. As a result,
we can end up with no layout selected in the keyboard menu and an "empty"
indicator. Fix this by explicitly passing null if no callback has been
provided.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/293


(cherry picked from commit 74bb9e6249)
2019-01-21 16:28:20 +00:00
24cdcc56da st-bin: Destroy child in ClutterActor:destroy vfunc
According to Clutter documentation, "[…] actors implementing the
ClutterContainer interface should override the default implementation
of the class handler of this signal and call clutter_actor_destroy()
on their  children."

StBin was doing that in GObject:dispose() instead. Move the child
destruction to a new ClutterActor:destroy() vfunc override.


(cherry picked from commit b719744e75)
2019-01-16 00:05:59 +00:00
1b28cdfbf4 keyboard: Do not call KeyboardManager.holdKeyboard() with set-content-type
When gnome-shell receives the signal of 'set-content-type' from ibus,
gnome-shell calls KeyboardManager.holdKeyboard() and
KeyboardManager.releaseKeyboard() and the functions change the current
input focus in GNOME Xorg and it could result in closing a popup window
which has a password entry by focusing on the entry.
The solution is to stop to call the APIs on 'set-content-type' signal.

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


(cherry picked from commit 551e827841)
2019-01-15 15:24:40 +00:00
a73294312f altSwitcher: Fix error when all alternatives are disabled
While we do consider the case that we don't have a child to show for the
visibility, we are still trying to move the click action unconditionally.

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

(cherry picked from commit e77463b875)
2019-01-11 11:30:27 +00:00
5e7a7e31a1 messageTray: Re-enable unredirection when banner is destroyed
The intention of commit 4dc20398 was to disable unredirection while
banners are shown, but the ::done-displaying signal currently used for
re-enabling unredirection is only emitted under some circumstances, so
it's possible that unredirection is left disabled indefinitely, whoops.

Fix this by tying disabling unredirection explicitly to the lifetime
of the banner actor.

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

(cherry picked from commit e5ce3d541e)
2019-01-11 11:30:27 +00:00
8111286463 messageTray: Disable unredirection while showing banners
We don't usually show notification banners while the monitor is in
fullscreen, but when we do - the notification is urgent - we should
actually show the banner, even if the top-most window is unredirected.
To achieve that, disable unredirection while the banner is showing.

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

(cherry picked from commit 4dc2039859)
2019-01-11 11:30:26 +00:00
06c6ecc15b workspacesView: initialize self._restackedNotifyId
This attribute was previously only assigned in show(). hide() compares
this attribute to 0. If hide() is called before show() is first called,
the comparison would give the correct result (undefined > 0 is false)
but log a warning:

    JS WARNING: [resource:///org/gnome/shell/ui/workspacesView.js 529]:
    reference to undefined property "_restackedNotifyId"

Initialize this attribute in _init(), alongside _scrollEventId and
_keyPressEventId which are also used in hide().

(cherry picked from commit b2fabd9356)
2019-01-11 11:30:26 +00:00
36f9dcd2bd endSessionDialog: squash "reference to undefined property" warning
dialogContent is set to one of the elements of the list DialogContent,
but not all of those have a checkBoxText property. When logging out (as
opposed to shutting down), this causes a warning:

    JS WARNING: [resource:///org/gnome/shell/ui/endSessionDialog.js
    763]: reference to undefined property "checkBoxText"

(The line number corresponds to this line in 3.28.3.)

The warning is apparently not triggered if the undefined property is
used as part of a boolean expression:

    gjs> var x = {};
    gjs> x.a;
    typein:2:1 strict warning: reference to undefined property "a"
    gjs> if (x.b) { log('oh no'); }
    gjs> x.c || ''
    ""
_setCheckBoxLabel() just checks the truthiness of its 'text' argument,
and the empty string is false-y, so passing '' rather than undefined has
no functional effect.

(cherry picked from commit 0892b5dcdb)
2019-01-11 11:30:26 +00:00
219118e633 viewSelector: Don't unfocus other modals on reset
Don't drop the key focus on Clutter's side if anything but the overview has
pushed a modal (e.g. system modals when activated using the overview).

Closes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/618

(cherry picked from commit fffe58f829)
2019-01-11 11:30:26 +00:00
1e929357e0 panel: Also ignore hidden windows for proximity
We currently only ignore minimized windows, not windows that are
hidden for other reasons - namely on wayland windows are initially
hidden until they are placed.

This fixes a flicker in the transparent top bar on wayland when the
"position" of an unplaced window wrongly suggests the window is
overlapping the top bar.

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

(cherry-picked from commit a0dc8dc7ef)
2019-01-11 11:30:26 +00:00
e7463e38ca notificationDaemon: support file:// or icon theme names for image-path
While this sounds counter-intuitive, the image-path hint value might also
be used with URIs or icon names.

As per freedesktop standard:
  The "app_icon" parameter and "image-path" hint should be either an URI
  (file:// is the only URI schema supported right now) or a name in a
  freedesktop.org-compliant icon theme (not a GTK+ stock ID).

Thus the image-path hint should also be parsed as it happens for the
app_icon.

Reuse same logic, by falling back on _iconForNotificationData with the
hint value.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/285

(cherry picked from commit 33b8537bf5)
2019-01-11 11:30:26 +00:00
420c1cbfd1 dash: destroy items's child before tooltip
Destroy the DashItemContainer's child from the same handler as the tooltip. This
will prevent invalid reads when the item is destroyed while its quicklist is
still open.

Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/781

(cherry picked from commit ff2fbf5ae4)
2019-01-11 11:30:26 +00:00
d53bd98532 StWidget: don't forget to invalidate the paint state if not on stage
If the actor is not on the stage yet (i.e. does not have a theme
node), but has a paint state cached, we currently fail to invalidate
it, which will lead to the actor painting with old contents once it
gets onto the stage.

This commit fixes the issue by changing our invalidation strategy;
previously we were looking at the widget's own theme node to determine
if it should be invalidated or not.
Now we look at the theme nodes of our cached paint states. When the
widget is mapped on stage, those are the same as the widget's own
theme node, but when the widget is not on the stage, we'll still be
able to invalidate them.

As part of this, we move the invalidation API to StThemeNodePaintState,
which is a more natural place for our use case.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/314

(cherry picked from commit 6743c18fdf)
2019-01-11 11:30:26 +00:00
128a501b9a StTextureCache: use right event to detect file changes
StTextureCache installs file monitors that invalidate caches when
contents of the underlying file change.
At the moment, the cache uses the Gio.FileMonitorEvent.CHANGED event
type to make that determination.

However, that is suboptimal for at least two reasons:
- while a file is being written to disk, many CHANGED events will be
  emitted in sequence. That will cause needless cache invalidations,
  and we will risk loading the file before it's fully loaded.
- if an existing file is replaced, e.g. with g_file_replace(), we may
  not get a CHANGED event but a CREATED one instead, so the cache ends
  up never getting invalidated.

The good news is that in both of those cases GFileMonitor will send a
CHANGES_DONE_HINT event after changes have settled, or after the file
is replaced.

This commit fixes both cases by switching from the CHANGED event to
CHANGES_DONE_HINT to determine that a file has in fact changed.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/286

(cherry picked from commit ca3f4cfb41)
2019-01-11 11:30:26 +00:00
b29e243fec st: Avoid integer overflow on unpremultiply
When computing the effective border color, we operate on colors with
premultiplied alpha to simplify the calculations, then unpremultiply
the result. However we miss a bounds check in the last check, so any
color component can overflow the allowed maximum of 0xff and shift the
result in unexpected ways.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/305

(cherry picked from commit 925a25da17)
2019-01-11 11:30:26 +00:00
fa2ddcc52f dnd: Repick target actor if destroyed mid iteration
The picked target actor may be destroyed (e.g. hover style change
resulting in the ClutterTexture to be destroyed). If we don't handle
this, GJS will abort when it sees the exception caused by Javascript
code trying to access the destroyed target actor.

To handle it, listen on the 'destroy' signal on the target actor, and
repick, so a valid actor is passed to the next motion callback.

Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/632

(cherry picked from commit 4259676f6e)
2019-01-11 11:30:26 +00:00
fbf194f6a1 st-button: Ignore pointer emulated touch events
In X11, pointer emulated touch events are replicated with normal PRESS, RELEASE
pair events which are generated by the server. Thus for a single tap we get:
 - TOUCH_BEGIN -> TOUCH_END, PRESS -> RELEASE

This will cause st-button to send two "clicked" signals, instead of just one,
breaking extensions (like dash-to-dock) that show buttons in the main stage
which will be checked two times or that will receive the same signal two times.


(cherry picked from commit 4c11d15a07)
2018-11-26 21:22:10 +00:00
5610a2435d iconGrid: Defer and group animation cleanup
The `reactive` property of icon actors was being restored 24 times over
the course of the spring animation, all at slightly different times as
each icon finished animating at different times.

The problem is that toggling `reactive` on an `StWidget` incurs a style
change of the `insensitive` pseudo class, and style changes would quickly
queue relayouts incurring full stage reallocation. This occurred many times
during a spring animation hogging the CPU and limiting the frame rate.

The solution is defer and batch the cleanup for all icons until after the
last icon has finished animating. This way the CPU impact of the style
change and stage relayout isn't felt during the animation so the frame
rate remains higher and smoother. The overall CPU usage of the animation
is also reduced as the remaining relayouts are much more likely to be
grouped into a single frame.

Icon spring animation performance on an i7-7700:
Before: 83% CPU and 47 FPS
After : 78% CPU and 54 FPS
which is about a 22% increase in performance per clock (FPS/CPU).

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/253


(cherry picked from commit a5e6dd52d2)
2018-11-20 19:52:16 +00:00
a5b36fc7f4 osdWindow: Disconnect signals on destroy
Since we started to show OSD windows on all monitors, OSD windows are
destroyed when the corresponding monitor is disconnected. We shouldn't
leave any signal handlers around in that case - they prevent the object
from being garbage collected, and trigger warnings for accessing proper-
ties of invalidated GObjects.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/602
2018-10-30 13:13:50 +01:00
923d80bba8 Updated Czech translation 2018-10-07 14:32:30 +02:00
9e196d2765 workspace: Avoid setting an undefined width
Since commit c04289853f the `width` parameter may be undefined, but
it is still set unconditionally, whoops.
2018-09-04 17:30:56 +02:00
94897492be calendar: chain up to parent on _onDestroy
(cherry picked from commit 5bca4a884e)
2018-09-03 23:39:40 +00:00
6baf82eb83 messageList: stop syncing if closeButton has been destroyed
The _sync function for Message only updates the close button visibility,
so we can safely stop doing that if the close button get get destroyed earlier
(as it happens when clicking on it).

https://bugzilla.gnome.org/show_bug.cgi?id=791233


(cherry picked from commit 87da623d86)
2018-09-03 23:38:47 +00:00
65d27aaa43 automountManager: remove allowAutorun expire timeout on volume removal
If the volume is removed before AUTORUN_EXPIRE_TIMEOUT_SECS seconds, we can stop
the timeout earlier as there's nothing to unset, while the volume instance
won't be valid anymore.

https://bugzilla.gnome.org/show_bug.cgi?id=791233


(cherry picked from commit 9c41736a81)
2018-09-03 23:38:17 +00:00
176aaa4a97 extensionSystem: Unset stylesheet file reference when unloaded
We must remove the GFile reference from the representing object when an
extension has been unloaded as this won't be used anymore later (e.g. as cached
ref).


(cherry picked from commit 72f5802be9)
2018-09-03 23:36:00 +00:00
5ae5811155 js/main: Throw error if no valid default stylesheet is found
Throw an error using an informative message in case a mode uses a stylesheet
that can't be loaded, instead of crashing later because the theming can't be
properly computed, and thus the minimum size of the actors.


(cherry picked from commit 30cb2127a1)
2018-09-03 23:35:30 +00:00
e027af9548 extensionSystem: Unload stylesheet if extension is not loaded
We should not keep any reference to an extension custom stylesheet in case we
got an error while enabling that


(cherry picked from commit 3aea290adc)
2018-09-03 23:34:54 +00:00
73649a0d6a extensionSystem: Don't load an extension with invalid stylesheet
We currently assign the stylesheet to an extension whenever the file exists,
regardless of whether it actually loaded successfully or not.
And thus we load an extension that ships a stylesheet even if that file can't
be used.

There is no point in trying to load an extension if its stylesheet wasn't
loaded in the first place, so make sure this happens only on success.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/188


(cherry picked from commit 5b3ff7184e)
2018-09-03 23:34:26 +00:00
7dbcd26619 network: Don't assume the active connection has been processed first
`NMConnectionDevice._sync()` is responsible for setting up the active
connection that we'll end up displaying. It expects the active
connection to already be in a map `_connectionItems`. If it isn't in
there, we get a null dereference and the indicator can get into a weird
state where it doesn't display devices / connections properly.

Let's change this expectation. If there is an active connection,
`_deviceAdded()` will eventually get to it and call `_sync()` to set up
the active connection state. We make `_sync()` tolerate there being no
active connection when it's called.

Closes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/140


(cherry picked from commit 5d61e2563d)
2018-09-03 23:34:07 +00:00
f30ec4a4c8 workspace: Don't initially hide the title of window overlays
To be able to read the properties of the title correctly during the
first relayout of the overlay, the title, just like the border, can't be
hidden. Otherwise the title can be misaligned some pixels to the left
sometimes.

This slighty worsens the issue that windows moved to a separate
workspace using DND will show an overlay when the workspace is shown in
the overview even though no window is pointed at. Before this commit,
only the border would be visible for windows moved to another workspace,
now the title also is.
2018-09-04 01:18:00 +02:00
c04289853f workspace: Avoid setting overlay title width
Avoid setting the width of the overlay title ourselves to keep the
default width of -1, this way StLabel will change its width by itself as
soon as the text is updated.

The width only needs to be changed if the window title changes, and we
don't animate it in this case anyway so there's no need to pass a width
to _animateOverlayActor().

Setting the title width to the preferred width on relayout is impossible
because get_preferred_width() will always return the width we set the
label to before. If the width is not set to -1, there's no way to get
the new preferred width without calculating it ourselves from the
underlying ClutterText instance.

https://bugzilla.gnome.org/show_bug.cgi?id=787260
2018-09-04 01:18:00 +02:00
b72b773d87 search: Ignore search provider results metas if search is cancelled
When a search has been cancelled, it is expected that providers don't
return the requested number of results, so don't log a warning in that
case.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/205
2018-09-04 01:12:24 +02:00
da7cd2807f search: Cancel search provider operations on clear
Ensure that the search provider operations (just getResultMetas requests
in the current implementation) in progress are properly cancelled when we
clear the UI, otherwise returned results might still be added when not
needed.

This is triggered for each provider by the SearchResults reset.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/205
2018-09-04 01:12:12 +02:00
20373ba64e viewSelector: Cancel search on overview hidden
Currently when the overview is hidden, any pending search is kept alive,
not only at remote search provider level (as per issue #183), but even
the shell providers proxies continue to get and process data. This happens
even if this is not needed anymore, while the UI reset is performed only
next time that the overview is shown (causing some more computation
presentation time).

In order to stop this to happen, when the overview is hidden, we have to
unset the search entry to an empty value as this would make SearchResults
to have empty terms list and that would make the proxies cancellable to
be triggered (without causing any further search to start).

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/205
2018-09-04 01:12:04 +02:00
025f6eb68e objectManager: correct other invalid index code in onNameVanished
The object manager tries to synthesize interface removal
events if the bus name of a remote object drops off the bus.

The code had bad typos in it, though: it reuses the `i`
index variable in its inner loop, where it should be using
the `j` index variable.

This commit corrects the i/j confusion.
2018-09-04 01:11:40 +02:00
dc5df5c4c9 objectManager: correct invalid index code in onNameVanished
The object manager tries to synthesize interface removal
events if the bus name of a remote object drops off the bus.

The code has a bad typo in it, though: it confuses `objectPaths`
(the list of all object paths) and `objectPath` (the object
currently being processed this iteration of the loop).

That leads to a failure to synthesize the interface removal
events, and spew in the log.

This commit corrects the objectPath/objectPaths confusion.
2018-09-04 01:11:40 +02:00
81db908339 layoutManager: Return null monitor if focusIndex is invalid
https://bugzilla.gnome.org/show_bug.cgi?id=788882


(cherry picked from commit 996dd74157)
2018-08-31 14:40:35 +00:00
706a2259b8 windowManager: Don't animate unmanaged windows on (un)minimization
(cherry picked from commit 878946962d)
2018-08-31 14:40:01 +00:00
e94af71430 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


(cherry picked from commit 19e864ed3b)
2018-08-31 14:39:12 +00:00
a662e7bb87 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


(cherry picked from commit c9bf72c5c4)
2018-08-31 14:38:54 +00:00
0b82388c49 overviewControls: Sync hover after drag operations
During global grabs, actors miss enter and leave events required
for correct hover tracking. This can cause the workspace switcher
to get stuck while slid out, so ensure the actor's hover state is
synced after drag operations.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/161


(cherry picked from commit 328c63bf64)
2018-08-31 14:28:11 +00:00
b359b937e9 layout: Mark chrome container as NO_LAYOUT
Showing and hiding children does not affect the allocation of the uiGroup
nor its other children. We can avoid full relayout/redraw in those
situations.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/197


(cherry picked from commit 73d8c82640)
2018-08-31 14:27:15 +00:00
98fb7c33f2 windowManager: Declare variables
Fixes warnings from GJS.


(cherry picked from commit 2f76951658)
2018-08-31 14:22:21 +00:00
4dfc2e0fd1 st-texture-cache: Obey cache policy in st_texture_cache_load
https://bugzilla.gnome.org/show_bug.cgi?id=663461


(cherry picked from commit 50e849a186)
2018-08-31 14:15:30 +00:00
9152d3a286 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.


(cherry picked from commit ab4c72d758)
2018-08-31 14:11:58 +00:00
ba33a05dd2 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.


(cherry picked from commit 86a520b880)
2018-08-31 14:11:05 +00:00
ddb309815c 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.


(cherry picked from commit 4bf033a885)
2018-08-31 14:08:57 +00:00
6a796675bd 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


(cherry picked from commit 0dee82fb9f)
2018-08-31 13:48:21 +00:00
d08497414f workspace: Fix infinite loop when finding parent window of dialogs
When a dialog is added to a window while the overview is shown, we get
its parent using get_transient_for() so we can add it to the right
window clone.

If we have multiple layers of dialogs we have to do this recursively
until we find the root ancestor. This case currently results in an
infinite loop: Since parent is always set to the same window, the
while-condition will always be true.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/180


(cherry picked from commit 52cbc299a7)
2018-08-30 02:39:37 +00:00
82886b7ee8 overview: Use whole stage size for cover pane
We show a cover pane on top of the overview during transitions to
prevent issues caused by clicks and mouseover events when the overview
is not ready. Right now, this pane is only being shown on the primary
monitor, which obviosly allows interactions to happen before the
animations are finished on the secondary monitors.

To fix this, use the size of the whole stage for the cover pane.


(cherry picked from commit 02d06bb1f3)
2018-08-30 02:37:28 +00:00
dca43c7b24 st: Use ClutterClickAction on StEntry primary/secondary icons
This makes them work on touchscreens as well.

Closes: #116


(cherry picked from commit dd59212d3f)
2018-08-19 21:12:22 +00:00
af50a7829f runDialog: Use ClutterText::activate for enter handling
Instead of consuming the event in front of the input method. Enter
is sometimes overriden by those, so it seems better to let the IM
handle the key event, and react later to it if it got propagated
anyway. That is what ::activate does, so use this signal.

This used to work before ClutterInputMethod/InputFocus because the
IM received the events directly from stage captured events. This
is not the case anymore.

Closes: #440


(cherry picked from commit 3ab9e9e8ad)
2018-08-19 21:11:37 +00:00
67cb02d46a Revert "workspaceThumbnail: rebuild thumbnails if workareas size changed"
It is unclear what the change was supposed to be fixing, but it
broke animations of workspace additions and removals, as those
events trigger the ::workareas-changed signal.

This reverts commit c29bd46e7a.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/162
2018-08-19 15:12:28 +02:00
721ce54037 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


(cherry picked from commit 905801b178)
2018-07-31 00:17:49 +00:00
445eed40a7 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


(cherry picked from commit 2e90c5fa4b)
2018-07-31 00:14:53 +00:00
fddd122956 gdm, util: Always allow to retry login in unlock mode
When in lockscreen mode there's no point of resetting the auth login as there's
no welcome screen, and that would just cause the UI to freeze, with no reason.
This could have been useful if we were stopping the user to login for a given
time after ALLOWED_FAILURES attempts, but this is not the case yet.


(cherry picked from commit cf69fe4b18)
2018-07-25 20:38:58 +00:00
df1b46eee2 authPrompt: Do not enable sensitivity if retries are disallowed
Set the sensitivity of the UI according to the canRetry parameter and thus
if no more logins are allowed don't take any input.

Fixes #311


(cherry picked from commit 8f848925f6)
2018-07-25 20:37:42 +00:00
bf318df7f3 authPrompt: Unset preemptiveAnswer on reset
When we get a reset signal the preemptiveAnswer should be also unset or it will
be used next time the user authPrompt will be activated, even without any further
user interaction.

Fixes #311


(cherry picked from commit d21657fe61)
2018-07-25 20:37:20 +00:00
2a2f3c981e workspaceThumbnail: Sync clone position changes with actor
We need to update the clone position if window actor (not the meta window)
position changed.

https://bugzilla.gnome.org/show_bug.cgi?id=776588
2018-07-24 13:11:39 +02:00
8e5eab0498 workspace: Recompute bounding box on window 'position-changed'
We need to update the clone position if window size changed
also, rename meta window 'size-changed' callback accordingly.

https://bugzilla.gnome.org/show_bug.cgi?id=792681
2018-07-24 13:11:39 +02:00
56 changed files with 489 additions and 306 deletions

27
NEWS
View File

@ -1,3 +1,30 @@
3.28.4
======
* Fix wrong window positions in overview on wayland [Marco; #776588]
* overview: Fix handling of confirmation dialogs on wayland [verdre; !180]
* Avoid some full relayout/redraws [Carlos; !197]
* Keep workspace switcher slid out when workspaces are in use [Florian; !161]
* Cancel search on overview hiding [Marco; !205]
* Fix disappearing network icon [Iain; #140]
* Improve performance of app icon animations [Daniel; !253]
* notifications: Support icon theme names in 'image-path' hint [Marco; !285]
* Avoid focus changes when updating keyboard options [Takao; #391]
* Fix unresponsive-app dialog blocking input in other windows [Florian; #273]
* Fix ellipsization in dialog subtitles/bodies [Marco; !531]
* Misc. bug fixes [Marco, Andrea, Florian, Jasper, Sam, verdre, Jonas,
Cosimo, Carlos; #792681, #372, !112, !162, #414, #663461, #788882, #787260,
!188, #791233, #602, #632, !305, !286, !314, #781, #693, #618, #430, #799,
#783, !293, #298, #1015, #539, #1270]
Contributors:
Jonas Ådahl, Andrea Azzarone, Cosimo Cecchi, Takao Fujiwara, Carlos Garnacho,
Iain Lane, Florian Müllner, Georges Basile Stavracas Neto, Jasper St. Pierre,
Sam Spilsbury, Ray Strode, Will Thompson, Marco Trevisan (Treviño), verdre,
Daniel van Vugt
Translators:
Marek Černocký [cs]
3.28.3
======
* Fix lagging pointer when zoomed [Daniel; #682013]

View File

@ -39,7 +39,7 @@
</description>
</key>
<key name="favorite-apps" type="as">
<default>[ 'firefox.desktop', 'evolution.desktop', 'rhythmbox.desktop', 'shotwell.desktop', 'org.gnome.Nautilus.desktop', 'org.gnome.Software.desktop' ]</default>
<default>[ 'epiphany.desktop', 'evolution.desktop', 'rhythmbox.desktop', 'shotwell.desktop', 'org.gnome.Nautilus.desktop', 'org.gnome.Software.desktop' ]</default>
<summary>List of desktop file IDs for favorite applications</summary>
<description>
The applications corresponding to these identifiers

View File

@ -824,8 +824,6 @@ StScrollBar {
.screencast-indicator { color: $warning_color; }
.remote-access-indicator { color: $warning_color; }
&.solid {
background-color: black;
/* transition from transparent to solid */

View File

@ -242,11 +242,11 @@ var AuthPrompt = new Lang.Class({
this.emit('prompted');
},
_onVerificationFailed() {
_onVerificationFailed(userVerifier, canRetry) {
this._queryingService = null;
this.clear();
this.updateSensitivity(true);
this.updateSensitivity(canRetry);
this.setActorInDefaultButtonWell(null);
this.verificationStatus = AuthPromptStatus.VERIFICATION_FAILED;
},
@ -439,6 +439,7 @@ var AuthPrompt = new Lang.Class({
this.verificationStatus = AuthPromptStatus.NOT_VERIFYING;
this.cancelButton.reactive = true;
this.nextButton.label = _("Next");
this._preemptiveAnswer = null;
if (this._userVerifier)
this._userVerifier.cancel();

View File

@ -534,12 +534,13 @@ var ShellUserVerifier = new Lang.Class({
_verificationFailed(retry) {
// For Not Listed / enterprise logins, immediately reset
// the dialog
// Otherwise, we allow ALLOWED_FAILURES attempts. After that, we
// go back to the welcome screen.
// Otherwise, when in login mode we allow ALLOWED_FAILURES attempts.
// After that, we go back to the welcome screen.
this._failCounter++;
let canRetry = retry && this._userName &&
this._failCounter < this._settings.get_int(ALLOWED_FAILURES_KEY);
(this._reauthOnly ||
this._failCounter < this._settings.get_int(ALLOWED_FAILURES_KEY));
if (canRetry) {
if (!this.hasPendingMessages) {
@ -562,7 +563,7 @@ var ShellUserVerifier = new Lang.Class({
}
}
this.emit('verification-failed');
this.emit('verification-failed', canRetry);
},
_onConversationStopped(client, serviceName) {

View File

@ -130,7 +130,6 @@
<file>ui/status/rfkill.js</file>
<file>ui/status/volume.js</file>
<file>ui/status/bluetooth.js</file>
<file>ui/status/remoteAccess.js</file>
<file>ui/status/screencast.js</file>
<file>ui/status/system.js</file>
<file>ui/status/thunderbolt.js</file>

View File

@ -205,7 +205,7 @@ var IBusManager = new Lang.Class({
}
this._ibus.set_global_engine_async(id, this._MAX_INPUT_SOURCE_ACTIVATION_TIME,
null, callback);
null, callback || null);
},
preloadEngines(ids) {

View File

@ -236,11 +236,12 @@ var ObjectManager = new Lang.Class({
_onNameVanished() {
let objectPaths = Object.keys(this._objects);
for (let i = 0; i < objectPaths.length; i++) {
let object = this._objects[objectPaths];
let objectPath = objectPaths[i];
let object = this._objects[objectPath];
let interfaceNames = Object.keys(object);
for (let j = 0; i < interfaceNames.length; i++) {
let interfaceName = interfaceNames[i];
for (let j = 0; j < interfaceNames.length; j++) {
let interfaceName = interfaceNames[j];
if (object[interfaceName])
this._removeInterface(objectPath, interfaceName);

View File

@ -41,7 +41,6 @@ const RENAMED_DESKTOP_IDS = {
'gnotravex.desktop': 'gnome-tetravex.desktop',
'gnotski.desktop': 'gnome-klotski.desktop',
'gtali.desktop': 'tali.desktop',
'mozilla-firefox.desktop': 'firefox.desktop',
'nautilus.desktop': 'org.gnome.Nautilus.desktop',
'polari.desktop': 'org.gnome.Polari.desktop',
'totem.desktop': 'org.gnome.Totem.desktop',

View File

@ -264,7 +264,7 @@ var Background = new Lang.Class({
(lm, aboutToSuspend) => {
if (aboutToSuspend)
return;
this.emit('changed');
this._refreshAnimation();
});
this._settingsChangedSignalId = this._settings.connect('changed', () => {

View File

@ -802,6 +802,8 @@ var NotificationMessage = new Lang.Class({
},
_onDestroy() {
this.parent();
if (this._updatedId)
this.notification.disconnect(this._updatedId);
this._updatedId = 0;

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,10 @@ var CloseDialog = new Lang.Class({
this.parent();
this._window = window;
this._dialog = null;
this._tracked = undefined;
this._timeoutId = 0;
this._windowFocusChangedId = 0;
this._keyFocusChangedId = 0;
},
get window() {
@ -93,10 +99,57 @@ var CloseDialog = new Lang.Class({
this.response(Meta.CloseDialogResponse.FORCE_CLOSE);
},
_onFocusChanged() {
if (Meta.is_wayland_compositor())
return;
let focusWindow = global.display.focus_window;
let keyFocus = global.stage.key_focus;
let shouldTrack;
if (focusWindow != null)
shouldTrack = focusWindow == this._window;
else
shouldTrack = keyFocus && this._dialog.contains(keyFocus);
if (this._tracked === shouldTrack)
return;
if (shouldTrack)
Main.layoutManager.trackChrome(this._dialog,
{ affectsInputRegion: true });
else
Main.layoutManager.untrackChrome(this._dialog);
// The buttons are broken when they aren't added to the input region,
// so disable them properly in that case
this._dialog.buttonLayout.get_children().forEach(b => {
b.reactive = shouldTrack;
});
this._tracked = shouldTrack;
},
vfunc_show() {
if (this._dialog != null)
return;
Meta.disable_unredirect_for_screen(global.screen);
this._timeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, ALIVE_TIMEOUT,
() => {
this._window.check_alive(global.display.get_current_time_roundtrip());
return GLib.SOURCE_CONTINUE;
});
this._windowFocusChangedId =
global.display.connect('notify::focus-window',
this._onFocusChanged.bind(this));
this._keyFocusChangedId =
global.stage.connect('notify::key-focus',
this._onFocusChanged.bind(this));
this._addWindowEffect();
this._initDialog();
@ -107,9 +160,7 @@ var CloseDialog = new Lang.Class({
{ scale_y: 1,
transition: 'linear',
time: DIALOG_TRANSITION_TIME,
onComplete: () => {
Main.layoutManager.trackChrome(this._dialog, { affectsInputRegion: true });
}
onComplete: this._onFocusChanged.bind(this)
});
},
@ -117,6 +168,17 @@ var CloseDialog = new Lang.Class({
if (this._dialog == null)
return;
Meta.enable_unredirect_for_screen(global.screen);
GLib.source_remove(this._timeoutId);
this._timeoutId = 0;
global.display.disconnect(this._windowFocusChangedId)
this._windowFocusChangedId = 0;
global.stage.disconnect(this._keyFocusChangedId);
this._keyFocusChangedId = 0;
let dialog = this._dialog;
this._dialog = null;
this._removeWindowEffect();

View File

@ -210,6 +210,10 @@ var AutomountManager = new Lang.Class({
},
_onVolumeRemoved(monitor, volume) {
if (volume._allowAutorunExpireId && volume._allowAutorunExpireId > 0) {
Mainloop.source_remove(volume._allowAutorunExpireId);
delete volume._allowAutorunExpireId;
}
this._volumeQueue =
this._volumeQueue.filter(element => (element != volume));
},
@ -234,8 +238,10 @@ var AutomountManager = new Lang.Class({
_allowAutorunExpire(volume) {
let id = Mainloop.timeout_add_seconds(AUTORUN_EXPIRE_TIMEOUT_SECS, () => {
volume.allowAutorun = false;
delete volume._allowAutorunExpireId;
return GLib.SOURCE_REMOVE;
});
volume._allowAutorunExpireId = id;
GLib.Source.set_name_by_id(id, '[gnome-shell] volume.allowAutorun');
}
});

View File

@ -52,6 +52,8 @@ var DashItemContainer = new Lang.Class({
this.animatingOut = false;
this.connect('destroy', () => {
if (this.child != null)
this.child.destroy();
this.label.destroy();
});
},

View File

@ -183,7 +183,7 @@ var MessageDialogContent = new Lang.Class({
this[`_${prop}`].add_style_class_name(`message-dialog-${prop}`);
});
let textProps = { ellipsize_mode: Pango.EllipsizeMode.NONE,
let textProps = { ellipsize: Pango.EllipsizeMode.NONE,
line_wrap: true };
Object.assign(this._subtitle.clutter_text, textProps);
Object.assign(this._body.clutter_text, textProps);

View File

@ -125,6 +125,16 @@ var _Draggable = new Lang.Class({
},
_onTouchEvent(actor, event) {
// Here we only handle touch events on wayland. On X11
// we do get emulated pointer events, which already works
// for single-touch cases. Besides, the X11 passive touch grab
// set up by Mutter will make us see first the touch events
// and later the pointer events, so it will look like two
// unrelated series of events, we want to avoid double handling
// in these cases.
if (!Meta.is_wayland_compositor())
return Clutter.EVENT_PROPAGATE;
if (event.type() != Clutter.EventType.TOUCH_BEGIN ||
!global.display.is_pointer_emulating_sequence(event.get_event_sequence()))
return Clutter.EVENT_PROPAGATE;
@ -396,10 +406,15 @@ var _Draggable = new Lang.Class({
return true;
},
_pickTargetActor() {
return this._dragActor.get_stage().get_actor_at_pos(Clutter.PickMode.ALL,
this._dragX, this._dragY);
},
_updateDragHover() {
this._updateHoverId = 0;
let target = this._dragActor.get_stage().get_actor_at_pos(Clutter.PickMode.ALL,
this._dragX, this._dragY);
let target = this._pickTargetActor();
let dragEvent = {
x: this._dragX,
y: this._dragY,
@ -407,6 +422,18 @@ var _Draggable = new Lang.Class({
source: this.actor._delegate,
targetActor: target
};
let targetActorDestroyHandlerId;
let handleTargetActorDestroyClosure;
handleTargetActorDestroyClosure = () => {
target = this._pickTargetActor();
dragEvent.targetActor = target;
targetActorDestroyHandlerId =
target.connect('destroy', handleTargetActorDestroyClosure);
};
targetActorDestroyHandlerId =
target.connect('destroy', handleTargetActorDestroyClosure);
for (let i = 0; i < dragMonitors.length; i++) {
let motionFunc = dragMonitors[i].dragMotion;
if (motionFunc) {
@ -417,6 +444,7 @@ var _Draggable = new Lang.Class({
}
}
}
dragEvent.targetActor.disconnect(targetActorDestroyHandlerId);
while (target) {
if (target._delegate && target._delegate.handleDragOver) {

View File

@ -760,7 +760,7 @@ var EndSessionDialog = new Lang.Class({
let updatePrepared = this._pkOfflineProxy.UpdatePrepared;
let updatesAllowed = this._updatesPermission && this._updatesPermission.allowed;
_setCheckBoxLabel(this._checkBox, dialogContent.checkBoxText);
_setCheckBoxLabel(this._checkBox, dialogContent.checkBoxText || '');
this._checkBox.actor.visible = (dialogContent.checkBoxText && updatePrepared && updatesAllowed);
this._checkBox.actor.checked = (updatePrepared && updateTriggered);

View File

@ -76,6 +76,7 @@ function disableExtension(uuid) {
if (extension.stylesheet) {
let theme = St.ThemeContext.get_for_stage(global.stage).get_theme();
theme.unload_stylesheet(extension.stylesheet);
delete extension.stylesheet;
}
try {
@ -115,13 +116,18 @@ function enableExtension(uuid) {
extensionOrder.push(uuid);
let stylesheetNames = [global.session_mode + '.css', 'stylesheet.css'];
let theme = St.ThemeContext.get_for_stage(global.stage).get_theme();
for (let i = 0; i < stylesheetNames.length; i++) {
let stylesheetFile = extension.dir.get_child(stylesheetNames[i]);
if (stylesheetFile.query_exists(null)) {
let theme = St.ThemeContext.get_for_stage(global.stage).get_theme();
try {
let stylesheetFile = extension.dir.get_child(stylesheetNames[i]);
theme.load_stylesheet(stylesheetFile);
extension.stylesheet = stylesheetFile;
break;
} catch (e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND))
continue; // not an error
log(`Failed to load stylesheet for extension ${uuid}: ${e.message}`);
return;
}
}
@ -131,6 +137,10 @@ function enableExtension(uuid) {
_signals.emit('extension-state-changed', extension);
return;
} catch(e) {
if (extension.stylesheet) {
theme.unload_stylesheet(extension.stylesheet);
delete extension.stylesheet;
}
logExtensionError(uuid, e);
return;
}

View File

@ -418,6 +418,11 @@ var IconGrid = new Lang.Class({
},
_animationDone() {
this._clonesAnimating.forEach(clone => {
clone.source.reactive = true;
clone.source.opacity = 255;
clone.destroy();
});
this._clonesAnimating = [];
this.emit('animation-done');
},
@ -538,10 +543,6 @@ var IconGrid = new Lang.Class({
onComplete: () => {
if (isLastItem)
this._animationDone();
actor.opacity = 255;
actor.reactive = true;
actorClone.destroy();
}};
fadeParams = { time: ANIMATION_FADE_IN_TIME_FOR_ITEM,
transition: 'easeInOutQuad',
@ -562,12 +563,8 @@ var IconGrid = new Lang.Class({
scale_x: scaleX,
scale_y: scaleY,
onComplete: () => {
if (isLastItem) {
if (isLastItem)
this._animationDone();
this._restoreItemsOpacity();
}
actor.reactive = true;
actorClone.destroy();
}};
fadeParams = { time: ANIMATION_FADE_IN_TIME_FOR_ITEM,
transition: 'easeInOutQuad',
@ -581,12 +578,6 @@ var IconGrid = new Lang.Class({
}
},
_restoreItemsOpacity() {
for (let index = 0; index < this._items.length; index++) {
this._items[index].actor.opacity = 255;
}
},
_getAllocatedChildSizeAndSpacing(child) {
let [,, natWidth, natHeight] = child.get_preferred_size();
let width = Math.min(this._getHItemSize(), natWidth);

View File

@ -533,17 +533,25 @@ var FocusTracker = new Lang.Class({
},
_setCurrentRect(rect) {
let frameRect = this._currentWindow.get_frame_rect();
rect.x -= frameRect.x;
rect.y -= frameRect.y;
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 frameRect = this._currentWindow.get_frame_rect();
let rect = { x: this._rect.x + frameRect.x, y: this._rect.y + frameRect.y, width: this._rect.width, height: this._rect.height };
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;
}
@ -916,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;

View File

@ -203,6 +203,7 @@ var LayoutManager = new Lang.Class({
// Set up stage hierarchy to group all UI actors under one container.
this.uiGroup = new Shell.GenericContainer({ name: 'uiGroup' });
this.uiGroup.set_flags(Clutter.ActorFlags.NO_LAYOUT);
this.uiGroup.connect('allocate', (actor, box, flags) => {
let children = actor.get_children();
for (let i = 0; i < children.length; i++)
@ -557,6 +558,8 @@ var LayoutManager = new Lang.Class({
},
get focusMonitor() {
if (this.focusIndex < 0)
return null;
return this.monitors[this.focusIndex];
},

View File

@ -207,13 +207,7 @@ function _initializeUI() {
return true;
});
global.display.connect('gl-video-memory-purged', () => {
let cache = St.TextureCache.get_default();
cache.clear();
loadTheme();
});
global.display.connect('gl-video-memory-purged', loadTheme);
// Provide the bus object for gnome-session to
// initiate logouts.
@ -349,6 +343,9 @@ function loadTheme() {
let theme = new St.Theme ({ application_stylesheet: _cssStylesheet,
default_stylesheet: _defaultCssStylesheet });
if (theme.default_stylesheet == null)
throw new Error("No valid stylesheet found for '%s'".format(sessionMode.stylesheetName));
if (previousTheme) {
let customStylesheets = previousTheme.get_custom_stylesheets();

View File

@ -362,7 +362,8 @@ var Message = new Lang.Class({
this.setBody(body);
this._closeButton.connect('clicked', this.close.bind(this));
this.actor.connect('notify::hover', this._sync.bind(this));
let actorHoverId = this.actor.connect('notify::hover', this._sync.bind(this));
this._closeButton.connect('destroy', this.actor.disconnect.bind(this.actor, actorHoverId));
this.actor.connect('clicked', this._onClicked.bind(this));
this.actor.connect('destroy', this._onDestroy.bind(this));
this._sync();

View File

@ -1320,6 +1320,7 @@ var MessageTray = new Lang.Class({
this._bannerBin.y = -this._banner.actor.height;
this.actor.show();
Meta.disable_unredirect_for_screen(global.screen);
this._updateShowingNotification();
let [x, y, mods] = global.get_pointer();
@ -1457,6 +1458,7 @@ var MessageTray = new Lang.Class({
this._pointerInNotification = false;
this._notificationRemoved = false;
Meta.enable_unredirect_for_screen(global.screen);
this._banner.actor.destroy();
this._banner = null;

View File

@ -117,10 +117,8 @@ var FdoNotificationDaemon = new Lang.Class({
bitsPerSample, nChannels, data] = hints['image-data'];
return Shell.util_create_pixbuf_from_data(data, GdkPixbuf.Colorspace.RGB, hasAlpha,
bitsPerSample, width, height, rowStride);
} else if (hints['image-path']) {
return new Gio.FileIcon({ file: Gio.File.new_for_path(hints['image-path']) });
}
return null;
return this._iconForNotificationData(hints['image-path']);
},
_fallbackIconForNotificationData(hints) {

View File

@ -108,15 +108,30 @@ var OsdWindow = new Lang.Class({
this._hideTimeoutId = 0;
this._reset();
Main.layoutManager.connect('monitors-changed',
this._relayout.bind(this));
this.actor.connect('destroy', this._onDestroy.bind(this));
this._monitorsChangedId =
Main.layoutManager.connect('monitors-changed',
this._relayout.bind(this));
let themeContext = St.ThemeContext.get_for_stage(global.stage);
themeContext.connect('notify::scale-factor',
this._relayout.bind(this));
this._scaleChangedId =
themeContext.connect('notify::scale-factor',
this._relayout.bind(this));
this._relayout();
Main.uiGroup.add_child(this.actor);
},
_onDestroy() {
if (this._monitorsChangedId)
Main.layoutManager.disconnect(this._monitorsChangedId);
this._monitorsChangedId = 0;
let themeContext = St.ThemeContext.get_for_stage(global.stage);
if (this._scaleChangedId)
themeContext.disconnect(this._scaleChangedId);
this._scaleChangedId = 0;
},
setIcon(icon) {
this._icon.gicon = icon;
},

View File

@ -393,10 +393,8 @@ var Overview = new Lang.Class({
if (!Main.layoutManager.primaryMonitor)
return;
let workArea = Main.layoutManager.getWorkAreaForMonitor(Main.layoutManager.primaryIndex);
this._coverPane.set_position(0, workArea.y);
this._coverPane.set_size(workArea.width, workArea.height);
this._coverPane.set_position(0, 0);
this._coverPane.set_size(global.screen_width, global.screen_height);
this._updateBackgrounds();
},

View File

@ -284,6 +284,11 @@ var ThumbnailsSlider = new Lang.Class({
return child.get_theme_node().get_length('visible-width');
},
_onDragEnd() {
this.actor.sync_hover();
this.parent();
},
_getSlide() {
if (!this._visible)
return 0;

View File

@ -709,7 +709,6 @@ var AggregateMenu = new Lang.Class({
this._bluetooth = null;
}
this._remoteAccess = new imports.ui.status.remoteAccess.RemoteAccessApplet();
this._power = new imports.ui.status.power.Indicator();
this._rfkill = new imports.ui.status.rfkill.Indicator();
this._volume = new imports.ui.status.volume.Indicator();
@ -730,7 +729,6 @@ var AggregateMenu = new Lang.Class({
if (this._bluetooth) {
this._indicators.add_child(this._bluetooth.indicators);
}
this._indicators.add_child(this._remoteAccess.indicators);
this._indicators.add_child(this._rfkill.indicators);
this._indicators.add_child(this._volume.indicators);
this._indicators.add_child(this._power.indicators);
@ -745,7 +743,6 @@ var AggregateMenu = new Lang.Class({
if (this._bluetooth) {
this.menu.addMenuItem(this._bluetooth.menu);
}
this.menu.addMenuItem(this._remoteAccess.menu);
this.menu.addMenuItem(this._location.menu);
this.menu.addMenuItem(this._rfkill.menu);
this.menu.addMenuItem(this._power.menu);
@ -799,6 +796,7 @@ var Panel = new Lang.Class({
this.actor.connect('get-preferred-height', this._getPreferredHeight.bind(this));
this.actor.connect('allocate', this._allocate.bind(this));
this.actor.connect('button-press-event', this._onButtonPress.bind(this));
this.actor.connect('touch-event', this._onButtonPress.bind(this));
this.actor.connect('key-press-event', this._onKeyPress.bind(this));
Main.overview.connect('showing', () => {
@ -942,8 +940,13 @@ var Panel = new Lang.Class({
if (event.get_source() != actor)
return Clutter.EVENT_PROPAGATE;
let button = event.get_button();
if (button != 1)
let type = event.type();
let isPress = type == Clutter.EventType.BUTTON_PRESS;
if (!isPress && type != Clutter.EventType.TOUCH_BEGIN)
return Clutter.EVENT_PROPAGATE;
let button = isPress ? event.get_button() : -1;
if (isPress && button != 1)
return Clutter.EVENT_PROPAGATE;
let focusWindow = global.display.focus_window;
@ -1082,6 +1085,7 @@ var Panel = new Lang.Class({
let windows = activeWorkspace.list_windows().filter(metaWindow => {
return metaWindow.is_on_primary_monitor() &&
metaWindow.showing_on_its_workspace() &&
!metaWindow.is_hidden() &&
metaWindow.get_window_type() != Meta.WindowType.DESKTOP;
});

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

@ -114,18 +114,16 @@ var RunDialog = new Lang.Class({
this._history = new History.HistoryManager({ gsettingsKey: HISTORY_KEY,
entry: this._entryText });
this._entryText.connect('activate', (o) => {
this.popModal();
this._run(o.get_text(),
Clutter.get_current_event().get_state() & Clutter.ModifierType.CONTROL_MASK);
if (!this._commandError ||
!this.pushModal())
this.close();
});
this._entryText.connect('key-press-event', (o, e) => {
let symbol = e.get_key_symbol();
if (symbol == Clutter.Return || symbol == Clutter.KP_Enter) {
this.popModal();
this._run(o.get_text(),
e.get_state() & Clutter.ModifierType.CONTROL_MASK);
if (!this._commandError ||
!this.pushModal())
this.close();
return Clutter.EVENT_STOP;
}
if (symbol == Clutter.Tab) {
let text = o.get_text();
let prefix;

View File

@ -192,6 +192,7 @@ var SearchResultsBase = new Lang.Class({
},
clear() {
this._cancellable.cancel();
for (let resultId in this._resultDisplays)
this._resultDisplays[resultId].actor.destroy();
this._resultDisplays = {};
@ -225,6 +226,12 @@ var SearchResultsBase = new Lang.Class({
this._cancellable.reset();
this.provider.getResultMetas(metasNeeded, metas => {
if (this._cancellable.is_cancelled()) {
if (metas.length > 0)
log(`Search provider ${this.provider.id} returned results after the request was canceled`);
callback(false);
return;
}
if (metas.length != metasNeeded.length) {
log('Wrong number of result metas returned by search provider ' + this.provider.id +
': expected ' + metasNeeded.length + ' but got ' + metas.length);

View File

@ -360,11 +360,14 @@ var InputSourceManager = new Lang.Class({
this._settings.connect('per-window-changed', this._sourcesPerWindowChanged.bind(this));
this._sourcesPerWindowChanged();
this._disableIBus = false;
this._reloading = false;
},
reload() {
this._reloading = true;
this._keyboardManager.setKeyboardOptions(this._settings.keyboardOptions);
this._inputSourcesChanged();
this._reloading = false;
},
_ibusReadyCallback(im, ready) {
@ -458,7 +461,15 @@ var InputSourceManager = new Lang.Class({
},
activateInputSource(is, interactive) {
KeyboardManager.holdKeyboard();
// The focus changes during holdKeyboard/releaseKeyboard may trick
// the client into hiding UI containing the currently focused entry.
// So holdKeyboard/releaseKeyboard are not called when
// 'set-content-type' signal is received.
// E.g. Focusing on a password entry in a popup in Xorg Firefox
// will emit 'set-content-type' signal.
// https://gitlab.gnome.org/GNOME/gnome-shell/issues/391
if (!this._reloading)
KeyboardManager.holdKeyboard();
this._keyboardManager.apply(is.xkbId);
// All the "xkb:..." IBus engines simply "echo" back symbols,
@ -473,7 +484,10 @@ var InputSourceManager = new Lang.Class({
else
engine = 'xkb:us::eng';
this._ibusManager.setEngine(engine, KeyboardManager.releaseKeyboard);
if (!this._reloading)
this._ibusManager.setEngine(engine, KeyboardManager.releaseKeyboard);
else
this._ibusManager.setEngine(engine);
this._currentInputSourceChanged(is);
if (interactive)

View File

@ -419,12 +419,14 @@ var NMConnectionDevice = new Lang.Class({
this._deactivateItem.actor.visible = this._device.state > NM.DeviceState.DISCONNECTED;
if (this._activeConnection == null) {
this._activeConnection = this._device.active_connection;
if (this._activeConnection) {
ensureActiveConnectionProps(this._activeConnection, this._client);
let item = this._connectionItems.get(this._activeConnection.connection.get_uuid());
item.setActiveConnection(this._activeConnection);
let activeConnection = this._device.active_connection;
if (activeConnection && activeConnection.connection) {
let item = this._connectionItems.get(activeConnection.connection.get_uuid());
if (item) {
this._activeConnection = activeConnection;
ensureActiveConnectionProps(this._activeConnection, this._client);
item.setActiveConnection(this._activeConnection);
}
}
}

View File

@ -1,81 +0,0 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Lang = imports.lang;
const Meta = imports.gi.Meta;
const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;
var RemoteAccessApplet = new Lang.Class({
Name: 'RemoteAccessApplet',
Extends: PanelMenu.SystemIndicator,
_init() {
this.parent();
let backend = Meta.get_backend();
let controller = backend.get_remote_access_controller();
if (!controller)
return;
// We can't possibly know about all types of screen sharing on X11, so
// showing these controls on X11 might give a false sense of security.
// Thus, only enable these controls when using Wayland, where we are
// in control of sharing.
if (!Meta.is_wayland_compositor())
return;
this._handles = new Set();
this._indicator = null;
this._menuSection = null;
controller.connect('new-handle', (controller, handle) => {
this._onNewHandle(handle);
});
},
_ensureControls() {
if (this._indicator)
return;
this._indicator = this._addIndicator();
this._indicator.icon_name = 'screen-shared-symbolic';
this._indicator.add_style_class_name('remote-access-indicator');
this._item =
new PopupMenu.PopupSubMenuMenuItem(_("Screen is Being Shared"),
true);
this._item.menu.addAction(_("Turn off"),
() => {
for (let handle of this._handles)
handle.stop();
});
this._item.icon.icon_name = 'screen-shared-symbolic';
this.menu.addMenuItem(this._item);
},
_sync() {
if (this._handles.size == 0) {
this._indicator.visible = false;
this._item.actor.visible = false;
} else {
this._indicator.visible = true;
this._item.actor.visible = true;
}
},
_onStopped(handle) {
this._handles.delete(handle);
this._sync();
},
_onNewHandle(handle) {
this._handles.add(handle);
handle.connect('stopped', this._onStopped.bind(this));
if (this._handles.size == 1) {
this._ensureControls();
this._sync();
}
},
});

View File

@ -58,6 +58,9 @@ var AltSwitcher = new Lang.Class({
childToShow = this._standard;
} else if (this._alternate.visible) {
childToShow = this._alternate;
} else {
this.actor.hide();
return;
}
let childShown = this.actor.get_child();
@ -79,7 +82,7 @@ var AltSwitcher = new Lang.Class({
global.sync_pointer();
}
this.actor.visible = (childToShow != null);
this.actor.show();
},
_onDestroy() {

View File

@ -311,6 +311,7 @@ var ViewSelector = new Lang.Class({
},
hide() {
this.reset();
this._workspacesDisplay.hide();
},
@ -459,7 +460,11 @@ var ViewSelector = new Lang.Class({
},
reset() {
global.stage.set_key_focus(null);
// Don't drop the key focus on Clutter's side if anything but the
// overview has pushed a modal (e.g. system modals when activated using
// the overview).
if (Main.modalCount <= 1)
global.stage.set_key_focus(null);
this._entry.text = '';

View File

@ -627,8 +627,8 @@ var AppSwitchAction = new Lang.Class({
if (this.get_n_current_points() == 3) {
for (let i = 0; i < this.get_n_current_points(); i++) {
[startX, startY] = this.get_press_coords(i);
[x, y] = this.get_motion_coords(i);
let [startX, startY] = this.get_press_coords(i);
let [x, y] = this.get_motion_coords(i);
if (Math.abs(x - startX) > MOTION_THRESHOLD ||
Math.abs(y - startY) > MOTION_THRESHOLD)
@ -1173,6 +1173,10 @@ var WindowManager = new Lang.Class({
yScale = geom.height / actor.height;
} else {
let monitor = Main.layoutManager.monitors[actor.meta_window.get_monitor()];
if (!monitor) {
this._minimizeWindowDone();
return;
}
xDest = monitor.x;
yDest = monitor.y;
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
@ -1248,6 +1252,11 @@ var WindowManager = new Lang.Class({
geom.height / actor.height);
} else {
let monitor = Main.layoutManager.monitors[actor.meta_window.get_monitor()];
if (!monitor) {
actor.show();
this._unminimizeWindowDone();
return;
}
actor.set_position(monitor.x, monitor.y);
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
actor.x += monitor.width;
@ -1754,6 +1763,14 @@ var WindowManager = new Lang.Class({
}
}
for (let i = 0; i < switchData.windows.length; i++) {
let w = switchData.windows[i];
w.windowDestroyId = w.window.connect('destroy', () => {
switchData.windows.splice(switchData.windows.indexOf(w), 1);
});
}
switchData.inGroup.set_position(-xDest, -yDest);
switchData.inGroup.raise_top();
@ -1784,8 +1801,8 @@ var WindowManager = new Lang.Class({
for (let i = 0; i < switchData.windows.length; i++) {
let w = switchData.windows[i];
if (w.window.is_destroyed()) // Window gone
continue;
w.window.disconnect(w.windowDestroyId);
if (w.window.get_parent() == switchData.outGroup) {
w.window.reparent(w.parent);
w.window.hide();

View File

@ -128,11 +128,10 @@ var WindowMenu = new Lang.Class({
let screen = global.screen;
let nMonitors = screen.get_n_monitors();
if (nMonitors > 1) {
let monitorIndex = window.get_monitor();
if (nMonitors > 1 && monitorIndex >= 0) {
this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
let monitorIndex = window.get_monitor();
let dir = Meta.ScreenDirection.UP;
let upMonitorIndex =
screen.get_monitor_neighbor_index(monitorIndex, dir);

View File

@ -137,8 +137,10 @@ var WindowClone = new Lang.Class({
this._dragSlot = [0, 0, 0, 0];
this._stackAbove = null;
this._windowClone._updateId = this.metaWindow.connect('size-changed',
this._onRealWindowSizeChanged.bind(this));
this._windowClone._sizeChangedId = this.metaWindow.connect('size-changed',
this._onMetaWindowSizeChanged.bind(this));
this._windowClone._posChangedId = this.metaWindow.connect('position-changed',
this._computeBoundingBox.bind(this));
this._windowClone._destroyId =
this.realWindow.connect('destroy', () => {
// First destroy the clone and then destroy everything
@ -206,8 +208,7 @@ var WindowClone = new Lang.Class({
addAttachedDialog(win) {
this._doAddAttachedDialog(win, win.get_compositor_private());
this._computeBoundingBox();
this.emit('size-changed');
this._onMetaWindowSizeChanged();
},
hasAttachedDialogs() {
@ -216,15 +217,14 @@ var WindowClone = new Lang.Class({
_doAddAttachedDialog(metaWin, realWin) {
let clone = new Clutter.Clone({ source: realWin });
clone._updateId = metaWin.connect('size-changed', () => {
this._computeBoundingBox();
this.emit('size-changed');
});
clone._sizeChangedId = metaWin.connect('size-changed',
this._onMetaWindowSizeChanged.bind(this));
clone._posChangedId = metaWin.connect('position-changed',
this._onMetaWindowSizeChanged.bind(this));
clone._destroyId = realWin.connect('destroy', () => {
clone.destroy();
this._computeBoundingBox();
this.emit('size-changed');
this._onMetaWindowSizeChanged();
});
this.actor.add_child(clone);
},
@ -321,12 +321,13 @@ var WindowClone = new Lang.Class({
else
realWindow = child.source;
realWindow.meta_window.disconnect(child._updateId);
realWindow.meta_window.disconnect(child._sizeChangedId);
realWindow.meta_window.disconnect(child._posChangedId);
realWindow.disconnect(child._destroyId);
});
},
_onRealWindowSizeChanged() {
_onMetaWindowSizeChanged() {
this._computeBoundingBox();
this.emit('size-changed');
},
@ -469,7 +470,6 @@ var WindowOverlay = new Lang.Class({
this._windowAddedId = 0;
button.hide();
title.hide();
this.title = title;
this.closeButton = button;
@ -544,12 +544,10 @@ var WindowOverlay = new Lang.Class({
let titleX = cloneX + (cloneWidth - title.width) / 2;
let titleY = cloneY + cloneHeight - (title.height - this.borderSize) / 2;
if (animate) {
this._animateOverlayActor(title, Math.floor(titleX), Math.floor(titleY), title.width);
} else {
title.width = title.width;
if (animate)
this._animateOverlayActor(title, Math.floor(titleX), Math.floor(titleY));
else
title.set_position(Math.floor(titleX), Math.floor(titleY));
}
let borderX = cloneX - this.borderSize;
let borderY = cloneY - this.borderSize;
@ -568,10 +566,12 @@ var WindowOverlay = new Lang.Class({
_animateOverlayActor(actor, x, y, width, height) {
let params = { x: x,
y: y,
width: width,
time: Overview.ANIMATION_TIME,
transition: 'easeOutQuad' };
if (width !== undefined)
params.width = width;
if (height !== undefined)
params.height = height;
@ -1506,7 +1506,7 @@ var Workspace = new Lang.Class({
if (metaWin.is_attached_dialog()) {
let parent = metaWin.get_transient_for();
while (parent.is_attached_dialog())
parent = metaWin.get_transient_for();
parent = parent.get_transient_for();
let idx = this._lookupIndex (parent);
if (idx < 0) {

View File

@ -68,7 +68,7 @@ var WindowClone = new Lang.Class({
this.realWindow = realWindow;
this.metaWindow = realWindow.meta_window;
this.clone._updateId = this.metaWindow.connect('position-changed',
this.clone._updateId = this.realWindow.connect('notify::position',
this._onPositionChanged.bind(this));
this.clone._destroyId = this.realWindow.connect('destroy', () => {
// First destroy the clone and then destroy everything
@ -153,7 +153,7 @@ var WindowClone = new Lang.Class({
let clone = new Clutter.Clone({ source: realDialog });
this._updateDialogPosition(realDialog, clone);
clone._updateId = metaDialog.connect('position-changed', dialog => {
clone._updateId = realDialog.connect('notify::position', dialog => {
this._updateDialogPosition(dialog, clone);
});
clone._destroyId = realDialog.connect('destroy', () => {
@ -171,7 +171,6 @@ var WindowClone = new Lang.Class({
},
_onPositionChanged() {
let rect = this.metaWindow.get_frame_rect();
this.actor.set_position(this.realWindow.x, this.realWindow.y);
},
@ -179,7 +178,7 @@ var WindowClone = new Lang.Class({
this.actor.get_children().forEach(child => {
let realWindow = child.source;
realWindow.meta_window.disconnect(child._updateId);
realWindow.disconnect(child._updateId);
realWindow.disconnect(child._destroyId);
});
},
@ -417,7 +416,7 @@ var WorkspaceThumbnail = new Lang.Class({
} else if (metaWin.is_attached_dialog()) {
let parent = metaWin.get_transient_for();
while (parent.is_attached_dialog())
parent = metaWin.get_transient_for();
parent = parent.get_transient_for();
let idx = this._lookupIndex (parent);
if (idx < 0) {
@ -677,7 +676,11 @@ var ThumbnailsBox = new Lang.Class({
this._settings.connect('changed::dynamic-workspaces',
this._updateSwitcherVisibility.bind(this));
Main.layoutManager.connect('monitors-changed', this._rebuildThumbnails.bind(this));
Main.layoutManager.connect('monitors-changed', () => {
this._destroyThumbnails();
if (Main.overview.visible)
this._createThumbnails();
});
},
_updateSwitcherVisibility() {
@ -870,9 +873,6 @@ var ThumbnailsBox = new Lang.Class({
Main.overview.connect('windows-restacked',
this._syncStacking.bind(this));
this._workareasChangedId =
global.screen.connect('workareas-changed', this._rebuildThumbnails.bind(this));
this._targetScale = 0;
this._scale = 0;
this._pendingScaleUpdate = false;
@ -902,24 +902,12 @@ var ThumbnailsBox = new Lang.Class({
this._syncStackingId = 0;
}
if (this._workareasChangedId > 0) {
global.screen.disconnect(this._workareasChangedId);
this._workareasChangedId = 0;
}
for (let w = 0; w < this._thumbnails.length; w++)
this._thumbnails[w].destroy();
this._thumbnails = [];
this._porthole = null;
},
_rebuildThumbnails() {
this._destroyThumbnails();
if (Main.overview.visible)
this._createThumbnails();
},
_workspacesChanged() {
let validThumbnails =
this._thumbnails.filter(t => t.state <= ThumbnailState.NORMAL);

View File

@ -470,6 +470,7 @@ var WorkspacesDisplay = new Lang.Class({
this._switchWorkspaceNotifyId = 0;
this._notifyOpacityId = 0;
this._restackedNotifyId = 0;
this._scrollEventId = 0;
this._keyPressEventId = 0;

View File

@ -1,5 +1,5 @@
project('gnome-shell', 'c',
version: '3.28.3',
version: '3.28.4',
meson_version: '>= 0.42.0',
license: 'GPLv2+'
)

View File

@ -1064,7 +1064,7 @@ msgstr "Načítá se…"
#: js/ui/dateMenu.js:321
#, javascript-format
msgid "Feels like %s."
msgstr "Pocitově jako %s."
msgstr "Pocitová teplota %s."
#: js/ui/dateMenu.js:324
msgid "Go online for weather information"

View File

@ -399,6 +399,9 @@ get_gl_vendor (void)
gboolean
shell_util_need_background_refresh (void)
{
if (!clutter_check_windowing_backend (CLUTTER_WINDOWING_X11))
return FALSE;
if (g_strcmp0 (get_gl_vendor (), "NVIDIA Corporation") == 0)
return TRUE;

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

@ -177,15 +177,15 @@ st_bin_get_preferred_height (ClutterActor *self,
}
static void
st_bin_dispose (GObject *gobject)
st_bin_destroy (ClutterActor *actor)
{
StBinPrivate *priv = st_bin_get_instance_private (ST_BIN (gobject));
StBinPrivate *priv = st_bin_get_instance_private (ST_BIN (actor));
if (priv->child)
clutter_actor_destroy (priv->child);
g_assert (priv->child == NULL);
G_OBJECT_CLASS (st_bin_parent_class)->dispose (gobject);
CLUTTER_ACTOR_CLASS (st_bin_parent_class)->destroy (actor);
}
static void
@ -315,11 +315,11 @@ st_bin_class_init (StBinClass *klass)
gobject_class->set_property = st_bin_set_property;
gobject_class->get_property = st_bin_get_property;
gobject_class->dispose = st_bin_dispose;
actor_class->get_preferred_width = st_bin_get_preferred_width;
actor_class->get_preferred_height = st_bin_get_preferred_height;
actor_class->allocate = st_bin_allocate;
actor_class->destroy = st_bin_destroy;
widget_class->popup_menu = st_bin_popup_menu;
widget_class->navigate_focus = st_bin_navigate_focus;

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

@ -248,14 +248,17 @@ st_button_touch_event (ClutterActor *actor,
if (event->type == CLUTTER_TOUCH_BEGIN && !priv->press_sequence)
{
clutter_input_device_sequence_grab (device, sequence, actor);
st_button_press (button, device, 0, sequence);
if (!clutter_event_is_pointer_emulated ((ClutterEvent*) event))
st_button_press (button, device, 0, sequence);
return CLUTTER_EVENT_STOP;
}
else if (event->type == CLUTTER_TOUCH_END &&
priv->device == device &&
priv->press_sequence == sequence)
{
st_button_release (button, device, mask, 0, sequence);
if (!clutter_event_is_pointer_emulated ((ClutterEvent*) event))
st_button_release (button, device, mask, 0, sequence);
clutter_input_device_sequence_ungrab (device, sequence);
return CLUTTER_EVENT_STOP;
}

View File

@ -906,6 +906,13 @@ st_entry_unmap (ClutterActor *actor)
CLUTTER_ACTOR_CLASS (st_entry_parent_class)->unmap (actor);
}
static gboolean
st_entry_get_paint_volume (ClutterActor *actor,
ClutterPaintVolume *volume)
{
return clutter_paint_volume_set_from_allocation (volume, actor);
}
static void
st_entry_class_init (StEntryClass *klass)
{
@ -923,6 +930,7 @@ st_entry_class_init (StEntryClass *klass)
actor_class->allocate = st_entry_allocate;
actor_class->paint = st_entry_paint;
actor_class->unmap = st_entry_unmap;
actor_class->get_paint_volume = st_entry_get_paint_volume;
actor_class->key_press_event = st_entry_key_press_event;
actor_class->key_focus_in = st_entry_key_focus_in;
@ -1287,10 +1295,10 @@ st_entry_get_input_hints (StEntry *entry)
return clutter_text_get_input_hints (CLUTTER_TEXT (priv->entry));
}
static gboolean
_st_entry_icon_press_cb (ClutterActor *actor,
ClutterButtonEvent *event,
StEntry *entry)
static void
_st_entry_icon_clicked_cb (ClutterClickAction *action,
ClutterActor *actor,
StEntry *entry)
{
StEntryPrivate *priv = ST_ENTRY_PRIV (entry);
@ -1298,8 +1306,6 @@ _st_entry_icon_press_cb (ClutterActor *actor,
g_signal_emit (entry, entry_signals[PRIMARY_ICON_CLICKED], 0);
else
g_signal_emit (entry, entry_signals[SECONDARY_ICON_CLICKED], 0);
return FALSE;
}
static void
@ -1309,21 +1315,24 @@ _st_entry_set_icon (StEntry *entry,
{
if (*icon)
{
g_signal_handlers_disconnect_by_func (*icon,
_st_entry_icon_press_cb,
entry);
clutter_actor_remove_action_by_name (*icon, "entry-icon-action");
clutter_actor_remove_child (CLUTTER_ACTOR (entry), *icon);
*icon = NULL;
}
if (new_icon)
{
ClutterAction *action;
*icon = g_object_ref (new_icon);
clutter_actor_set_reactive (*icon, TRUE);
clutter_actor_add_child (CLUTTER_ACTOR (entry), *icon);
g_signal_connect (*icon, "button-release-event",
G_CALLBACK (_st_entry_icon_press_cb), entry);
action = clutter_click_action_new ();
clutter_actor_add_action_with_name (*icon, "entry-icon-action", action);
g_signal_connect (action, "clicked",
G_CALLBACK (_st_entry_icon_clicked_cb), entry);
}
clutter_actor_queue_relayout (CLUTTER_ACTOR (entry));

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

@ -105,18 +105,6 @@ st_texture_cache_class_init (StTextureCacheClass *klass)
G_TYPE_NONE, 1, G_TYPE_FILE);
}
/* Evicts all cached textures */
void
st_texture_cache_clear (StTextureCache *cache)
{
GHashTableIter iter;
gpointer key;
gpointer value;
g_hash_table_remove_all (cache->priv->keyed_cache);
g_signal_emit (cache, signals[ICON_THEME_CHANGED], 0);
}
/* Evicts all cached textures for named icons */
static void
st_texture_cache_evict_icons (StTextureCache *cache)
@ -792,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;
}
@ -996,7 +984,7 @@ file_changed_cb (GFileMonitor *monitor,
char *key;
guint file_hash;
if (event_type != G_FILE_MONITOR_EVENT_CHANGED)
if (event_type != G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT)
return;
file_hash = g_file_hash (file);

View File

@ -52,7 +52,6 @@ typedef enum {
} StTextureCachePolicy;
StTextureCache* st_texture_cache_get_default (void);
void st_texture_cache_clear (StTextureCache *cache);
ClutterActor *
st_texture_cache_load_sliced_image (StTextureCache *cache,

View File

@ -229,9 +229,9 @@ unpremultiply (ClutterColor *color)
{
if (color->alpha != 0)
{
color->red = (color->red * 255 + 127) / color->alpha;
color->green = (color->green * 255 + 127) / color->alpha;
color->blue = (color->blue * 255 + 127) / color->alpha;
color->red = MIN((color->red * 255 + 127) / color->alpha, 255);
color->green = MIN((color->green * 255 + 127) / color->alpha, 255);
color->blue = MIN((color->blue * 255 + 127) / color->alpha, 255);
}
}
@ -402,7 +402,7 @@ st_theme_node_lookup_corner (StThemeNode *node,
return COGL_INVALID_HANDLE;
key = corner_to_string (&corner);
texture = st_texture_cache_load (cache, key, ST_TEXTURE_CACHE_POLICY_NONE, load_corner, &corner, NULL);
texture = st_texture_cache_load (cache, key, ST_TEXTURE_CACHE_POLICY_FOREVER, load_corner, &corner, NULL);
if (texture)
{
@ -1414,6 +1414,32 @@ st_theme_node_load_background_image (StThemeNode *node)
return node->background_texture != COGL_INVALID_HANDLE;
}
static gboolean
st_theme_node_invalidate_resources_for_file (StThemeNode *node,
GFile *file)
{
StBorderImage *border_image;
gboolean changed = FALSE;
GFile *theme_file;
theme_file = st_theme_node_get_background_image (node);
if ((theme_file != NULL) && g_file_equal (theme_file, file))
{
st_theme_node_invalidate_background_image (node);
changed = TRUE;
}
border_image = st_theme_node_get_border_image (node);
theme_file = border_image ? st_border_image_get_file (border_image) : NULL;
if ((theme_file != NULL) && g_file_equal (theme_file, file))
{
st_theme_node_invalidate_border_image (node);
changed = TRUE;
}
return changed;
}
static void st_theme_node_prerender_shadow (StThemeNodePaintState *state);
static void
@ -2751,3 +2777,17 @@ st_theme_node_paint_state_invalidate (StThemeNodePaintState *state)
state->alloc_width = 0;
state->alloc_height = 0;
}
gboolean
st_theme_node_paint_state_invalidate_for_file (StThemeNodePaintState *state,
GFile *file)
{
if (state->node != NULL &&
st_theme_node_invalidate_resources_for_file (state->node, file))
{
st_theme_node_paint_state_invalidate (state);
return TRUE;
}
return FALSE;
}

View File

@ -287,6 +287,9 @@ void st_theme_node_paint_state_free (StThemeNodePaintState *state);
void st_theme_node_paint_state_copy (StThemeNodePaintState *state,
StThemeNodePaintState *other);
void st_theme_node_paint_state_invalidate (StThemeNodePaintState *state);
gboolean st_theme_node_paint_state_invalidate_for_file (StThemeNodePaintState *state,
GFile *file);
void st_theme_node_paint_state_set_node (StThemeNodePaintState *state,
StThemeNode *node);

View File

@ -289,44 +289,17 @@ st_widget_texture_cache_changed (StTextureCache *cache,
{
StWidget *actor = ST_WIDGET (user_data);
StWidgetPrivate *priv = st_widget_get_instance_private (actor);
StThemeNode *node = priv->theme_node;
StBorderImage *border_image;
gboolean changed = FALSE;
GFile *theme_file;
int i;
if (node == NULL)
return;
theme_file = st_theme_node_get_background_image (node);
if ((theme_file != NULL) && g_file_equal (theme_file, file))
for (i = 0; i < G_N_ELEMENTS (priv->paint_states); i++)
{
st_theme_node_invalidate_background_image (node);
changed = TRUE;
StThemeNodePaintState *paint_state = &priv->paint_states[i];
changed |= st_theme_node_paint_state_invalidate_for_file (paint_state, file);
}
border_image = st_theme_node_get_border_image (node);
theme_file = border_image ? st_border_image_get_file (border_image) : NULL;
if ((theme_file != NULL) && g_file_equal (theme_file, file))
{
st_theme_node_invalidate_border_image (node);
changed = TRUE;
}
if (changed)
{
/* If we prerender the background / border, we need to update
* the paint state. We should probably implement a method to
* the theme node to determine this, but for now, just wipe
* the entire paint state.
*
* Use the existing state instead of a new one because it's
* assumed the rest of the state will stay the same.
*/
st_theme_node_paint_state_invalidate (current_paint_state (actor));
if (clutter_actor_is_mapped (CLUTTER_ACTOR (actor)))
clutter_actor_queue_redraw (CLUTTER_ACTOR (actor));
}
if (changed && clutter_actor_is_mapped (CLUTTER_ACTOR (actor)))
clutter_actor_queue_redraw (CLUTTER_ACTOR (actor));
}
static void