Compare commits

..

62 Commits

Author SHA1 Message Date
19dcfa6912 icons: avoid 96x96
- use 128 instead for total sharpness

see https://gitlab.gnome.org/GNOME/nautilus/issues/743
2018-11-13 15:11:14 +01:00
361cc6cf92 st: Remove deprecated cogl_texture_new()
cogl_texture_new() is used in a few places in GNOME Shell, but
it's a deprecated Cogl function. The replacement is the less
verbose cogl_texture_2d_new_with_size(), that is very much a
straightforward replacement.

Remove the few places where this function is used, replacing
it by the CoglTexture2d counterpart.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/287
2018-11-12 21:59:36 -02:00
5fb8d4f730 calendar: do not call destroy() recursively
We have a callback that will call close() when the notification is
destroyed, and a callback that will call destroy() on the notification
when the message is closed.

Currently, if the notification is destroyed we'll execute our callback
that will call again destroy() on the notification. That's bad
practice in general, and it also has the side effect of resetting the
destroy reason.

This commit avoids re-destroying the notification by dropping the
notification reference on destroy.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/258
2018-11-10 10:56:49 +00:00
a98ed08a54 notificationDaemon: use different reason when replacing notification
Differently from the fd.o notifications, Gtk notifications do not
have a mechanism to update themselves. Instead, when a new
notification is received for an ID already known to the notification
daemon, the old notification is dismissed and a replaced with a new
one.

Currently though, there is no way to distinguish a notification that
was dismissed because of an user interaction, or because it was
replaced. That is an useful piece of information, so add a new value
to the NotificationDestroyedReason enum to account for it.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/258
2018-11-10 10:56:49 +00:00
80a7547129 notificationDaemon: separate out GtkNotification creation
This way, source subclasses can easily use a notification subclass
if different functionality is required.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/258
2018-11-10 10:56:49 +00:00
ca3f4cfb41 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
2018-11-10 00:42:49 +01:00
551e827841 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
2018-11-09 10:55:30 +00:00
4dc2039859 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
2018-11-08 12:51:27 +00:00
f1195ecb01 workspaces: Use correct schema for workspace settings
The custom overrides system is gone, we need to use the original
mutter schema.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/768
2018-11-08 10:50:32 +01:00
127ba318fd polkit: Only unregister registered handles
If the initialization fails for some reason, for example by
running 'gnome-shell --replace', we should not crash because
of an attempt of unregistering an unregistered agent handle.

Fix that by checking if the handle is not NULL before calling
the unregistering routines.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/66
2018-11-06 13:05:29 -02:00
72fa44d0fd polkit: Port to G_DECLARE_FINAL_CLASS
So we can remove this old boilerplate code. In order to be able
to use that, the autoptr function for PolkitAgentListener was
added as well.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/66
2018-11-06 13:05:15 -02:00
b96cc9a161 Update Spanish translation 2018-11-06 11:04:19 +00:00
5f2c167947 Update Brazilian Portuguese translation
(cherry picked from commit e55bdb0fbb)
2018-11-05 19:58:53 +00:00
86a78c340f Theme: fix modal dialog button
- allow for focused hover state

Fixes issue #727
2018-11-02 14:45:05 +01:00
1acdff822a iconGrid: Keep icons reactive during pulse animation
The `reactive` property of icon actors was being restored multiple times
over the course of the pulse 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 pulse animation, limiting its smoothness and performance.

The solution is to not toggle the `reactive` property in the pulse
animation at all, which avoids incurring multiple full stage relayouts.

As a bonus, this means the icon under the cursor pulses with the correct
selection highlight, appearing more seamless and responsive.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/261
2018-10-30 19:58:52 +01:00
a5e6dd52d2 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
2018-10-30 18:01:05 +00:00
14953041cc Update Malayalam translation 2018-10-28 14:08:07 +00:00
4e422a527f Updated Slovenian translation 2018-10-25 21:40:05 +02:00
c0b561dd4a switcherPopup: Bind to the stage, not the monitor
The switcher popup is a large, mostly transparent actor that
should cover all the clickable area of GNOME Shell. In Clutter
terms, it should cover the whole stage.

By binding it to the primary monitor, the Alt+Tab behavior
becomes a bit inconsistent. For example, by not hiding when
clicking at empty spaces at other monitors.

Fix that by binding the SwitcherPopup to the whole stage,
and not only the primary monitor.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/647
2018-10-25 12:33:10 -03:00
0f542c2e16 Remove padding from date strings
The padding is removed by using %-d instead of %e or %d.

Examples:

"%B %d %Y"  -> "October 04 2018"

"%B %e %Y"  -> "October  4 2018"

"%B %-d %Y" -> "October 4 2018"

https://gitlab.gnome.org/GNOME/gnome-shell/issues/666
2018-10-25 13:05:47 +02:00
cff9eaf5aa Change a translator comment to be less ambiguous
https://gitlab.gnome.org/GNOME/gnome-shell/issues/666
2018-10-25 13:05:08 +02:00
468117583a Update Slovak translation 2018-10-24 06:31:09 +00:00
7026a6fd32 automountManager: Add handling of udisks errors for no/wrong passwords
If no password or a wrong password is entered after automounting an
encrypted device, then the password should be reasked. However, this
does not happen because the relevant udisks error messages for this
cases are missing in the exception handler that calls _reaskPassword.

Fix this issue by adding the relevant udisks error strings to the
exception handling in the _onVolumeMounted method.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/640
2018-10-24 00:13:10 +02:00
ceed3e07e4 build: Include params.js in portal-helper gresources
Fix a regression causing the portal helper to crash.
In 94423151b2 we moved the dbus interface
descriptions into seperate files which is why we had to include the
fileUtils js module. This module imports the params js module, so add
params.js to the gresources file for the portal helper.
2018-10-23 15:38:31 +00:00
a0dc8dc7ef 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
2018-10-23 16:24:22 +02:00
b405ed6442 keyboardManager: Avoid idempotent calls to meta_backend_set_keymap()
But still try to apply the keymap whenever the input sources changed. This
is a different approach to gnome-shell#240 that still avoid redundant
changes to the current keymap, but actually trigger one when input sources
are added.

https://bugzilla.redhat.com/show_bug.cgi?id=1637418

Closes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/691
2018-10-23 09:45:02 +00:00
8566ec2ee5 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-22 14:58:50 +00:00
ae7dd5e2db osdWindow: Ensure we setMaxLevel before setting Level itself
When maxLevel is > 100%, first OSD appearance was capping the current
level to 100%. Consecutives key press were then OK.
Ensure we setMaxLevel before setting Level itself, so that correct cap
value is applied.
2018-10-19 16:18:41 +02:00
9f3c85fdc8 Update Esperanto translation 2018-10-16 21:02:53 +00:00
aa685310bb Fix enumeration in HACKING.md
The HACKING.md file contains an enumeration in the Indentation and
whitespace section, but the sentences look incorrectly divided.

This patch proposes a fix for that section, reordering all its
contents in a single enumeration, instead of a paragraph and
an enumeration, and also reconstruct the sentences.
2018-10-14 14:05:04 +02:00
76117fd306 appFolder: Don't block all shortcuts
App folder popups take a grab when opened, and as we don't pass any
particular pushModal() parameters, all keybindings are blocked. While
this makes sense for most keybindings that would interfere with the
popup interaction, others like volume/brightness keys or screenshots
can be allowed safely.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/648
2018-10-11 20:12:54 +02:00
8855622666 popupMenu: Handle keypress if numlock is enabled
Add exception to handle a keypress if numlock is enabled as we already do for
capslock. This uses Clutter.ModifierType.MOD2_MASK because at the moment there
is not a more explicit way to refer to the numlock mask.

Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/550
2018-10-11 07:45:44 +00:00
655234e6c3 shell: Remove ShellGenericContainer
Now that it is no longer used in GNOME Shell, let's
remove this old workaround. This commit also removes
the docs reference from the sgml file.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/153
2018-10-08 22:44:14 -03:00
38c1ebba62 dash: expand and center align DashItemContainer
This is necessary to keep the small actor that shows up
during drag motion center aligned.
2018-10-08 22:43:13 -03:00
557b232c89 panel: Delegate container destruction to PanelMenu.ButtonBox
Instead of taking care of the PanelMenu.ButtonBox.container
destruction by itself, delegate that to the very object that
created it in the first place: PanelMenu.ButtonBox itself.
2018-10-08 22:43:13 -03:00
b719744e75 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.
2018-10-08 22:43:13 -03:00
038f8b6ea5 keyboard: Stop using Shell.GenericContainer
This is the last remaining usage of Shell.GenericContainer
in the codebase, and posed small challenges compared to the
other removals.

A new St.Widget subclass called InputSourceIndicatorContainer
was added as a replacement to the Shell.GenericContainer. It
was needed because GNOME Shell needs to override the regular
size allocation functions, but InputSourceIndicator already
is a St.Widget with its own size allocation overrides.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/153
2018-10-08 22:43:01 -03:00
2ee321e0d8 tests: Stop using Shell.GenericContainer
The test doesn't look and behave like before, but they are
already broken in master anyway. This commit makes it work
without Shell.GenericContainer, but the test itself remains
to be fixed.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/153
2018-10-08 22:43:01 -03:00
b4c674900f inspector: Stop using Shell.GenericContainer
No alarms and no surprises here.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/153
2018-10-08 22:43:01 -03:00
3fa19e58ac boxPointer: Stop using Shell.GenericContainer
An easy removal too.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/153
2018-10-08 22:43:01 -03:00
f460f2748d boxPointer: Add compatibility API
Because we're late in the cycle, and don't know how many
extensions actually rely on this API, this commit adds
back the BoxPointer.show() and .hide() functions, with
warning messages to notify consumers that this is going
to be removed.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/153
2018-10-08 22:43:01 -03:00
8b215b2446 boxPointer: Rename show/hide to open/close
Pretty much like dd4709bb2, BoxPointer's show() and hide()
functions will clash with Clutter.Actor's ones.

In addition to that, on a conceptual level, the current API
is not great, because calling boxPointer.hide() won't result
in boxPointer.actor.visible == false.

For these reasons, rename show() and hide() to open() and
close(). A compatibility layer will be added in a following
commit, warning about the usage of show() and hide().

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/153
2018-10-08 22:42:53 -03:00
0c0d76f7d6 loginDialog: Stop using Shell.GenericContainer
Removing the Shell.GenericContainer from the login dialog
was remarkably easier, since it only overrides 'allocate'.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/153
2018-10-08 22:42:26 -03:00
dd225713a1 layoutManager: Subclass GObject.Object
LayoutManager is currently a pure JavaScript class that
relies on the rudimentary Signals.addSignalMethods() to
handle signals. This is an inefficient implementation of
one of the most central classes in GNOME Shell.

In addition to removing Shell.GenericContainer, then,
turn LayoutManager into a proper GObject.Object subclass.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/153
2018-10-08 22:42:26 -03:00
f4682748fa layoutManager: Stop using Shell.GenericContainer
This one was remarkably easy to port. In order to make it,
replace the Shell.GenericContainer handlers by a constraint
and simply replace it by a St.Widget.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/153
2018-10-08 22:42:26 -03:00
b058e89166 workspaceSwitcherPopup: Stop using Shell.GenericContainer
Removing Shell.GenericContainer here was slightly trickier
because it required factoring out a new JavaScript class.

It's nevertheless a straightforward removal.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/153
2018-10-08 22:42:26 -03:00
ac314cfb05 messageTray: Drop Shell.GenericContainer usage
Nothing particularly outstanding with this class - it was
a straightforward removal and subclassing.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/153
2018-10-08 22:42:26 -03:00
fc342fe8c5 buttonBox: Drop Shell.GenericContainer usage
Another easy port.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/153
2018-10-08 22:42:25 -03:00
dd4709bb27 appMenuButton: Rename show/hide to fadeIn/fadeOut
In the next commit, we will turn PanelMenu.ButtonBox into a
St.Widget subclass. As a domino effect, PanelMenu.Button will
become one too, and so will Panel.AppMenuButton.

When that happens, the current show() and hide() functions in
Panel.AppMenuButton will clash with Clutter.Actor's ones.

To avoid that, rename these functions to fadeIn() and fadeOut()
and avoid a name clash.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/153
2018-10-08 22:42:25 -03:00
e9f4f2e8ae thumbnailBox: Stop using Shell.GenericContainer
This is another straight port from Shell.GenericContainer.
The important thing to notice is that the calculation is
broken if the StThemeNode helpers (adjust_preferred_* and
adjust_for_*) aren't used.

The downside of this patch is that it removed the skip_paint
from the thumbnails. Keeping it would add an unecessarily
large amount of code.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/153
2018-10-08 22:42:25 -03:00
197c0eee29 iconGrid: Stop using Shell.GenericContainer
Removing Shell.GenericContainer from the IconGrid class was
challenging because it needs the "skip paint" API from it.
This API was added, too, as a workaround to the inability
to override vfuncs from GJS.

The overrides are largely copy-pasted and translated versions
of the Shell.GenericContainer code.

The IconGrid:key-focus-in signal was renamed to :child-focused
to avoid clashing with ClutterActor:key-focus-in.

In GridSearchResults, the internal IconGrid had it's y_expand
set to false, so it doesn't push other search elements (the
list results mainly) to the bottom of the screen.

Because skip paint wasn't and still isn't a GObject property,
rename it to _skipPaint to reflect that.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/153
2018-10-08 22:42:25 -03:00
034a723677 iconGrid: Rename ::key-focus-in signal
As part of our quest to obsolete Shell.GenericContainer, IconGrid will
become a Clutter.Actor subclass. As the ::key-focus-in signal would
clash with Clutter.Actor::key-focus-in, rename it to ::child-focused.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/153
2018-10-08 22:42:25 -03:00
efb3025d8c dash: Set scale and opacity on parent actor
DashItemContainer currently animates the scale and opacity
of its child when zooming in. This is visible when adding
a new favorite item to the dash; the items will zoom in from
the center.

After the previous commit, however, the zoom animation got
slightly broken, and looked like the icon was coming from
the bottom instead of the center.

Fix that by setting the scale and opacity of DashItemContainer
itself, instead of its child. Remove the unused code after that
too.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/153
2018-10-08 22:42:24 -03:00
81ec8215a0 baseIcon: Stop using Shell.GenericContainer
Pretty much like the previous patches, this extends St.Bin. The
most interesting aspect of this patch is that most of the sizing
routines of the icons is now delegated to the actors and layout
managers, removing quite a bunch of code.

The 'spacing' theme property is now redirected to StBoxLayout's
spacing property. Also adjust the Dash code to stop forcing a
potentially invalid width in the first icon too.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/153
2018-10-08 22:42:24 -03:00
4be66ecf01 windowIcon: Subclass St.BoxLayout
Following the previous work, turn WindowIcon into a
St.BoxLayout subclass, and remove the this.actor
field from it.
2018-10-08 22:42:24 -03:00
2717ca9d08 st-box-layout: Pass correct allocation box to layout manager
StBoxLayout implements StScrollable, which, semantically, means that
the StBoxLayout size may not match the minimum size reported by the
layout manager. In this specific case, the layout manager by is a
ClutterBoxLayout by default. For example:

        +--------------+
        |   Viewport   |
 +------+--------------+-----------------+
 |      |              |                 |
 |      |              |     Content     |
 |      |              |                 |
 +------+--------------+-----------------+
        |              |
        +--------------+

So, assuming that:

 - ContentSize = the minimum size of the content;
 - ViewportSize = the allocated size of the viewport;

When allocating StBoxLayout, it must assume ViewportSize, but must
pass ContentSize to the layout manager. That way, the children of
StBoxLayout are correctly placed within it, even if it's bigger than
ViewportSize.

And here's the problem: right now, StBoxLayout assumes ViewportSize
AND also passes it to layout manager. Commit 77c4c6b6d specifically
exposed this bug by relying entirely on StBoxLayout to arrange the
app and window icons.

Fix that by using ViewportSize to allocate StBoxLayout itself, but
passing ContentSize to the layout manager.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/153
2018-10-08 22:42:24 -03:00
c6cea277eb switcherList: Stop using Shell.GenericContainer
This commit removes all the uses of Shell.GenericContainer from
SwitcherPopup.SwitcherList. Compared to the other patches, this
one was specially trickier to get right, and a few invasive
changes needed to be done.

The most noticeable one is that the allocation of the items is
done entirely by St.BoxLayout -- we don't manually allocate them
anymore. To make it work, get_preferred_width() had to calculate
the correct value. It now assumes that:

 * Minimum width: the minimum width of the widest child.
 * Natural width: the minimum width of the StBoxLayout (use it
   instead of the natural width to force the labels to ellipsize
   when too long.)

The AppIcon class became a St.Widget subclass as well, to override
get_preferred_width() and be able to keep the squared shape.

Besides that, add a new SwitcherButton class to reimplement squared
icons without having to resort to hacks in the size allocation
machinery. This class has a single vfunc override to ensure that it
is squared when the SwitcherList is.

The arrows indicating multiple windows are now in this._list
actor to the SwitcherPopup itself, since this._list automatically
manages its own children now.

At last, adapt (but preserve) the hack in CyclerPopup.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/153
2018-10-08 22:42:24 -03:00
9a47b4b343 switcherList: Remove unused variable
The title is self-explanatory, 'primary' was not being used
anywhere.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/153
2018-10-08 22:42:24 -03:00
0ec36fc5cf switcherPopup: Use MonitorConstraint instead of vfunc overrides
Instead of overriding vfunc_get_preferred_width|height(), use the
already available Layout.MonitorConstraint to bind SwitcherPopup
to the primary monitor.
2018-10-08 22:42:23 -03:00
a315e75e95 switcherPopup: Subclass St.Widget
This commit turns SwitcherPopup.SwitcherPopup into a St.Widget
subclass, and gets rid of Shell.GenericContainer usage. Subclasses
were adapted to that too.

This class introduced a new challenge: it overrides show(). As per
discussions, we now call this.visible = true inside show().

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/153
2018-10-08 22:42:23 -03:00
e82c68accd switcherPopup: Rename destroy() to fadeAndDestroy()
In the process of purging all usages of Shell.GenericContainer
of GNOME Shell, one specific problematic situation that might
occur is when classes have functions that would clash with any
ClutterActor or StWidget function name.

One of such example is SwitcherPopup.destroy(). Right now, this
class is a pure JavaScript class that wraps a real actor, but
soon this will change, and it'll become a St.Widget subclass.

Another problem with functions that mimic the toolkit ones is
the predictability of them; after calling destroy(), that widget
is expected to not be available anymore. In SwitcherPopup case,
it is still available for a short while. In this case, that's not
a big problem, but the show() and hide() functions in other clases
are more problematic because the actor's visibility does not
follow that.

This commit is a first step in cleaning that up, and changes the
SwitcherPopup.destroy() to fadeAndDestroy().

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/153
2018-10-08 22:42:23 -03:00
286ffbe2b6 panel: Stop using Shell.GenericContainer
Shell.GenericContainer exposes the size negotiation machinery
through the use of signals. Signals are not specially performant.
One of the reasons is that they acquire a global lock for signal
handlers lookup. GNOME Shell has more than 2,000 actors at any
given point in time, up to 20 levels deep in hierarchy, making
size negotiation and painting non-trivial tasks. Such a critical
section of Clutter's machinery shouldn't rely on signals
whatsoever.

Regardless of that, Shell.GenericContainer is a workaround to
a non-existing issue anymore. It shouldn't be used anyway, and
any performance improvements that removing it can potentially
yield are bonuses to it.

This commit starts this work by removing Shell.GenericContainer
usage from Panel.Panel class. The class now extends St.Widget,
and as such, it has no "this.actor" field set anymore. A couple
of places where this actor field was used are adjuste as well.

It is important to notice that we now allocate the Panel itself
inside vfunc_allocate(). This was previously done before emitting
the signal by Shell.GenericContainer.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/153
2018-10-08 22:42:23 -03:00
52 changed files with 2574 additions and 3297 deletions

View File

@ -10,15 +10,15 @@ 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, braces 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
on one line.
* 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 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.
* 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;

21
NEWS
View File

@ -1,24 +1,3 @@
3.30.2
======
* popupMenu: Fix keyboard activation when numlock is active [Andrea; #550]
* Do not block all shortcuts while app folders are expanded [Florian; #648]
* Fix regression in handling new input sources [Carlos; #691]
* Improve performance of app icon animations [Daniel; !253, !261]
* Respect natural-scroll setting for workspace swipe gesture [Erik; #516]
* notifications: Support icon theme names in 'image-path' hint [Marco; !285]
* Confine window preview titles to workspace area [Florian; !214]
* Misc. bug fixes [Florian, Cosimo; #602, #693, #768, #430, !286]
Contributors:
Andrea Azzarone, Cosimo Cecchi, Erik Duxstad, Carlos Garnacho,
Florian Müllner, Didier Roche, Marco Trevisan (Treviño), verdre,
Daniel van Vugt
Translators:
Rūdolfs Mazurs [lv], Kristjan SCHMIDT [eo], Milo Casagrande [it],
Dušan Kazik [sk], gogo [hr], Anish Sheela [ml], Rafael Fontenelle [pt_BR],
Daniel Mustieles [es]
3.30.1
======
* Cancel search on overview hiding [Marco; !205]

View File

@ -57,8 +57,8 @@ stage {
border-right-width: 1px;
@include button(normal);
&:insensitive { @include button(insensitive); }
&:focus { @include button(focus); }
&:hover { @include button(hover); }
&:focus { @include button(focus); }
&:active { @include button(active); }
padding: 12px;
@ -1287,7 +1287,7 @@ StScrollBar {
}
.list-search-results { spacing: 3px; }
.search-section-separator { height: 2px; background-color: rgba(255, 255, 255, 0.2); }
.search-section-separator { margin-top: 16px; height: 2px; background-color: rgba(255, 255, 255, 0.2); }
.list-search-result-content { spacing: 30px; }
.list-search-result-title { color: darken($osd_fg_color,5%); spacing: 12px; }
@ -1344,7 +1344,7 @@ StScrollBar {
-shell-grid-horizontal-item-size: 136px;
-shell-grid-vertical-item-size: 136px;
.overview-icon { icon-size: 96px; }
.overview-icon { icon-size: 128px; }
}
//.app-display { spacing: 20px; }

View File

@ -17,7 +17,6 @@
<chapter>
<title>Actors</title>
<xi:include href="xml/shell-generic-container.xml"/>
<xi:include href="xml/shell-stack.xml"/>
</chapter>
<chapter>

View File

@ -408,16 +408,18 @@ Signals.addSignalMethods(SessionMenuButton.prototype);
var LoginDialog = new Lang.Class({
Name: 'LoginDialog',
Extends: St.Widget,
Signals: { 'failed': {} },
_init(parentActor) {
this.actor = new Shell.GenericContainer({ style_class: 'login-dialog',
visible: false });
this.actor.get_accessible().set_role(Atk.Role.WINDOW);
this.parent({ style_class: 'login-dialog',
visible: false });
this.actor.add_constraint(new Layout.MonitorConstraint({ primary: true }));
this.actor.connect('allocate', this._onAllocate.bind(this));
this.actor.connect('destroy', this._onDestroy.bind(this));
parentActor.add_child(this.actor);
this.get_accessible().set_role(Atk.Role.WINDOW);
this.add_constraint(new Layout.MonitorConstraint({ primary: true }));
this.connect('destroy', this._onDestroy.bind(this));
parentActor.add_child(this);
this._userManager = AccountsService.UserManager.get_default()
this._gdmClient = new Gdm.Client();
@ -442,7 +444,7 @@ var LoginDialog = new Lang.Class({
y_align: Clutter.ActorAlign.CENTER,
vertical: true,
visible: false });
this.actor.add_child(this._userSelectionBox);
this.add_child(this._userSelectionBox);
this._userList = new UserList();
this._userSelectionBox.add(this._userList.actor,
@ -454,7 +456,7 @@ var LoginDialog = new Lang.Class({
this._authPrompt.connect('prompted', this._onPrompted.bind(this));
this._authPrompt.connect('reset', this._onReset.bind(this));
this._authPrompt.hide();
this.actor.add_child(this._authPrompt.actor);
this.add_child(this._authPrompt.actor);
// translators: this message is shown below the user list on the
// login screen. It can be activated to reveal an entry for
@ -482,7 +484,7 @@ var LoginDialog = new Lang.Class({
opacity: 0,
vscrollbar_policy: Gtk.PolicyType.AUTOMATIC,
hscrollbar_policy: Gtk.PolicyType.NEVER });
this.actor.add_child(this._bannerView);
this.add_child(this._bannerView);
let bannerBox = new St.BoxLayout({ vertical: true });
@ -497,7 +499,7 @@ var LoginDialog = new Lang.Class({
this._logoBin = new St.Widget({ style_class: 'login-dialog-logo-bin',
x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.END });
this.actor.add_child(this._logoBin);
this.add_child(this._logoBin);
this._updateLogo();
this._userList.connect('activate', (userList, item) => {
@ -576,7 +578,12 @@ var LoginDialog = new Lang.Class({
return actorBox;
},
_onAllocate(actor, dialogBox, flags) {
vfunc_allocate(dialogBox, flags) {
this.set_allocation(dialogBox, flags);
let themeNode = this.get_theme_node();
dialogBox = themeNode.get_content_box(dialogBox);
let dialogWidth = dialogBox.x2 - dialogBox.x1;
let dialogHeight = dialogBox.y2 - dialogBox.y1;
@ -919,10 +926,10 @@ var LoginDialog = new Lang.Class({
},
_loginScreenSessionActivated() {
if (this.actor.opacity == 255 && this._authPrompt.verificationStatus == AuthPrompt.AuthPromptStatus.NOT_VERIFYING)
if (this.opacity == 255 && this._authPrompt.verificationStatus == AuthPrompt.AuthPromptStatus.NOT_VERIFYING)
return;
Tweener.addTween(this.actor,
Tweener.addTween(this,
{ opacity: 255,
time: _FADE_ANIMATION_TIME,
transition: 'easeOutQuad',
@ -931,7 +938,7 @@ var LoginDialog = new Lang.Class({
for (let i = 0; i < children.length; i++) {
if (children[i] != Main.layoutManager.screenShieldGroup)
children[i].opacity = this.actor.opacity;
children[i].opacity = this.opacity;
}
},
onUpdateScope: this,
@ -952,7 +959,7 @@ var LoginDialog = new Lang.Class({
},
_startSession(serviceName) {
Tweener.addTween(this.actor,
Tweener.addTween(this,
{ opacity: 0,
time: _FADE_ANIMATION_TIME,
transition: 'easeOutQuad',
@ -961,7 +968,7 @@ var LoginDialog = new Lang.Class({
for (let i = 0; i < children.length; i++) {
if (children[i] != Main.layoutManager.screenShieldGroup)
children[i].opacity = this.actor.opacity;
children[i].opacity = this.opacity;
}
},
onUpdateScope: this,
@ -1230,17 +1237,17 @@ var LoginDialog = new Lang.Class({
},
open() {
Main.ctrlAltTabManager.addGroup(this.actor,
Main.ctrlAltTabManager.addGroup(this,
_("Login Window"),
'dialog-password-symbolic',
{ sortGroup: CtrlAltTab.SortGroup.MIDDLE });
this._userList.actor.grab_key_focus();
this.actor.show();
this.actor.opacity = 0;
this.show();
this.opacity = 0;
Main.pushModal(this.actor, { actionMode: Shell.ActionMode.LOGIN_SCREEN });
Main.pushModal(this, { actionMode: Shell.ActionMode.LOGIN_SCREEN });
Tweener.addTween(this.actor,
Tweener.addTween(this,
{ opacity: 255,
time: 1,
transition: 'easeInQuad' });
@ -1249,8 +1256,8 @@ var LoginDialog = new Lang.Class({
},
close() {
Main.popModal(this.actor);
Main.ctrlAltTabManager.removeGroup(this.actor);
Main.popModal(this);
Main.ctrlAltTabManager.removeGroup(this);
},
cancel() {
@ -1265,4 +1272,3 @@ var LoginDialog = new Lang.Class({
this._authPrompt.finish(onComplete);
},
});
Signals.addSignalMethods(LoginDialog.prototype);

View File

@ -243,13 +243,13 @@ function formatTime(time, params) {
followed by a time string in 24h format.
i.e. "May 25, 14:30" */
// xgettext:no-c-format
format = N_("%B %d, %H\u2236%M");
format = N_("%B %-d, %H\u2236%M");
else
/* Translators: this is the month name, day number, year
number followed by a time string in 24h format.
i.e. "May 25 2012, 14:30" */
// xgettext:no-c-format
format = N_("%B %d %Y, %H\u2236%M");
format = N_("%B %-d %Y, %H\u2236%M");
} else {
// Show only the time if date is on today
if (daysAgo < 1 || params.timeOnly)
@ -272,13 +272,13 @@ function formatTime(time, params) {
followed by a time string in 12h format.
i.e. "May 25, 2:30 pm" */
// xgettext:no-c-format
format = N_("%B %d, %l\u2236%M %p");
format = N_("%B %-d, %l\u2236%M %p");
else
/* Translators: this is the month name, day number, year
number followed by a time string in 12h format.
i.e. "May 25 2012, 2:30 pm"*/
// xgettext:no-c-format
format = N_("%B %d %Y, %l\u2236%M %p");
format = N_("%B %-d %Y, %l\u2236%M %p");
}
let formattedTime = date.format(Shell.util_translate_time_string(format));

View File

@ -3,6 +3,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 Mainloop = imports.mainloop;
const Meta = imports.gi.Meta;
@ -21,10 +22,10 @@ var THUMBNAIL_POPUP_TIME = 500; // milliseconds
var THUMBNAIL_FADE_TIME = 0.1; // seconds
var WINDOW_PREVIEW_SIZE = 128;
var APP_ICON_SIZE = 96;
var APP_ICON_SIZE = 128;
var APP_ICON_SIZE_SMALL = 48;
const baseIconSizes = [96, 64, 48, 32, 22];
const baseIconSizes = [128, 64, 48, 32, 22];
var AppIconMode = {
THUMBNAIL_ONLY: 1,
@ -80,41 +81,41 @@ var AppSwitcherPopup = new Lang.Class({
this._items = this._switcherList.icons;
},
_allocate(actor, box, flags) {
this.parent(actor, box, flags);
vfunc_allocate(box, flags) {
this.parent(box, flags);
// Allocate the thumbnails
// We try to avoid overflowing the screen so we base the resulting size on
// those calculations
if (this._thumbnails) {
let childBox = this._switcherList.actor.get_allocation_box();
let childBox = this._switcherList.get_allocation_box();
let primary = Main.layoutManager.primaryMonitor;
let leftPadding = this.actor.get_theme_node().get_padding(St.Side.LEFT);
let rightPadding = this.actor.get_theme_node().get_padding(St.Side.RIGHT);
let bottomPadding = this.actor.get_theme_node().get_padding(St.Side.BOTTOM);
let leftPadding = this.get_theme_node().get_padding(St.Side.LEFT);
let rightPadding = this.get_theme_node().get_padding(St.Side.RIGHT);
let bottomPadding = this.get_theme_node().get_padding(St.Side.BOTTOM);
let hPadding = leftPadding + rightPadding;
let icon = this._items[this._selectedIndex].actor;
let icon = this._items[this._selectedIndex];
let [posX, posY] = icon.get_transformed_position();
let thumbnailCenter = posX + icon.width / 2;
let [childMinWidth, childNaturalWidth] = this._thumbnails.actor.get_preferred_width(-1);
let [childMinWidth, childNaturalWidth] = this._thumbnails.get_preferred_width(-1);
childBox.x1 = Math.max(primary.x + leftPadding, Math.floor(thumbnailCenter - childNaturalWidth / 2));
if (childBox.x1 + childNaturalWidth > primary.x + primary.width - hPadding) {
let offset = childBox.x1 + childNaturalWidth - primary.width + hPadding;
childBox.x1 = Math.max(primary.x + leftPadding, childBox.x1 - offset - hPadding);
}
let spacing = this.actor.get_theme_node().get_length('spacing');
let spacing = this.get_theme_node().get_length('spacing');
childBox.x2 = childBox.x1 + childNaturalWidth;
if (childBox.x2 > primary.x + primary.width - rightPadding)
childBox.x2 = primary.x + primary.width - rightPadding;
childBox.y1 = this._switcherList.actor.allocation.y2 + spacing;
childBox.y1 = this._switcherList.allocation.y2 + spacing;
this._thumbnails.addClones(primary.y + primary.height - bottomPadding - childBox.y1);
let [childMinHeight, childNaturalHeight] = this._thumbnails.actor.get_preferred_height(-1);
let [childMinHeight, childNaturalHeight] = this._thumbnails.get_preferred_height(-1);
childBox.y2 = childBox.y1 + childNaturalHeight;
this._thumbnails.actor.allocate(childBox, flags);
this._thumbnails.allocate(childBox, flags);
}
},
@ -262,7 +263,7 @@ var AppSwitcherPopup = new Lang.Class({
_windowActivated(thumbnailList, n) {
let appIcon = this._items[this._selectedIndex];
Main.activateWindow(appIcon.cachedWindows[n]);
this.destroy();
this.fadeAndDestroy();
},
_windowEntered(thumbnailList, n) {
@ -367,7 +368,7 @@ var AppSwitcherPopup = new Lang.Class({
},
_destroyThumbnails() {
let thumbnailsActor = this._thumbnails.actor;
let thumbnailsActor = this._thumbnails;
Tweener.addTween(thumbnailsActor,
{ opacity: 0,
time: THUMBNAIL_FADE_TIME,
@ -387,19 +388,19 @@ var AppSwitcherPopup = new Lang.Class({
this._thumbnails.connect('item-activated', this._windowActivated.bind(this));
this._thumbnails.connect('item-entered', this._windowEntered.bind(this));
this._thumbnails.connect('item-removed', this._windowRemoved.bind(this));
this._thumbnails.actor.connect('destroy', () => {
this._thumbnails.connect('destroy', () => {
this._thumbnails = null;
this._thumbnailsFocused = false;
});
this.actor.add_actor(this._thumbnails.actor);
this.add_actor(this._thumbnails);
// Need to force an allocation so we can figure out whether we
// need to scroll when selecting
this._thumbnails.actor.get_allocation_box();
this._thumbnails.get_allocation_box();
this._thumbnails.actor.opacity = 0;
Tweener.addTween(this._thumbnails.actor,
this._thumbnails.opacity = 0;
Tweener.addTween(this._thumbnails,
{ opacity: 255,
time: THUMBNAIL_FADE_TIME,
transition: 'easeOutQuad',
@ -471,6 +472,21 @@ var CyclerHighlight = new Lang.Class({
}
});
// We don't show an actual popup, so just provide what SwitcherPopup
// expects instead of inheriting from SwitcherList
var CyclerList = new Lang.Class({
Name: 'CyclerList',
Extends: St.Widget,
Signals: { 'item-activated': { param_types: [GObject.TYPE_INT] },
'item-entered': { param_types: [GObject.TYPE_INT] },
'item-removed': { param_types: [GObject.TYPE_INT] },
'item-highlighted': { param_types: [GObject.TYPE_INT] } },
highlight(index, justOutline) {
this.emit('item-highlighted', index);
}
});
var CyclerPopup = new Lang.Class({
Name: 'CyclerPopup',
Extends: SwitcherPopup.SwitcherPopup,
@ -487,11 +503,10 @@ var CyclerPopup = new Lang.Class({
this._highlight = new CyclerHighlight();
global.window_group.add_actor(this._highlight.actor);
// We don't show an actual popup, so just provide what SwitcherPopup
// expects instead of inheriting from SwitcherList
this._switcherList = { actor: new St.Widget(),
highlight: this._highlightItem.bind(this),
connect() {} };
this._switcherList = new CyclerList();
this._switcherList.connect('item-highlighted', (list, index) => {
this._highlightItem(index);
});
},
_highlightItem(index, justOutline) {
@ -653,22 +668,32 @@ var WindowCyclerPopup = new Lang.Class({
var AppIcon = new Lang.Class({
Name: 'AppIcon',
Extends: St.BoxLayout,
_init(app) {
this.parent({ style_class: 'alt-tab-app',
vertical: true });
this.app = app;
this.actor = new St.BoxLayout({ style_class: 'alt-tab-app',
vertical: true });
this.icon = null;
this._iconBin = new St.Bin({ x_fill: true, y_fill: true });
this.actor.add(this._iconBin, { x_fill: false, y_fill: false } );
this.add(this._iconBin, { x_fill: false, y_fill: false } );
this.label = new St.Label({ text: this.app.get_name() });
this.actor.add(this.label, { x_fill: false });
this.add(this.label, { x_fill: false });
},
set_size(size) {
this.icon = this.app.create_icon_texture(size);
this._iconBin.child = this.icon;
this._iconBin.set_size(size, size);
},
vfunc_get_preferred_width(forHeight) {
let [minWidth, ] = this.parent(forHeight);
minWidth = Math.max(minWidth, forHeight);
return [minWidth, minWidth];
}
});
@ -707,11 +732,10 @@ var AppSwitcher = new Lang.Class({
}
this._curApp = -1;
this._iconSize = 0;
this._altTabPopup = altTabPopup;
this._mouseTimeOutId = 0;
this.actor.connect('destroy', this._onDestroy.bind(this));
this.connect('destroy', this._onDestroy.bind(this));
},
_onDestroy() {
@ -738,17 +762,16 @@ var AppSwitcher = new Lang.Class({
// We just assume the whole screen here due to weirdness happing with the passed width
let primary = Main.layoutManager.primaryMonitor;
let parentPadding = this.actor.get_parent().get_theme_node().get_horizontal_padding();
let availWidth = primary.width - parentPadding - this.actor.get_theme_node().get_horizontal_padding();
let parentPadding = this.get_parent().get_theme_node().get_horizontal_padding();
let availWidth = primary.width - parentPadding - this.get_theme_node().get_horizontal_padding();
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
let iconSizes = baseIconSizes.map(s => s * scaleFactor);
let iconSize = baseIconSizes[0];
if (this._items.length == 1) {
this._iconSize = baseIconSizes[0];
} else {
if (this._items.length > 1) {
for(let i = 0; i < baseIconSizes.length; i++) {
this._iconSize = baseIconSizes[i];
iconSize = baseIconSizes[i];
let height = iconSizes[i] + iconSpacing;
let w = height * this._items.length + totalSpacing;
if (w <= availWidth)
@ -756,32 +779,36 @@ var AppSwitcher = new Lang.Class({
}
}
this._iconSize = iconSize;
for(let i = 0; i < this.icons.length; i++) {
if (this.icons[i].icon != null)
break;
this.icons[i].set_size(this._iconSize);
this.icons[i].set_size(iconSize);
}
},
_getPreferredHeight(actor, forWidth, alloc) {
vfunc_get_preferred_height(forWidth) {
this._setIconSize();
this.parent(actor, forWidth, alloc);
return this.parent(forWidth);
},
_allocate(actor, box, flags) {
vfunc_allocate(box, flags) {
// Allocate the main list items
this.parent(actor, box, flags);
this.parent(box, flags);
let arrowHeight = Math.floor(this.actor.get_theme_node().get_padding(St.Side.BOTTOM) / 3);
let contentBox = this.get_theme_node().get_content_box(box);
let arrowHeight = Math.floor(this.get_theme_node().get_padding(St.Side.BOTTOM) / 3);
let arrowWidth = arrowHeight * 2;
// Now allocate each arrow underneath its item
let childBox = new Clutter.ActorBox();
for (let i = 0; i < this._items.length; i++) {
let itemBox = this._items[i].allocation;
childBox.x1 = Math.floor(itemBox.x1 + (itemBox.x2 - itemBox.x1 - arrowWidth) / 2);
childBox.x1 = contentBox.x1 + Math.floor(itemBox.x1 + (itemBox.x2 - itemBox.x1 - arrowWidth) / 2);
childBox.x2 = childBox.x1 + arrowWidth;
childBox.y1 = itemBox.y2 + arrowHeight;
childBox.y1 = contentBox.y1 + itemBox.y2 + arrowHeight;
childBox.y2 = childBox.y1 + arrowHeight;
this._arrows[i].allocate(childBox, flags);
}
@ -839,7 +866,7 @@ var AppSwitcher = new Lang.Class({
_addIcon(appIcon) {
this.icons.push(appIcon);
let item = this.addItem(appIcon.actor, appIcon.label);
let item = this.addItem(appIcon, appIcon.label);
appIcon._stateChangedId = appIcon.app.connect('notify::state', app => {
if (app.state != Shell.AppState.RUNNING)
@ -849,7 +876,7 @@ var AppSwitcher = new Lang.Class({
let n = this._arrows.length;
let arrow = new St.DrawingArea({ style_class: 'switcher-arrow' });
arrow.connect('repaint', () => { SwitcherPopup.drawArrow(arrow, St.Side.BOTTOM); });
this._list.add_actor(arrow);
this.add_actor(arrow);
this._arrows.push(arrow);
if (appIcon.cachedWindows.length == 1)
@ -907,21 +934,21 @@ var ThumbnailList = new Lang.Class({
}
this.actor.connect('destroy', this._onDestroy.bind(this));
this.connect('destroy', this._onDestroy.bind(this));
},
addClones(availHeight) {
if (!this._thumbnailBins.length)
return;
let totalPadding = this._items[0].get_theme_node().get_horizontal_padding() + this._items[0].get_theme_node().get_vertical_padding();
totalPadding += this.actor.get_theme_node().get_horizontal_padding() + this.actor.get_theme_node().get_vertical_padding();
totalPadding += this.get_theme_node().get_horizontal_padding() + this.get_theme_node().get_vertical_padding();
let [labelMinHeight, labelNaturalHeight] = this._labels[0].get_preferred_height(-1);
let spacing = this._items[0].child.get_theme_node().get_length('spacing');
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
let thumbnailSize = THUMBNAIL_DEFAULT_SIZE * scaleFactor;
availHeight = Math.min(availHeight - labelNaturalHeight - totalPadding - spacing, thumbnailSize);
let binHeight = availHeight + this._items[0].get_theme_node().get_vertical_padding() + this.actor.get_theme_node().get_vertical_padding() - spacing;
let binHeight = availHeight + this._items[0].get_theme_node().get_vertical_padding() + this.get_theme_node().get_vertical_padding() - spacing;
binHeight = Math.min(thumbnailSize, binHeight);
for (let i = 0; i < this._thumbnailBins.length; i++) {
@ -956,7 +983,7 @@ var ThumbnailList = new Lang.Class({
if (this._clones.length > 0)
this.highlight(SwitcherPopup.mod(index, this._clones.length));
else
this.actor.destroy();
this.destroy();
},
_onDestroy() {
@ -970,15 +997,17 @@ var ThumbnailList = new Lang.Class({
var WindowIcon = new Lang.Class({
Name: 'WindowIcon',
Extends: St.BoxLayout,
_init(window, mode) {
this.parent({ style_class: 'alt-tab-app',
vertical: true });
this.window = window;
this.actor = new St.BoxLayout({ style_class: 'alt-tab-app',
vertical: true });
this._icon = new St.Widget({ layout_manager: new Clutter.BinLayout() });
this.actor.add(this._icon, { x_fill: false, y_fill: false } );
this.add(this._icon, { x_fill: false, y_fill: false } );
this.label = new St.Label({ text: window.get_title() });
let tracker = Shell.WindowTracker.get_default();
@ -1034,7 +1063,7 @@ var WindowList = new Lang.Class({
this._label = new St.Label({ x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.CENTER });
this.actor.add_actor(this._label);
this.add_actor(this._label);
this.windows = windows;
this.icons = [];
@ -1043,7 +1072,7 @@ var WindowList = new Lang.Class({
let win = windows[i];
let icon = new WindowIcon(win, mode);
this.addItem(icon.actor, icon.label);
this.addItem(icon, icon.label);
this.icons.push(icon);
icon._unmanagedSignalId = icon.window.connect('unmanaged', (window) => {
@ -1051,7 +1080,7 @@ var WindowList = new Lang.Class({
});
}
this.actor.connect('destroy', () => { this._onDestroy(); });
this.connect('destroy', this._onDestroy.bind(this));
},
_onDestroy() {
@ -1060,26 +1089,40 @@ var WindowList = new Lang.Class({
});
},
_getPreferredHeight(actor, forWidth, alloc) {
this.parent(actor, forWidth, alloc);
vfunc_get_preferred_height(forWidth) {
let [minHeight, natHeight] = this.parent(forWidth);
let spacing = this.actor.get_theme_node().get_padding(St.Side.BOTTOM);
let spacing = this.get_theme_node().get_padding(St.Side.BOTTOM);
let [labelMin, labelNat] = this._label.get_preferred_height(-1);
alloc.min_size += labelMin + spacing;
alloc.natural_size += labelNat + spacing;
minHeight += labelMin + spacing;
natHeight += labelNat + spacing;
return [minHeight, natHeight];
},
_allocateTop(actor, box, flags) {
vfunc_allocate(box, flags) {
let themeNode = this.get_theme_node();
let contentBox = themeNode.get_content_box(box);
let childBox = new Clutter.ActorBox();
childBox.x1 = box.x1;
childBox.x2 = box.x2;
childBox.y2 = box.y2;
childBox.x1 = contentBox.x1;
childBox.x2 = contentBox.x2;
childBox.y2 = contentBox.y2;
childBox.y1 = childBox.y2 - this._label.height;
this._label.allocate(childBox, flags);
let spacing = this.actor.get_theme_node().get_padding(St.Side.BOTTOM);
box.y2 -= this._label.height + spacing;
this.parent(actor, box, flags);
let totalLabelHeight = this._label.height + themeNode.get_padding(St.Side.BOTTOM)
childBox.x1 = box.x1;
childBox.x2 = box.x2;
childBox.y1 = box.y1;
childBox.y2 = box.y2 - totalLabelHeight;
this.parent(childBox, flags);
// Hooking up the parent vfunc will call this.set_allocation() with
// the height without the label height, so call it again with the
// correct size here.
this.set_allocation(box, flags);
},
highlight(index, justOutline) {

View File

@ -126,17 +126,17 @@ var BaseAppView = new Lang.Class({
else
this._grid = new IconGrid.IconGrid(gridParams);
this._grid.connect('key-focus-in', (grid, actor) => {
this._keyFocusIn(actor);
this._grid.connect('child-focused', (grid, actor) => {
this._childFocused(actor);
});
// Standard hack for ClutterBinLayout
this._grid.actor.x_expand = true;
this._grid.x_expand = true;
this._items = {};
this._allItems = [];
},
_keyFocusIn(actor) {
_childFocused(actor) {
// Nothing by default
},
@ -203,7 +203,7 @@ var BaseAppView = new Lang.Class({
},
_doSpringAnimation(animationDirection) {
this._grid.actor.opacity = 255;
this._grid.opacity = 255;
this._grid.animateSpring(animationDirection,
Main.overview.getShowAppsButton());
},
@ -217,8 +217,8 @@ var BaseAppView = new Lang.Class({
}
if (animationDirection == IconGrid.AnimationDirection.IN) {
let id = this._grid.actor.connect('paint', () => {
this._grid.actor.disconnect(id);
let id = this._grid.connect('paint', () => {
this._grid.disconnect(id);
this._doSpringAnimation(animationDirection);
});
} else {
@ -228,7 +228,7 @@ var BaseAppView = new Lang.Class({
animateSwitch(animationDirection) {
Tweener.removeTweens(this.actor);
Tweener.removeTweens(this._grid.actor);
Tweener.removeTweens(this._grid);
let params = { time: VIEWS_SWITCH_TIME,
transition: 'easeOutQuad' };
@ -242,7 +242,7 @@ var BaseAppView = new Lang.Class({
params.onComplete = () => { this.actor.hide(); };
}
Tweener.addTween(this._grid.actor, params);
Tweener.addTween(this._grid, params);
}
});
Signals.addSignalMethods(BaseAppView.prototype);
@ -396,7 +396,7 @@ var AllView = new Lang.Class({
let box = new St.BoxLayout({ vertical: true });
this._grid.currentPage = 0;
this._stack.add_actor(this._grid.actor);
this._stack.add_actor(this._grid);
this._eventBlocker = new St.Widget({ x_expand: true, y_expand: true });
this._stack.add_actor(this._eventBlocker);
@ -717,7 +717,7 @@ var AllView = new Lang.Class({
});
},
_keyFocusIn(icon) {
_childFocused(icon) {
let itemPage = this._grid.getItemPage(icon);
this.goToPage(itemPage);
},
@ -745,7 +745,7 @@ var AllView = new Lang.Class({
box.y2 = height;
box = this.actor.get_theme_node().get_content_box(box);
box = this._scrollView.get_theme_node().get_content_box(box);
box = this._grid.actor.get_theme_node().get_content_box(box);
box = this._grid.get_theme_node().get_content_box(box);
let availWidth = box.x2 - box.x1;
let availHeight = box.y2 - box.y1;
let oldNPages = this._grid.nPages();
@ -794,9 +794,9 @@ var FrequentView = new Lang.Class({
y_align: Clutter.ActorAlign.CENTER,
y_expand: true });
this._grid.actor.y_expand = true;
this._grid.y_expand = true;
this.actor.add_actor(this._grid.actor);
this.actor.add_actor(this._grid);
this.actor.add_actor(this._noFrequentAppsLabel);
this._noFrequentAppsLabel.hide();
@ -843,7 +843,7 @@ var FrequentView = new Lang.Class({
box.x2 = width;
box.y2 = height;
box = this.actor.get_theme_node().get_content_box(box);
box = this._grid.actor.get_theme_node().get_content_box(box);
box = this._grid.get_theme_node().get_content_box(box);
let availWidth = box.x2 - box.x1;
let availHeight = box.y2 - box.y1;
this._grid.adaptToSize(availWidth, availHeight);
@ -1141,12 +1141,12 @@ var FolderView = new Lang.Class({
this.parent(null, null);
// If it not expand, the parent doesn't take into account its preferred_width when allocating
// the second time it allocates, so we apply the "Standard hack for ClutterBinLayout"
this._grid.actor.x_expand = true;
this._grid.x_expand = true;
this.actor = new St.ScrollView({ overlay_scrollbars: true });
this.actor.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
let scrollableContainer = new St.BoxLayout({ vertical: true, reactive: true });
scrollableContainer.add_actor(this._grid.actor);
scrollableContainer.add_actor(this._grid);
this.actor.add_actor(scrollableContainer);
let action = new Clutter.PanAction({ interpolate: true });
@ -1154,7 +1154,7 @@ var FolderView = new Lang.Class({
this.actor.add_action(action);
},
_keyFocusIn(actor) {
_childFocused(actor) {
Util.ensureActorVisibleInScrollView(this.actor, actor);
},
@ -1267,7 +1267,7 @@ var FolderIcon = new Lang.Class({
this._popupInvalidated = false;
this.icon = new IconGrid.BaseIcon('', { createIcon: this._createIcon.bind(this), setSizeManually: true });
this.actor.set_child(this.icon.actor);
this.actor.set_child(this.icon);
this.actor.label_actor = this.icon.label;
this.view = new FolderView();
@ -1369,7 +1369,7 @@ var FolderIcon = new Lang.Class({
_updatePopupSize() {
// StWidget delays style calculation until needed, make sure we use the correct values
this.view._grid.actor.ensure_style();
this.view._grid.ensure_style();
let offsetForEachSide = Math.ceil((this._popup.getOffset(St.Side.TOP) +
this._popup.getOffset(St.Side.BOTTOM) -
@ -1537,7 +1537,7 @@ var AppFolderPopup = new Lang.Class({
// is completed so we can animate the icons after as we like without
// showing them while boxpointer is animating.
this._view.actor.opacity = 0;
this._boxPointer.show(BoxPointer.PopupAnimation.FADE |
this._boxPointer.open(BoxPointer.PopupAnimation.FADE |
BoxPointer.PopupAnimation.SLIDE,
() => {
this._view.actor.opacity = 255;
@ -1553,8 +1553,8 @@ var AppFolderPopup = new Lang.Class({
this._grabHelper.ungrab({ actor: this.actor });
this._boxPointer.hide(BoxPointer.PopupAnimation.FADE |
BoxPointer.PopupAnimation.SLIDE);
this._boxPointer.close(BoxPointer.PopupAnimation.FADE |
BoxPointer.PopupAnimation.SLIDE);
this._isOpen = false;
this.emit('open-state-changed', false);
},
@ -1617,7 +1617,7 @@ var AppIcon = new Lang.Class({
iconParams['createIcon'] = this._createIcon.bind(this);
iconParams['setSizeManually'] = true;
this.icon = new IconGrid.BaseIcon(app.get_name(), iconParams);
this._iconContainer.add_child(this.icon.actor);
this._iconContainer.add_child(this.icon);
this.actor.label_actor = this.icon.label;

View File

@ -34,25 +34,25 @@ var POPUP_ANIMATION_TIME = 0.15;
*/
var BoxPointer = new Lang.Class({
Name: 'BoxPointer',
Extends: St.Widget,
Signals: { 'arrow-side-changed': {} },
_init(arrowSide, binProperties) {
this.parent();
this.actor = this;
this.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS);
this._arrowSide = arrowSide;
this._userArrowSide = arrowSide;
this._arrowOrigin = 0;
this._arrowActor = null;
this.actor = new St.Bin({ x_fill: true,
y_fill: true });
this._container = new Shell.GenericContainer();
this.actor.set_child(this._container);
this.actor.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS);
this._container.connect('get-preferred-width', this._getPreferredWidth.bind(this));
this._container.connect('get-preferred-height', this._getPreferredHeight.bind(this));
this._container.connect('allocate', this._allocate.bind(this));
this.bin = new St.Bin(binProperties);
this._container.add_actor(this.bin);
this.add_actor(this.bin);
this._border = new St.DrawingArea();
this._border.connect('repaint', this._drawBorder.bind(this));
this._container.add_actor(this._border);
this.add_actor(this._border);
this.bin.raise(this._border);
this._xOffset = 0;
this._yOffset = 0;
@ -69,19 +69,49 @@ var BoxPointer = new Lang.Class({
_muteInput() {
if (this._capturedEventId == 0)
this._capturedEventId = this.actor.connect('captured-event',
() => Clutter.EVENT_STOP);
this._capturedEventId = this.connect('captured-event',
() => Clutter.EVENT_STOP);
},
_unmuteInput() {
if (this._capturedEventId != 0) {
this.actor.disconnect(this._capturedEventId);
this.disconnect(this._capturedEventId);
this._capturedEventId = 0;
}
},
// BoxPointer.show() and BoxPointer.hide() are here for only compatibility
// purposes, and will be removed in 3.32.
show(animate, onComplete) {
let themeNode = this.actor.get_theme_node();
if (animate !== undefined) {
try {
throw new Error('BoxPointer.show() has been moved to BoxPointer.open(), this code will break in the future.');
} catch(e) {
logError(e);
this.open(animate, onComplete);
return;
}
}
this.visible = true;
},
hide(animate, onComplete) {
if (animate !== undefined) {
try {
throw new Error('BoxPointer.hide() has been moved to BoxPointer.close(), this code will break in the future.');
} catch(e) {
logError(e);
this.close(animate, onComplete);
return;
}
}
this.visible = false;
},
open(animate, onComplete) {
let themeNode = this.get_theme_node();
let rise = themeNode.get_length('-arrow-rise');
let animationTime = (animate & PopupAnimation.FULL) ? POPUP_ANIMATION_TIME : 0;
@ -90,7 +120,7 @@ var BoxPointer = new Lang.Class({
else
this.opacity = 255;
this.actor.show();
this.show();
if (animate & PopupAnimation.SLIDE) {
switch (this._arrowSide) {
@ -121,13 +151,13 @@ var BoxPointer = new Lang.Class({
time: animationTime });
},
hide(animate, onComplete) {
if (!this.actor.visible)
close(animate, onComplete) {
if (!this.visible)
return;
let xOffset = 0;
let yOffset = 0;
let themeNode = this.actor.get_theme_node();
let themeNode = this.get_theme_node();
let rise = themeNode.get_length('-arrow-rise');
let fade = (animate & PopupAnimation.FADE);
let animationTime = (animate & PopupAnimation.FULL) ? POPUP_ANIMATION_TIME : 0;
@ -158,7 +188,7 @@ var BoxPointer = new Lang.Class({
transition: 'linear',
time: animationTime,
onComplete: () => {
this.actor.hide();
this.hide();
this.opacity = 0;
this.xOffset = 0;
this.yOffset = 0;
@ -168,37 +198,48 @@ var BoxPointer = new Lang.Class({
});
},
_adjustAllocationForArrow(isWidth, alloc) {
let themeNode = this.actor.get_theme_node();
_adjustAllocationForArrow(isWidth, minSize, natSize) {
let themeNode = this.get_theme_node();
let borderWidth = themeNode.get_length('-arrow-border-width');
alloc.min_size += borderWidth * 2;
alloc.natural_size += borderWidth * 2;
minSize += borderWidth * 2;
natSize += borderWidth * 2;
if ((!isWidth && (this._arrowSide == St.Side.TOP || this._arrowSide == St.Side.BOTTOM))
|| (isWidth && (this._arrowSide == St.Side.LEFT || this._arrowSide == St.Side.RIGHT))) {
let rise = themeNode.get_length('-arrow-rise');
alloc.min_size += rise;
alloc.natural_size += rise;
minSize += rise;
natSize += rise;
}
return [minSize, natSize];
},
_getPreferredWidth(actor, forHeight, alloc) {
let [minInternalSize, natInternalSize] = this.bin.get_preferred_width(forHeight);
alloc.min_size = minInternalSize;
alloc.natural_size = natInternalSize;
this._adjustAllocationForArrow(true, alloc);
vfunc_get_preferred_width(forHeight) {
let themeNode = this.get_theme_node();
forHeight = themeNode.adjust_for_height(forHeight);
let width = this.bin.get_preferred_width(forHeight);
width = this._adjustAllocationForArrow(true, ...width);
return themeNode.adjust_preferred_width(...width);
},
_getPreferredHeight(actor, forWidth, alloc) {
let themeNode = this.actor.get_theme_node();
vfunc_get_preferred_height(forWidth) {
let themeNode = this.get_theme_node();
let borderWidth = themeNode.get_length('-arrow-border-width');
let [minSize, naturalSize] = this.bin.get_preferred_height(forWidth - 2 * borderWidth);
alloc.min_size = minSize;
alloc.natural_size = naturalSize;
this._adjustAllocationForArrow(false, alloc);
forWidth = themeNode.adjust_for_width(forWidth);
let height = this.bin.get_preferred_height(forWidth - 2 * borderWidth);
height = this._adjustAllocationForArrow(false, ...height);
return themeNode.adjust_preferred_height(...height);
},
_allocate(actor, box, flags) {
let themeNode = this.actor.get_theme_node();
vfunc_allocate(box, flags) {
this.set_allocation(box, flags);
let themeNode = this.get_theme_node();
box = themeNode.get_content_box(box);
let borderWidth = themeNode.get_length('-arrow-border-width');
let rise = themeNode.get_length('-arrow-rise');
let childBox = new Clutter.ActorBox();
@ -238,12 +279,12 @@ var BoxPointer = new Lang.Class({
},
_drawBorder(area) {
let themeNode = this.actor.get_theme_node();
let themeNode = this.get_theme_node();
if (this._arrowActor) {
let [sourceX, sourceY] = this._arrowActor.get_transformed_position();
let [sourceWidth, sourceHeight] = this._arrowActor.get_transformed_size();
let [absX, absY] = this.actor.get_transformed_position();
let [absX, absY] = this.get_transformed_position();
if (this._arrowSide == St.Side.TOP ||
this._arrowSide == St.Side.BOTTOM) {
@ -422,7 +463,7 @@ var BoxPointer = new Lang.Class({
setPosition(sourceActor, alignment) {
// We need to show it now to force an allocation,
// so that we can query the correct size.
this.actor.show();
this.show();
this._sourceActor = sourceActor;
this._arrowAlignment = alignment;
@ -450,13 +491,13 @@ var BoxPointer = new Lang.Class({
let sourceAllocation = Shell.util_get_transformed_allocation(sourceActor);
let sourceCenterX = sourceAllocation.x1 + sourceContentBox.x1 + (sourceContentBox.x2 - sourceContentBox.x1) * this._sourceAlignment;
let sourceCenterY = sourceAllocation.y1 + sourceContentBox.y1 + (sourceContentBox.y2 - sourceContentBox.y1) * this._sourceAlignment;
let [minWidth, minHeight, natWidth, natHeight] = this.actor.get_preferred_size();
let [minWidth, minHeight, natWidth, natHeight] = this.get_preferred_size();
// We also want to keep it onscreen, and separated from the
// edge by the same distance as the main part of the box is
// separated from its sourceActor
let monitor = Main.layoutManager.findMonitorForActor(sourceActor);
let themeNode = this.actor.get_theme_node();
let themeNode = this.get_theme_node();
let borderWidth = themeNode.get_length('-arrow-border-width');
let arrowBase = themeNode.get_length('-arrow-base');
let borderRadius = themeNode.get_length('-arrow-border-radius');
@ -542,7 +583,7 @@ var BoxPointer = new Lang.Class({
this.setArrowOrigin(arrowOrigin);
let parent = this.actor.get_parent();
let parent = this.get_parent();
let success, x, y;
while (!success) {
[success, x, y] = parent.transform_stage_point(resX, resY);
@ -581,16 +622,16 @@ var BoxPointer = new Lang.Class({
// allocation loops and warnings. Instead we do the positioning via
// the anchor point, which is independent of allocation, and leave
// x == y == 0.
this.actor.set_anchor_point(-(this._xPosition + this._xOffset),
-(this._yPosition + this._yOffset));
this.set_anchor_point(-(this._xPosition + this._xOffset),
-(this._yPosition + this._yOffset));
},
_calculateArrowSide(arrowSide) {
let sourceAllocation = Shell.util_get_transformed_allocation(this._sourceActor);
let [minWidth, minHeight, boxWidth, boxHeight] = this._container.get_preferred_size();
let [minWidth, minHeight, boxWidth, boxHeight] = this.get_preferred_size();
let monitorActor = this.sourceActor;
if (!monitorActor)
monitorActor = this.actor;
monitorActor = this;
let monitor = Main.layoutManager.findMonitorForActor(monitorActor);
switch (arrowSide) {
@ -625,7 +666,7 @@ var BoxPointer = new Lang.Class({
this._arrowSide = arrowSide;
this._reposition();
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
this._container.queue_relayout();
this.queue_relayout();
return false;
});
@ -651,14 +692,6 @@ var BoxPointer = new Lang.Class({
return this._yOffset;
},
set opacity(opacity) {
this.actor.opacity = opacity;
},
get opacity() {
return this.actor.opacity;
},
updateArrowSide(side) {
this._arrowSide = side;
this._border.queue_repaint();
@ -671,7 +704,6 @@ var BoxPointer = new Lang.Class({
},
getArrowHeight() {
return this.actor.get_theme_node().get_length('-arrow-rise');
return this.get_theme_node().get_length('-arrow-rise');
}
});
Signals.addSignalMethods(BoxPointer.prototype);

View File

@ -773,9 +773,11 @@ var NotificationMessage = new Lang.Class({
this.connect('close', () => {
this._closed = true;
this.notification.destroy(MessageTray.NotificationDestroyedReason.DISMISSED);
if (this.notification)
this.notification.destroy(MessageTray.NotificationDestroyedReason.DISMISSED);
});
this._destroyId = notification.connect('destroy', () => {
this.notification = null;
if (!this._closed)
this.close();
});
@ -866,11 +868,11 @@ var EventsSection = new Lang.Class({
if (sameYear(this._date, now))
/* Translators: Shown on calendar heading when selected day occurs on current year */
dayFormat = Shell.util_translate_time_string(NC_("calendar heading",
"%A, %B %d"));
"%A, %B %-d"));
else
/* Translators: Shown on calendar heading when selected day occurs on different year */
dayFormat = Shell.util_translate_time_string(NC_("calendar heading",
"%A, %B %d, %Y"));
"%A, %B %-d, %Y"));
this._title.label = this._date.toLocaleFormat(dayFormat);
},

View File

@ -197,9 +197,13 @@ var AutomountManager = new Lang.Class({
this._closeOperation(volume);
} catch (e) {
// FIXME: we will always get G_IO_ERROR_FAILED from the gvfs udisks
// backend in this case, see
// https://bugs.freedesktop.org/show_bug.cgi?id=51271
if (e.message.indexOf('No key available with this passphrase') != -1) {
// backend, see https://bugs.freedesktop.org/show_bug.cgi?id=51271
// To reask the password if the user input was empty or wrong, we
// will check for corresponding error messages. However, these
// error strings are not unique for the cases in the comments below.
if (e.message.includes('No key available with this passphrase') || // cryptsetup
e.message.includes('No key available to unlock device') || // udisks (no password)
e.message.includes('Error unlocking')) { // udisks (wrong password)
this._reaskPassword(volume);
} else {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.FAILED_HANDLED))

View File

@ -12,7 +12,7 @@ const SwitcherPopup = imports.ui.switcherPopup;
const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
var POPUP_APPICON_SIZE = 96;
var POPUP_APPICON_SIZE = 128;
var POPUP_FADE_TIME = 0.1; // seconds
var SortGroup = {
@ -125,10 +125,10 @@ var CtrlAltTabManager = new Lang.Class({
this._popup = new CtrlAltTabPopup(items);
this._popup.show(backward, binding, mask);
this._popup.actor.connect('destroy',
() => {
this._popup = null;
});
this._popup.connect('destroy',
() => {
this._popup = null;
});
}
},

View File

@ -38,7 +38,10 @@ var DashItemContainer = new Lang.Class({
Extends: St.Widget,
_init() {
this.parent({ style_class: 'dash-item-container' });
this.parent({ style_class: 'dash-item-container',
pivot_point: new Clutter.Point({ x: .5, y: .5 }),
x_expand: true,
x_align: Clutter.ActorAlign.CENTER });
this._labelText = "";
this.label = new St.Label({ style_class: 'dash-label'});
@ -56,52 +59,20 @@ var DashItemContainer = new Lang.Class({
});
},
vfunc_allocate(box, flags) {
this.set_allocation(box, flags);
if (this.child == null)
return;
let availWidth = box.x2 - box.x1;
let availHeight = box.y2 - box.y1;
let [minChildWidth, minChildHeight, natChildWidth, natChildHeight] =
this.child.get_preferred_size();
let [childScaleX, childScaleY] = this.child.get_scale();
let childWidth = Math.min(natChildWidth * childScaleX, availWidth);
let childHeight = Math.min(natChildHeight * childScaleY, availHeight);
let childBox = new Clutter.ActorBox();
childBox.x1 = (availWidth - childWidth) / 2;
childBox.y1 = (availHeight - childHeight) / 2;
childBox.x2 = childBox.x1 + childWidth;
childBox.y2 = childBox.y1 + childHeight;
this.child.allocate(childBox, flags);
},
vfunc_get_preferred_height(forWidth) {
let themeNode = this.get_theme_node();
if (this.child == null)
return [0, 0];
forWidth = themeNode.adjust_for_width(forWidth);
let [minHeight, natHeight] = this.child.get_preferred_height(forWidth);
return themeNode.adjust_preferred_height(minHeight * this.child.scale_y,
natHeight * this.child.scale_y);
let [minHeight, natHeight] = this.parent(forWidth);
return themeNode.adjust_preferred_height(minHeight * this.scale_y,
natHeight * this.scale_y);
},
vfunc_get_preferred_width(forHeight) {
let themeNode = this.get_theme_node();
if (this.child == null)
return [0, 0];
forHeight = themeNode.adjust_for_height(forHeight);
let [minWidth, natWidth] = this.child.get_preferred_width(forHeight);
return themeNode.adjust_preferred_width(minWidth * this.child.scale_y,
natWidth * this.child.scale_y);
let [minWidth, natWidth] = this.parent(forHeight);
return themeNode.adjust_preferred_width(minWidth * this.scale_x,
natWidth * this.scale_x);
},
showLabel() {
@ -163,9 +134,8 @@ var DashItemContainer = new Lang.Class({
this.child = actor;
this.add_actor(this.child);
this.child.set_scale_with_gravity(this._childScale, this._childScale,
Clutter.Gravity.CENTER);
this.child.set_opacity(this._childOpacity);
this.set_scale(this._childScale, this._childScale);
this.set_opacity(this._childOpacity);
},
show(animate) {
@ -204,11 +174,7 @@ var DashItemContainer = new Lang.Class({
set childScale(scale) {
this._childScale = scale;
if (this.child == null)
return;
this.child.set_scale_with_gravity(scale, scale,
Clutter.Gravity.CENTER);
this.set_scale(scale, scale);
this.queue_relayout();
},
@ -219,10 +185,7 @@ var DashItemContainer = new Lang.Class({
set childOpacity(opacity) {
this._childOpacity = opacity;
if (this.child == null)
return;
this.child.set_opacity(opacity);
this.set_opacity(opacity);
this.queue_redraw();
},
@ -247,7 +210,7 @@ var ShowAppsIcon = new Lang.Class({
{ setSizeManually: true,
showLabel: false,
createIcon: this._createIcon.bind(this) });
this.toggleButton.add_actor(this.icon.actor);
this.toggleButton.add_actor(this.icon);
this.toggleButton._delegate = this;
this.setChild(this.toggleButton);
@ -643,10 +606,10 @@ var Dash = new Lang.Class({
// Enforce the current icon size during the size request
firstIcon.icon.ensure_style();
let [currentWidth, currentHeight] = firstIcon.icon.get_size();
firstIcon.icon.set_size(this.iconSize * scaleFactor, this.iconSize * scaleFactor);
let [, currentHeight] = firstIcon.icon.get_size();
firstIcon.icon.set_height(this.iconSize * scaleFactor);
[minHeight, natHeight] = firstButton.get_preferred_height(-1);
firstIcon.icon.set_size(currentWidth, currentHeight);
firstIcon.icon.set_height(currentHeight);
// Subtract icon padding and box spacing from the available height
availHeight -= iconChildren.length * (natHeight - this.iconSize * scaleFactor) +

View File

@ -69,9 +69,11 @@ var TodayButton = new Lang.Class({
this._dayLabel.set_text(date.toLocaleFormat('%A'));
/* Translators: This is the date format to use when the calendar popup is
* shown - it is shown just below the time in the shell (e.g. "Tue 9:29 AM").
* shown - it is shown just below the time in the top bar (e.g.,
* "Tue 9:29 AM"). The string itself should become a full date, e.g.,
* "February 17 2015".
*/
let dateFormat = Shell.util_translate_time_string (N_("%B %e %Y"));
let dateFormat = Shell.util_translate_time_string (N_("%B %-d %Y"));
this._dateLabel.set_text(date.toLocaleFormat(dateFormat));
/* Translators: This is the accessible name of the date button shown

View File

@ -133,9 +133,9 @@ var CandidatePopup = new Lang.Class({
_init() {
this._boxPointer = new BoxPointer.BoxPointer(St.Side.TOP);
this._boxPointer.actor.visible = false;
this._boxPointer.actor.style_class = 'candidate-popup-boxpointer';
Main.layoutManager.addChrome(this._boxPointer.actor);
this._boxPointer.visible = false;
this._boxPointer.style_class = 'candidate-popup-boxpointer';
Main.layoutManager.addChrome(this._boxPointer);
let box = new St.BoxLayout({ style_class: 'candidate-popup-content',
vertical: true });
@ -272,7 +272,7 @@ var CandidatePopup = new Lang.Class({
this._updateVisibility();
});
panelService.connect('focus-out', ps => {
this._boxPointer.hide(BoxPointer.PopupAnimation.NONE);
this._boxPointer.close(BoxPointer.PopupAnimation.NONE);
Main.keyboard.resetSuggestions();
});
},
@ -291,10 +291,10 @@ var CandidatePopup = new Lang.Class({
if (isVisible) {
this._boxPointer.setPosition(Main.layoutManager.dummyCursor, 0);
this._boxPointer.show(BoxPointer.PopupAnimation.NONE);
this._boxPointer.open(BoxPointer.PopupAnimation.NONE);
this._boxPointer.actor.raise_top();
} else {
this._boxPointer.hide(BoxPointer.PopupAnimation.NONE);
this._boxPointer.close(BoxPointer.PopupAnimation.NONE);
}
},

View File

@ -12,8 +12,8 @@ const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
const Main = imports.ui.main;
var ICON_SIZE = 96;
var MIN_ICON_SIZE = 16;
var ICON_SIZE = 128;
var MIN_ICON_SIZE = 32;
var EXTRA_SPACE_ANIMATION_TIME = 0.25;
@ -36,6 +36,7 @@ var APPICON_ANIMATION_OUT_TIME = 0.25;
var BaseIcon = new Lang.Class({
Name: 'BaseIcon',
Extends: St.Bin,
_init(label, params) {
params = Params.parse(params, { createIcon: null,
@ -46,32 +47,26 @@ var BaseIcon = new Lang.Class({
if (params.showLabel)
styleClass += ' overview-icon-with-label';
this.actor = new St.Bin({ style_class: styleClass,
x_fill: true,
y_fill: true });
this.actor._delegate = this;
this.actor.connect('style-changed', this._onStyleChanged.bind(this));
this.actor.connect('destroy', this._onDestroy.bind(this));
this.parent({ style_class: styleClass,
x_fill: true,
y_fill: true });
this._spacing = 0;
this.actor = this;
let box = new Shell.GenericContainer();
box.connect('allocate', this._allocate.bind(this));
box.connect('get-preferred-width',
this._getPreferredWidth.bind(this));
box.connect('get-preferred-height',
this._getPreferredHeight.bind(this));
this.actor.set_child(box);
this.connect('destroy', this._onDestroy.bind(this));
this._box = new St.BoxLayout({ vertical: true });
this.set_child(this._box);
this.iconSize = ICON_SIZE;
this._iconBin = new St.Bin({ x_align: St.Align.MIDDLE,
y_align: St.Align.MIDDLE });
box.add_actor(this._iconBin);
this._box.add_actor(this._iconBin);
if (params.showLabel) {
this.label = new St.Label({ text: label });
box.add_actor(this.label);
this._box.add_actor(this.label);
} else {
this.label = null;
}
@ -86,54 +81,9 @@ var BaseIcon = new Lang.Class({
this._iconThemeChangedId = cache.connect('icon-theme-changed', this._onIconThemeChanged.bind(this));
},
_allocate(actor, box, flags) {
let availWidth = box.x2 - box.x1;
let availHeight = box.y2 - box.y1;
let iconSize = availHeight;
let [iconMinHeight, iconNatHeight] = this._iconBin.get_preferred_height(-1);
let [iconMinWidth, iconNatWidth] = this._iconBin.get_preferred_width(-1);
let preferredHeight = iconNatHeight;
let childBox = new Clutter.ActorBox();
if (this.label) {
let [labelMinHeight, labelNatHeight] = this.label.get_preferred_height(-1);
preferredHeight += this._spacing + labelNatHeight;
let labelHeight = availHeight >= preferredHeight ? labelNatHeight
: labelMinHeight;
iconSize -= this._spacing + labelHeight;
childBox.x1 = 0;
childBox.x2 = availWidth;
childBox.y1 = iconSize + this._spacing;
childBox.y2 = childBox.y1 + labelHeight;
this.label.allocate(childBox, flags);
}
childBox.x1 = Math.floor((availWidth - iconNatWidth) / 2);
childBox.y1 = Math.floor((iconSize - iconNatHeight) / 2);
childBox.x2 = childBox.x1 + iconNatWidth;
childBox.y2 = childBox.y1 + iconNatHeight;
this._iconBin.allocate(childBox, flags);
},
_getPreferredWidth(actor, forHeight, alloc) {
this._getPreferredHeight(actor, -1, alloc);
},
_getPreferredHeight(actor, forWidth, alloc) {
let [iconMinHeight, iconNatHeight] = this._iconBin.get_preferred_height(forWidth);
alloc.min_size = iconMinHeight;
alloc.natural_size = iconNatHeight;
if (this.label) {
let [labelMinHeight, labelNatHeight] = this.label.get_preferred_height(forWidth);
alloc.min_size += this._spacing + labelMinHeight;
alloc.natural_size += this._spacing + labelNatHeight;
}
vfunc_get_preferred_width(forHeight) {
// Return the actual height to keep the squared aspect
return this.get_preferred_height(-1);
},
// This can be overridden by a subclass, or by the createIcon
@ -161,9 +111,8 @@ var BaseIcon = new Lang.Class({
this._iconBin.child = this.icon;
},
_onStyleChanged() {
let node = this.actor.get_theme_node();
this._spacing = node.get_length('spacing');
vfunc_style_changed() {
let node = this.get_theme_node();
let size;
if (this._setSizeManually) {
@ -195,7 +144,7 @@ var BaseIcon = new Lang.Class({
// Animate only the child instead of the entire actor, so the
// styles like hover and running are not applied while
// animating.
zoomOutActor(this.actor.child);
zoomOutActor(this.child);
}
});
@ -240,8 +189,16 @@ function zoomOutActor(actor) {
var IconGrid = new Lang.Class({
Name: 'IconGrid',
Extends: St.Widget,
Signals: {'animation-done': {},
'child-focused': { param_types: [Clutter.Actor.$gtype]} },
_init(params) {
this.parent({ style_class: 'icon-grid',
y_align: Clutter.ActorAlign.START });
this.actor = this;
params = Params.parse(params, { rowLimit: null,
columnLimit: null,
minRows: 1,
@ -262,34 +219,27 @@ var IconGrid = new Lang.Class({
this.rightPadding = 0;
this.leftPadding = 0;
this.actor = new St.BoxLayout({ style_class: 'icon-grid',
vertical: true });
this._items = [];
this._clonesAnimating = [];
// Pulled from CSS, but hardcode some defaults here
this._spacing = 0;
this._hItemSize = this._vItemSize = ICON_SIZE;
this._fixedHItemSize = this._fixedVItemSize = undefined;
this._grid = new Shell.GenericContainer();
this.actor.add(this._grid, { expand: true, y_align: St.Align.START });
this.actor.connect('style-changed', this._onStyleChanged.bind(this));
this.connect('style-changed', this._onStyleChanged.bind(this));
// Cancel animations when hiding the overview, to avoid icons
// swarming into the void ...
this.actor.connect('notify::mapped', () => {
if (!this.actor.mapped)
this.connect('notify::mapped', () => {
if (!this.mapped)
this._cancelAnimation();
});
this._grid.connect('get-preferred-width', this._getPreferredWidth.bind(this));
this._grid.connect('get-preferred-height', this._getPreferredHeight.bind(this));
this._grid.connect('allocate', this._allocate.bind(this));
this._grid.connect('actor-added', this._childAdded.bind(this));
this._grid.connect('actor-removed', this._childRemoved.bind(this));
this.connect('actor-added', this._childAdded.bind(this));
this.connect('actor-removed', this._childRemoved.bind(this));
},
_keyFocusIn(actor) {
this.emit('key-focus-in', actor);
this.emit('child-focused', actor);
},
_childAdded(grid, child) {
@ -300,13 +250,13 @@ var IconGrid = new Lang.Class({
child.disconnect(child._iconGridKeyFocusInId);
},
_getPreferredWidth(grid, forHeight, alloc) {
vfunc_get_preferred_width(forHeight) {
if (this._fillParent)
// Ignore all size requests of children and request a size of 0;
// later we'll allocate as many children as fit the parent
return;
return [0, 0];
let nChildren = this._grid.get_n_children();
let nChildren = this.get_n_children();
let nColumns = this._colLimit ? Math.min(this._colLimit,
nChildren)
: nChildren;
@ -314,22 +264,28 @@ var IconGrid = new Lang.Class({
// Kind of a lie, but not really an issue right now. If
// we wanted to support some sort of hidden/overflow that would
// need higher level design
alloc.min_size = this._getHItemSize() + this.leftPadding + this.rightPadding;
alloc.natural_size = nColumns * this._getHItemSize() + totalSpacing + this.leftPadding + this.rightPadding;
let minSize = this._getHItemSize() + this.leftPadding + this.rightPadding;
let natSize = nColumns * this._getHItemSize() + totalSpacing + this.leftPadding + this.rightPadding;
return this.get_theme_node().adjust_preferred_width(minSize, natSize);
},
_getVisibleChildren() {
return this._grid.get_children().filter(actor => actor.visible);
return this.get_children().filter(actor => actor.visible);
},
_getPreferredHeight(grid, forWidth, alloc) {
vfunc_get_preferred_height(forWidth) {
if (this._fillParent)
// Ignore all size requests of children and request a size of 0;
// later we'll allocate as many children as fit the parent
return;
return [0, 0];
let themeNode = this.get_theme_node();
let children = this._getVisibleChildren();
let nColumns;
forWidth = themeNode.adjust_for_width(forWidth);
if (forWidth < 0)
nColumns = children.length;
else
@ -344,16 +300,21 @@ var IconGrid = new Lang.Class({
nRows = Math.min(nRows, this._rowLimit);
let totalSpacing = Math.max(0, nRows - 1) * this._getSpacing();
let height = nRows * this._getVItemSize() + totalSpacing + this.topPadding + this.bottomPadding;
alloc.min_size = height;
alloc.natural_size = height;
return themeNode.adjust_preferred_height(height, height);
},
_allocate(grid, box, flags) {
vfunc_allocate(box, flags) {
this.set_allocation(box, flags);
let themeNode = this.get_theme_node();
box = themeNode.get_content_box(box);
if (this._fillParent) {
// Reset the passed in box to fill the parent
let parentBox = this.actor.get_parent().allocation;
let gridBox = this.actor.get_theme_node().get_content_box(parentBox);
box = this._grid.get_theme_node().get_content_box(gridBox);
let parentBox = this.get_parent().allocation;
let gridBox = themeNode.get_content_box(parentBox);
box = themeNode.get_content_box(gridBox);
}
let children = this._getVisibleChildren();
@ -383,10 +344,10 @@ var IconGrid = new Lang.Class({
if (this._rowLimit && rowIndex >= this._rowLimit ||
this._fillParent && childBox.y2 > availHeight - this.bottomPadding) {
this._grid.set_skip_paint(children[i], true);
children[i]._skipPaint = true;
} else {
children[i].allocate(childBox, flags);
this._grid.set_skip_paint(children[i], false);
children[i]._skipPaint = false;
}
columnIndex++;
@ -404,6 +365,66 @@ var IconGrid = new Lang.Class({
}
},
vfunc_paint() {
this.paint_background();
this.get_children().forEach(c => {
if (!c._skipPaint)
c.paint();
});
},
vfunc_pick(color) {
this.parent(color);
this.get_children().forEach(c => {
if (!c._skipPaint)
c.paint();
});
},
vfunc_get_paint_volume(paintVolume) {
// Setting the paint volume does not make sense when we don't have
// any allocation
if (!this.has_allocation())
return false;
let themeNode = this.get_theme_node();
let allocationBox = this.get_allocation_box();
let paintBox = themeNode.get_paint_box(allocationBox);
let origin = new Clutter.Vertex();
origin.x = paintBox.x1 - allocationBox.x1;
origin.y = paintBox.y1 - allocationBox.y1;
origin.z = 0.0;
paintVolume.set_origin(origin);
paintVolume.set_width(paintBox.x2 - paintBox.x1);
paintVolume.set_height(paintBox.y2 - paintBox.y1);
if (this.get_clip_to_allocation())
return true;
for (let child = this.get_first_child();
child != null;
child = child.get_next_sibling()) {
if (!child.visible)
continue;
if (child._skipPaint)
continue;
let childVolume = child.get_transformed_paint_volume(this);
if (!childVolume)
return false
paintVolume.union(childVolume);
}
return true;
},
/**
* Intended to be override by subclasses if they need a different
* set of items to be animated.
@ -629,11 +650,11 @@ var IconGrid = new Lang.Class({
},
_onStyleChanged() {
let themeNode = this.actor.get_theme_node();
let themeNode = this.get_theme_node();
this._spacing = themeNode.get_length('spacing');
this._hItemSize = themeNode.get_length('-shell-grid-horizontal-item-size') || ICON_SIZE;
this._vItemSize = themeNode.get_length('-shell-grid-vertical-item-size') || ICON_SIZE;
this._grid.queue_relayout();
this.queue_relayout();
},
nRows(forWidth) {
@ -665,12 +686,12 @@ var IconGrid = new Lang.Class({
removeAll() {
this._items = [];
this._grid.remove_all_children();
this.remove_all_children();
},
destroyAll() {
this._items = [];
this._grid.destroy_all_children();
this.destroy_all_children();
},
addItem(item, index) {
@ -679,21 +700,21 @@ var IconGrid = new Lang.Class({
this._items.push(item);
if (index !== undefined)
this._grid.insert_child_at_index(item.actor, index);
this.insert_child_at_index(item.actor, index);
else
this._grid.add_actor(item.actor);
this.add_actor(item.actor);
},
removeItem(item) {
this._grid.remove_child(item.actor);
this.remove_child(item.actor);
},
getItemAtIndex(index) {
return this._grid.get_child_at_index(index);
return this.get_child_at_index(index);
},
visibleItemsCount() {
return this._grid.get_n_children() - this._grid.get_n_skip_paint();
return this.get_children().filter(c => !c._skipPaint).length;
},
setSpacing(spacing) {
@ -779,11 +800,12 @@ var IconGrid = new Lang.Class({
}
}
});
Signals.addSignalMethods(IconGrid.prototype);
var PaginatedIconGrid = new Lang.Class({
Name: 'PaginatedIconGrid',
Extends: IconGrid,
Signals: {'space-opened': {},
'space-closed': {} },
_init(params) {
this.parent(params);
@ -794,20 +816,22 @@ var PaginatedIconGrid = new Lang.Class({
this._childrenPerPage = 0;
},
_getPreferredHeight(grid, forWidth, alloc) {
alloc.min_size = (this._availableHeightPerPageForItems() + this.bottomPadding + this.topPadding) * this._nPages + this._spaceBetweenPages * this._nPages;
alloc.natural_size = (this._availableHeightPerPageForItems() + this.bottomPadding + this.topPadding) * this._nPages + this._spaceBetweenPages * this._nPages;
vfunc_get_preferred_height(forWidth) {
let height = (this._availableHeightPerPageForItems() + this.bottomPadding + this.topPadding) * this._nPages + this._spaceBetweenPages * this._nPages;
return [height, height];
},
_allocate(grid, box, flags) {
vfunc_allocate(box, flags) {
if (this._childrenPerPage == 0)
log('computePages() must be called before allocate(); pagination will not work.');
this.set_allocation(box, flags);
if (this._fillParent) {
// Reset the passed in box to fill the parent
let parentBox = this.actor.get_parent().allocation;
let gridBox = this.actor.get_theme_node().get_content_box(parentBox);
box = this._grid.get_theme_node().get_content_box(gridBox);
let parentBox = this.get_parent().allocation;
let gridBox = this.get_theme_node().get_content_box(parentBox);
box = this.get_theme_node().get_content_box(gridBox);
}
let children = this._getVisibleChildren();
let availWidth = box.x2 - box.x1;
@ -835,7 +859,7 @@ var PaginatedIconGrid = new Lang.Class({
for (let i = 0; i < children.length; i++) {
let childBox = this._calculateChildBox(children[i], x, y, box);
children[i].allocate(childBox, flags);
this._grid.set_skip_paint(children[i], false);
children[i]._skipPaint = false;
columnIndex++;
if (columnIndex == nColumns) {
@ -1006,4 +1030,3 @@ var PaginatedIconGrid = new Lang.Class({
}
}
});
Signals.addSignalMethods(PaginatedIconGrid.prototype);

View File

@ -269,7 +269,7 @@ var Key = new Lang.Class({
_onDestroy() {
if (this._boxPointer) {
this._boxPointer.actor.destroy();
this._boxPointer.destroy();
this._boxPointer = null;
}
},
@ -282,7 +282,7 @@ var Key = new Lang.Class({
{ x_fill: true,
y_fill: true,
x_align: St.Align.START });
this._boxPointer.actor.hide();
this._boxPointer.hide();
Main.layoutManager.addChrome(this._boxPointer.actor);
this._boxPointer.setPosition(this.keyButton, 0.5);
@ -356,7 +356,7 @@ var Key = new Lang.Class({
},
_showSubkeys() {
this._boxPointer.show(BoxPointer.PopupAnimation.FULL);
this._boxPointer.open(BoxPointer.PopupAnimation.FULL);
this._capturedEventId = global.stage.connect('captured-event',
this._onCapturedEvent.bind(this));
this._unmapId = this.keyButton.connect('notify::mapped', () => {
@ -367,7 +367,7 @@ var Key = new Lang.Class({
_hideSubkeys() {
if (this._boxPointer)
this._boxPointer.hide(BoxPointer.PopupAnimation.FULL);
this._boxPointer.close(BoxPointer.PopupAnimation.FULL);
if (this._capturedEventId) {
global.stage.disconnect(this._capturedEventId);
this._capturedEventId = 0;

View File

@ -177,8 +177,16 @@ const defaultParams = {
var LayoutManager = new Lang.Class({
Name: 'LayoutManager',
Extends: GObject.Object,
Signals: { 'hot-corners-changed': {},
'startup-complete': {},
'startup-prepared': {},
'monitors-changed': {},
'keyboard-visible-changed': { param_types: [GObject.TYPE_BOOLEAN] } },
_init() {
this.parent();
this._rtl = (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL);
this.monitors = [];
this.primaryMonitor = null;
@ -203,21 +211,12 @@ var LayoutManager = new Lang.Class({
global.stage.no_clear_hint = true;
// Set up stage hierarchy to group all UI actors under one container.
this.uiGroup = new Shell.GenericContainer({ name: 'uiGroup' });
this.uiGroup = new St.Widget({ 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++)
children[i].allocate_preferred_size(flags);
});
this.uiGroup.connect('get-preferred-width', (actor, forHeight, alloc) => {
let width = global.stage.width;
[alloc.min_size, alloc.natural_size] = [width, width];
});
this.uiGroup.connect('get-preferred-height', (actor, forWidth, alloc) => {
let height = global.stage.height;
[alloc.min_size, alloc.natural_size] = [height, height];
});
this.uiGroup.add_constraint(new Clutter.BindConstraint({
source: global.stage,
coordinate: Clutter.BindCoordinate.ALL,
}));
global.stage.remove_actor(global.window_group);
this.uiGroup.add_actor(global.window_group);
@ -1078,7 +1077,6 @@ var LayoutManager = new Lang.Class({
this._queueUpdateRegions();
},
});
Signals.addSignalMethods(LayoutManager.prototype);
// HotCorner:

View File

@ -4,6 +4,7 @@ const Clutter = imports.gi.Clutter;
const Cogl = imports.gi.Cogl;
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
const Meta = imports.gi.Meta;
const Pango = imports.gi.Pango;
@ -501,18 +502,21 @@ var RedBorderEffect = new Lang.Class({
var Inspector = new Lang.Class({
Name: 'Inspector',
Extends: Clutter.Actor,
Signals: { 'closed': {},
'target': { param_types: [Clutter.Actor.$gtype, GObject.TYPE_DOUBLE, GObject.TYPE_DOUBLE] } },
_init(lookingGlass) {
let container = new Shell.GenericContainer({ width: 0,
height: 0 });
container.connect('allocate', this._allocate.bind(this));
Main.uiGroup.add_actor(container);
this.parent({ width: 0,
height: 0 });
Main.uiGroup.add_actor(this);
let eventHandler = new St.BoxLayout({ name: 'LookingGlassDialog',
vertical: false,
reactive: true });
this._eventHandler = eventHandler;
container.add_actor(eventHandler);
this.add_actor(eventHandler);
this._displayText = new St.Label();
eventHandler.add(this._displayText, { expand: true });
@ -534,7 +538,9 @@ var Inspector = new Lang.Class({
this._lookingGlass = lookingGlass;
},
_allocate(actor, box, flags) {
vfunc_allocate(box, flags) {
this.set_allocation(box, flags);
if (!this._eventHandler)
return;
@ -631,8 +637,6 @@ var Inspector = new Lang.Class({
}
});
Signals.addSignalMethods(Inspector.prototype);
var Extensions = new Lang.Class({
Name: 'Extensions',

View File

@ -50,12 +50,15 @@ var State = {
// These reasons are useful when we destroy the notifications received through
// the notification daemon. We use EXPIRED for notifications that we dismiss
// and the user did not interact with, DISMISSED for all other notifications
// that were destroyed as a result of a user action, and SOURCE_CLOSED for the
// notifications that were requested to be destroyed by the associated source.
// that were destroyed as a result of a user action, SOURCE_CLOSED for the
// notifications that were requested to be destroyed by the associated source,
// and REPLACED for notifications that were destroyed as a consequence of a
// newer version having replaced them.
var NotificationDestroyedReason = {
EXPIRED: 1,
DISMISSED: 2,
SOURCE_CLOSED: 3
SOURCE_CLOSED: 3,
REPLACED: 4
};
// Message tray has its custom Urgency enumeration. LOW, NORMAL and CRITICAL
@ -587,16 +590,16 @@ var NotificationBanner = new Lang.Class({
var SourceActor = new Lang.Class({
Name: 'SourceActor',
Extends: St.Widget,
_init(source, size) {
this.parent();
this._source = source;
this._size = size;
this.actor = new Shell.GenericContainer();
this.actor.connect('get-preferred-width', this._getPreferredWidth.bind(this));
this.actor.connect('get-preferred-height', this._getPreferredHeight.bind(this));
this.actor.connect('allocate', this._allocate.bind(this));
this.actor.connect('destroy', () => {
this.actor = this;
this.connect('destroy', () => {
this._source.disconnect(this._iconUpdatedId);
this._actorDestroyed = true;
});
@ -604,10 +607,11 @@ var SourceActor = new Lang.Class({
let scale_factor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
this._iconBin = new St.Bin({ x_fill: true,
x_expand: true,
height: size * scale_factor,
width: size * scale_factor });
this.actor.add_actor(this._iconBin);
this.add_actor(this._iconBin);
this._iconUpdatedId = this._source.connect('icon-updated', this._updateIcon.bind(this));
this._updateIcon();
@ -618,21 +622,6 @@ var SourceActor = new Lang.Class({
this._iconSet = true;
},
_getPreferredWidth(actor, forHeight, alloc) {
let [min, nat] = this._iconBin.get_preferred_width(forHeight);
alloc.min_size = min; alloc.nat_size = nat;
},
_getPreferredHeight(actor, forWidth, alloc) {
let [min, nat] = this._iconBin.get_preferred_height(forWidth);
alloc.min_size = min; alloc.nat_size = nat;
},
_allocate(actor, box, flags) {
// the iconBin should fill our entire box
this._iconBin.allocate(box, flags);
},
_updateIcon() {
if (this._actorDestroyed)
return;
@ -665,23 +654,23 @@ var SourceActorWithLabel = new Lang.Class({
this._counterBin.translation_y = themeNode.get_length('-shell-counter-overlap-y');
});
this.actor.add_actor(this._counterBin);
this.add_actor(this._counterBin);
this._countUpdatedId = this._source.connect('count-updated', this._updateCount.bind(this));
this._updateCount();
this.actor.connect('destroy', () => {
this.connect('destroy', () => {
this._source.disconnect(this._countUpdatedId);
});
},
_allocate(actor, box, flags) {
this.parent(actor, box, flags);
vfunc_allocate(box, flags) {
this.parent(box, flags);
let childBox = new Clutter.ActorBox();
let [minWidth, minHeight, naturalWidth, naturalHeight] = this._counterBin.get_preferred_size();
let direction = this.actor.get_text_direction();
let direction = this.get_text_direction();
if (direction == Clutter.TextDirection.LTR) {
// allocate on the right in LTR

View File

@ -77,8 +77,10 @@ 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 this._iconForNotificationData(hints['image-path']);
return null;
},
_fallbackIconForNotificationData(hints) {
@ -658,6 +660,10 @@ var GtkNotificationDaemonAppSource = new Lang.Class({
return new FdoApplicationProxy(Gio.DBus.session, this._appId, this._objectPath, callback);
},
_createNotification(params) {
return new GtkNotificationDaemonNotification(this, params);
},
activateAction(actionId, target) {
this._createApp((app, error) => {
if (error == null)
@ -684,9 +690,9 @@ var GtkNotificationDaemonAppSource = new Lang.Class({
this._notificationPending = true;
if (this._notifications[notificationId])
this._notifications[notificationId].destroy();
this._notifications[notificationId].destroy(MessageTray.NotificationDestroyedReason.REPLACED);
let notification = new GtkNotificationDaemonNotification(this, notificationParams);
let notification = this._createNotification(notificationParams);
notification.connect('destroy', () => {
delete this._notifications[notificationId];
});

View File

@ -226,7 +226,7 @@ var Overview = new Lang.Class({
// Add a clone of the panel to the overview so spacing and such is
// automatic
this._panelGhost = new St.Bin({ child: new Clutter.Clone({ source: Main.panel.actor }),
this._panelGhost = new St.Bin({ child: new Clutter.Clone({ source: Main.panel }),
reactive: false,
opacity: 0 });
this._overview.add_actor(this._panelGhost);

View File

@ -250,7 +250,7 @@ var ThumbnailsSlider = new Lang.Class({
this.actor.request_mode = Clutter.RequestMode.WIDTH_FOR_HEIGHT;
this.actor.reactive = true;
this.actor.track_hover = true;
this.actor.add_actor(this._thumbnailsBox.actor);
this.actor.add_actor(this._thumbnailsBox);
Main.layoutManager.connect('monitors-changed', this._updateSlide.bind(this));
global.workspace_manager.connect('active-workspace-changed',
@ -258,7 +258,7 @@ var ThumbnailsSlider = new Lang.Class({
global.workspace_manager.connect('notify::n-workspaces',
this._updateSlide.bind(this));
this.actor.connect('notify::hover', this._updateSlide.bind(this));
this._thumbnailsBox.actor.bind_property('visible', this.actor, 'visible', GObject.BindingFlags.SYNC_CREATE);
this._thumbnailsBox.bind_property('visible', this.actor, 'visible', GObject.BindingFlags.SYNC_CREATE);
},
_getAlwaysZoomOut() {

View File

@ -86,6 +86,7 @@ function _unpremultiply(color) {
var AppMenuButton = new Lang.Class({
Name: 'AppMenuButton',
Extends: PanelMenu.Button,
Signals: {'changed': {}},
_init(panel) {
this.parent(0.0, null, true);
@ -127,7 +128,7 @@ var AppMenuButton = new Lang.Class({
this._visible = this._gtkSettings.gtk_shell_shows_app_menu &&
!Main.overview.visible;
if (!this._visible)
this.actor.hide();
this.hide();
this._overviewHidingId = Main.overview.connect('hiding', this._sync.bind(this));
this._overviewShowingId = Main.overview.connect('showing', this._sync.bind(this));
this._showsAppMenuId = this._gtkSettings.connect('notify::gtk-shell-shows-app-menu',
@ -149,13 +150,13 @@ var AppMenuButton = new Lang.Class({
this._sync();
},
show() {
fadeIn() {
if (this._visible)
return;
this._visible = true;
this.actor.reactive = true;
this.actor.show();
this.show();
Tweener.removeTweens(this.actor);
Tweener.addTween(this.actor,
{ opacity: 255,
@ -163,7 +164,7 @@ var AppMenuButton = new Lang.Class({
transition: 'easeOutQuad' });
},
hide() {
fadeOut() {
if (!this._visible)
return;
@ -175,7 +176,7 @@ var AppMenuButton = new Lang.Class({
time: Overview.ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete() {
this.actor.hide();
this.hide();
},
onCompleteScope: this });
},
@ -314,9 +315,9 @@ var AppMenuButton = new Lang.Class({
shellShowsAppMenu &&
!Main.overview.visibleTarget);
if (visible)
this.show();
this.fadeIn();
else
this.hide();
this.fadeOut();
let isBusy = (this._targetApp != null &&
(this._targetApp.get_state() == Shell.AppState.STARTING ||
@ -366,7 +367,7 @@ var AppMenuButton = new Lang.Class({
this._menuManager.addMenu(menu);
},
destroy() {
_onDestroy() {
if (this._appStateChangedSignalId > 0) {
let appSys = Shell.AppSystem.get_default();
appSys.disconnect(this._appStateChangedSignalId);
@ -398,8 +399,6 @@ var AppMenuButton = new Lang.Class({
}
});
Signals.addSignalMethods(AppMenuButton.prototype);
var ActivitiesButton = new Lang.Class({
Name: 'ActivitiesButton',
Extends: PanelMenu.Button,
@ -774,12 +773,16 @@ const PANEL_ITEM_IMPLEMENTATIONS = {
var Panel = new Lang.Class({
Name: 'Panel',
Extends: St.Widget,
_init() {
this.actor = new Shell.GenericContainer({ name: 'panel',
reactive: true });
this.actor._delegate = this;
this.actor.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS);
this.parent({ name: 'panel',
reactive: true });
// For compatibility with extensions that still use the
// this.actor field
this.actor = this;
this.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS);
this._sessionStyle = null;
@ -788,36 +791,33 @@ var Panel = new Lang.Class({
this.menuManager = new PopupMenu.PopupMenuManager(this);
this._leftBox = new St.BoxLayout({ name: 'panelLeft' });
this.actor.add_actor(this._leftBox);
this.add_child(this._leftBox);
this._centerBox = new St.BoxLayout({ name: 'panelCenter' });
this.actor.add_actor(this._centerBox);
this.add_child(this._centerBox);
this._rightBox = new St.BoxLayout({ name: 'panelRight' });
this.actor.add_actor(this._rightBox);
this.add_child(this._rightBox);
this._leftCorner = new PanelCorner(St.Side.LEFT);
this.actor.add_actor(this._leftCorner.actor);
this.add_child(this._leftCorner.actor);
this._rightCorner = new PanelCorner(St.Side.RIGHT);
this.actor.add_actor(this._rightCorner.actor);
this.add_child(this._rightCorner.actor);
this.actor.connect('get-preferred-width', this._getPreferredWidth.bind(this));
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));
this.connect('button-press-event', this._onButtonPress.bind(this));
this.connect('touch-event', this._onButtonPress.bind(this));
this.connect('key-press-event', this._onKeyPress.bind(this));
Main.overview.connect('showing', () => {
this.actor.add_style_pseudo_class('overview');
this.add_style_pseudo_class('overview');
this._updateSolidStyle();
});
Main.overview.connect('hiding', () => {
this.actor.remove_style_pseudo_class('overview');
this.remove_style_pseudo_class('overview');
this._updateSolidStyle();
});
Main.layoutManager.panelBox.add(this.actor);
Main.ctrlAltTabManager.addGroup(this.actor, _("Top Bar"), 'focus-top-bar-symbolic',
Main.layoutManager.panelBox.add(this);
Main.ctrlAltTabManager.addGroup(this, _("Top Bar"), 'focus-top-bar-symbolic',
{ sortGroup: CtrlAltTab.SortGroup.TOP });
Main.sessionMode.connect('updated', this._updatePanel.bind(this));
@ -827,7 +827,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.display.connect('workareas-changed', () => { this.actor.queue_relayout(); });
global.display.connect('workareas-changed', () => { this.queue_relayout(); });
this._updatePanel();
},
@ -847,24 +847,18 @@ var Panel = new Lang.Class({
this._updateSolidStyle();
},
_getPreferredWidth(actor, forHeight, alloc) {
vfunc_get_preferred_width(actor, forHeight) {
let primaryMonitor = Main.layoutManager.primaryMonitor;
alloc.min_size = -1;
if (primaryMonitor)
alloc.natural_size = primaryMonitor.width;
else
alloc.natural_size = -1;
return [0, primaryMonitor.width];
return [0, 0];
},
_getPreferredHeight(actor, forWidth, alloc) {
// We don't need to implement this; it's forced by the CSS
alloc.min_size = -1;
alloc.natural_size = -1;
},
vfunc_allocate(box, flags) {
this.parent(box, flags);
_allocate(actor, box, flags) {
let allocWidth = box.x2 - box.x1;
let allocHeight = box.y2 - box.y1;
@ -876,7 +870,7 @@ var Panel = new Lang.Class({
centerWidth = centerNaturalWidth;
// get workspace area and center date entry relative to it
let monitor = Main.layoutManager.findMonitorForActor(actor);
let monitor = Main.layoutManager.findMonitorForActor(this);
let centerOffset = 0;
if (monitor) {
let workArea = Main.layoutManager.getWorkAreaForMonitor(monitor.index);
@ -889,7 +883,7 @@ var Panel = new Lang.Class({
childBox.y1 = 0;
childBox.y2 = allocHeight;
if (this.actor.get_text_direction() == Clutter.TextDirection.RTL) {
if (this.get_text_direction() == Clutter.TextDirection.RTL) {
childBox.x1 = Math.max(allocWidth - Math.min(Math.floor(sideWidth),
leftNaturalWidth),
0);
@ -909,7 +903,7 @@ var Panel = new Lang.Class({
childBox.y1 = 0;
childBox.y2 = allocHeight;
if (this.actor.get_text_direction() == Clutter.TextDirection.RTL) {
if (this.get_text_direction() == Clutter.TextDirection.RTL) {
childBox.x1 = 0;
childBox.x2 = Math.min(Math.floor(sideWidth),
rightNaturalWidth);
@ -1069,7 +1063,7 @@ var Panel = new Lang.Class({
if (this._sessionStyle)
this._addStyleClassName(this._sessionStyle);
if (this.actor.get_text_direction() == Clutter.TextDirection.RTL) {
if (this.get_text_direction() == Clutter.TextDirection.RTL) {
this._leftCorner.setStyleParent(this._rightBox);
this._rightCorner.setStyleParent(this._leftBox);
} else {
@ -1079,7 +1073,7 @@ var Panel = new Lang.Class({
},
_updateSolidStyle() {
if (this.actor.has_style_pseudo_class('overview') || !Main.sessionMode.hasWindows) {
if (this.has_style_pseudo_class('overview') || !Main.sessionMode.hasWindows) {
this._removeStyleClassName('solid');
return;
}
@ -1098,8 +1092,8 @@ var Panel = new Lang.Class({
});
/* Check if at least one window is near enough to the panel */
let [, panelTop] = this.actor.get_transformed_position();
let panelBottom = panelTop + this.actor.get_height();
let [, panelTop] = this.get_transformed_position();
let panelBottom = panelTop + this.get_height();
let scale = St.ThemeContext.get_for_stage(global.stage).scale_factor;
let isNearEnough = windows.some(metaWindow => {
let verticalPosition = metaWindow.get_frame_rect().y;
@ -1165,7 +1159,6 @@ var Panel = new Lang.Class({
let destroyId = indicator.connect('destroy', emitter => {
delete this.statusArea[role];
emitter.disconnect(destroyId);
container.destroy();
});
indicator.connect('menu-set', this._onMenuSet.bind(this));
this._onMenuSet(indicator);
@ -1191,13 +1184,13 @@ var Panel = new Lang.Class({
},
_addStyleClassName(className) {
this.actor.add_style_class_name(className);
this.add_style_class_name(className);
this._rightCorner.actor.add_style_class_name(className);
this._leftCorner.actor.add_style_class_name(className);
},
_removeStyleClassName(className) {
this.actor.remove_style_class_name(className);
this.remove_style_class_name(className);
this._rightCorner.actor.remove_style_class_name(className);
this._leftCorner.actor.remove_style_class_name(className);
},

View File

@ -15,21 +15,23 @@ const PopupMenu = imports.ui.popupMenu;
var ButtonBox = new Lang.Class({
Name: 'ButtonBox',
Extends: St.Widget,
_init(params) {
params = Params.parse(params, { style_class: 'panel-button' }, true);
this.actor = new Shell.GenericContainer(params);
this.actor._delegate = this;
this.parent(params);
this.actor = this;
this._delegate = this;
this.container = new St.Bin({ y_fill: true,
x_fill: true,
child: this.actor });
this.actor.connect('get-preferred-width', this._getPreferredWidth.bind(this));
this.actor.connect('get-preferred-height', this._getPreferredHeight.bind(this));
this.actor.connect('allocate', this._allocate.bind(this));
this.connect('style-changed', this._onStyleChanged.bind(this));
this.connect('destroy', this._onDestroy.bind(this));
this.actor.connect('style-changed', this._onStyleChanged.bind(this));
this._minHPadding = this._natHPadding = 0.0;
},
@ -40,31 +42,34 @@ var ButtonBox = new Lang.Class({
this._natHPadding = themeNode.get_length('-natural-hpadding');
},
_getPreferredWidth(actor, forHeight, alloc) {
let child = actor.get_first_child();
vfunc_get_preferred_width(forHeight) {
let child = this.get_first_child();
let minimumSize, naturalSize;
if (child) {
[alloc.min_size, alloc.natural_size] = child.get_preferred_width(-1);
} else {
alloc.min_size = alloc.natural_size = 0;
}
if (child)
[minimumSize, naturalSize] = child.get_preferred_width(-1);
else
minimumSize = naturalSize = 0;
alloc.min_size += 2 * this._minHPadding;
alloc.natural_size += 2 * this._natHPadding;
minimumSize += 2 * this._minHPadding;
naturalSize += 2 * this._natHPadding;
return [minimumSize, naturalSize];
},
_getPreferredHeight(actor, forWidth, alloc) {
let child = actor.get_first_child();
vfunc_get_preferred_height(forWidth) {
let child = this.get_first_child();
if (child) {
[alloc.min_size, alloc.natural_size] = child.get_preferred_height(-1);
} else {
alloc.min_size = alloc.natural_size = 0;
}
if (child)
return child.get_preferred_height(-1);
return [0, 0];
},
_allocate(actor, box, flags) {
let child = actor.get_first_child();
vfunc_allocate(box, flags) {
this.set_allocation(box, flags);
let child = this.get_first_child();
if (!child)
return;
@ -87,11 +92,17 @@ var ButtonBox = new Lang.Class({
child.allocate(childBox, flags);
},
_onDestroy() {
this.container.child = null;
this.container.destroy();
},
});
var Button = new Lang.Class({
Name: 'PanelMenuButton',
Extends: ButtonBox,
Signals: {'menu-set': {} },
_init(menuAlignment, nameText, dontCreateMenu) {
this.parent({ reactive: true,
@ -100,8 +111,8 @@ var Button = new Lang.Class({
accessible_name: nameText ? nameText : "",
accessible_role: Atk.Role.MENU });
this.actor.connect('event', this._onEvent.bind(this));
this.actor.connect('notify::visible', this._onVisibilityChanged.bind(this));
this.connect('event', this._onEvent.bind(this));
this.connect('notify::visible', this._onVisibilityChanged.bind(this));
if (dontCreateMenu)
this.menu = new PopupMenu.PopupDummyMenu(this.actor);
@ -110,9 +121,9 @@ var Button = new Lang.Class({
},
setSensitive(sensitive) {
this.actor.reactive = sensitive;
this.actor.can_focus = sensitive;
this.actor.track_hover = sensitive;
this.reactive = sensitive;
this.can_focus = sensitive;
this.track_hover = sensitive;
},
setMenu(menu) {
@ -184,17 +195,13 @@ var Button = new Lang.Class({
this.menu.actor.style = ('max-height: %spx;').format(maxHeight);
},
destroy() {
this.actor._delegate = null;
_onDestroy() {
this.parent();
if (this.menu)
this.menu.destroy();
this.actor.destroy();
this.emit('destroy');
}
});
Signals.addSignalMethods(Button.prototype);
/* SystemIndicator:
*

View File

@ -783,7 +783,7 @@ var PopupMenu = new Lang.Class({
{ x_fill: true,
y_fill: true,
x_align: St.Align.START });
this.actor = this._boxPointer.actor;
this.actor = this._boxPointer;
this.actor._delegate = this;
this.actor.style_class = 'popup-menu-boxpointer';
@ -874,7 +874,7 @@ var PopupMenu = new Lang.Class({
this.isOpen = true;
this._boxPointer.setPosition(this.sourceActor, this._arrowAlignment);
this._boxPointer.show(animate);
this._boxPointer.open(animate);
this.actor.raise_top();
@ -886,7 +886,7 @@ var PopupMenu = new Lang.Class({
this._activeMenuItem.setActive(false);
if (this._boxPointer.actor.visible) {
this._boxPointer.hide(animate, () => {
this._boxPointer.close(animate, () => {
this.emit('menu-closed');
});
}

View File

@ -150,7 +150,7 @@ var NotificationsBox = new Lang.Class({
_makeNotificationSource(source, box) {
let sourceActor = new MessageTray.SourceActor(source, SUMMARY_ICON_SIZE);
box.add(sourceActor.actor, { y_fill: true });
box.add(sourceActor, { y_fill: true });
let textBox = new St.BoxLayout({ vertical: true });
box.add(textBox, { y_fill: false, y_align: St.Align.START });
@ -172,7 +172,7 @@ var NotificationsBox = new Lang.Class({
let sourceActor = new MessageTray.SourceActor(source, SUMMARY_ICON_SIZE);
let sourceBin = new St.Bin({ y_align: St.Align.START,
x_align: St.Align.START,
child: sourceActor.actor });
child: sourceActor });
box.add(sourceBin);
let textBox = new St.BoxLayout({ vertical: true });

View File

@ -147,7 +147,7 @@ var GridSearchResult = new Lang.Class({
this.icon = new IconGrid.BaseIcon(this.metaInfo['name'],
{ createIcon: this.metaInfo['createIcon'] });
let content = new St.Bin({ child: this.icon.actor });
let content = new St.Bin({ child: this.icon });
this.actor.set_child(content);
this.actor.label_actor = this.icon.label;
}
@ -363,8 +363,9 @@ var GridSearchResults = new Lang.Class({
this._grid = new IconGrid.IconGrid({ rowLimit: MAX_GRID_SEARCH_RESULTS_ROWS,
xAlign: St.Align.START });
this._bin = new St.Bin({ x_align: St.Align.MIDDLE });
this._bin.set_child(this._grid.actor);
this._bin.set_child(this._grid);
this._resultDisplayBin.set_child(this._bin);
},

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) {
@ -414,7 +417,7 @@ var InputSourceManager = new Lang.Class({
let popup = new InputSourcePopup(this._mruSources, this._keybindingAction, this._keybindingActionBackward);
if (!popup.show(binding.is_reversed(), binding.get_name(), binding.get_mask()))
popup.destroy();
popup.fadeAndDestroy();
},
_keyboardOptionsChanged() {
@ -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)
@ -773,6 +787,44 @@ function getInputSourceManager() {
return _inputSourceManager;
}
var InputSourceIndicatorContainer = new Lang.Class({
Name: 'InputSourceIndicatorContainer',
Extends: St.Widget,
vfunc_get_preferred_width(forHeight) {
// Here, and in vfunc_get_preferred_height, we need to query
// for the height of all children, but we ignore the results
// for those we don't actually display.
return this.get_children().reduce((maxWidth, child) => {
let width = child.get_preferred_width(forHeight);
return [Math.max(maxWidth[0], width[0]),
Math.max(maxWidth[1], width[1])];
}, [0, 0]);
},
vfunc_get_preferred_height(forWidth) {
return this.get_children().reduce((maxHeight, child) => {
let height = child.get_preferred_height(forWidth);
return [Math.max(maxHeight[0], height[0]),
Math.max(maxHeight[1], height[1])];
}, [0, 0]);
},
vfunc_allocate(box, flags) {
this.set_allocation(box, flags);
// translate box to (0, 0)
box.x2 -= box.x1;
box.x1 = 0;
box.y2 -= box.y1;
box.y1 = 0;
this.get_children().forEach(c => {
c.allocate_align_fill(box, 0.5, 0.5, false, false, flags);
});
}
});
var InputSourceIndicator = new Lang.Class({
Name: 'InputSourceIndicator',
Extends: PanelMenu.Button,
@ -783,10 +835,7 @@ var InputSourceIndicator = new Lang.Class({
this._menuItems = {};
this._indicatorLabels = {};
this._container = new Shell.GenericContainer();
this._container.connect('get-preferred-width', this._containerGetPreferredWidth.bind(this));
this._container.connect('get-preferred-height', this._containerGetPreferredHeight.bind(this));
this._container.connect('allocate', this._containerAllocate.bind(this));
this._container = new InputSourceIndicatorContainer();
this._hbox = new St.BoxLayout({ style_class: 'panel-status-menu-box' });
this._hbox.add_child(this._container);
@ -1021,48 +1070,4 @@ var InputSourceIndicator = new Lang.Class({
Util.spawn(['gkbd-keyboard-display', '-l', description]);
},
_containerGetPreferredWidth(container, for_height, alloc) {
// Here, and in _containerGetPreferredHeight, we need to query
// for the height of all children, but we ignore the results
// for those we don't actually display.
let max_min_width = 0, max_natural_width = 0;
for (let i in this._inputSourceManager.inputSources) {
let label = this._indicatorLabels[i];
let [min_width, natural_width] = label.get_preferred_width(for_height);
max_min_width = Math.max(max_min_width, min_width);
max_natural_width = Math.max(max_natural_width, natural_width);
}
alloc.min_size = max_min_width;
alloc.natural_size = max_natural_width;
},
_containerGetPreferredHeight(container, for_width, alloc) {
let max_min_height = 0, max_natural_height = 0;
for (let i in this._inputSourceManager.inputSources) {
let label = this._indicatorLabels[i];
let [min_height, natural_height] = label.get_preferred_height(for_width);
max_min_height = Math.max(max_min_height, min_height);
max_natural_height = Math.max(max_natural_height, natural_height);
}
alloc.min_size = max_min_height;
alloc.natural_size = max_natural_height;
},
_containerAllocate(container, box, flags) {
// translate box to (0, 0)
box.x2 -= box.x1;
box.x1 = 0;
box.y2 -= box.y1;
box.y1 = 0;
for (let i in this._inputSourceManager.inputSources) {
let label = this._indicatorLabels[i];
label.allocate_align_fill(box, 0.5, 0.5, false, false, flags);
}
}
});

View File

@ -2,6 +2,7 @@
const Clutter = imports.gi.Clutter;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
@ -39,23 +40,22 @@ function primaryModifier(mask) {
var SwitcherPopup = new Lang.Class({
Name: 'SwitcherPopup',
Extends: St.Widget,
Abstract: true,
_init(items) {
this.parent({ style_class: 'switcher-popup',
reactive: true,
visible: false });
this._switcherList = null;
this._items = items || [];
this._selectedIndex = 0;
this.actor = new Shell.GenericContainer({ style_class: 'switcher-popup',
reactive: true,
visible: false });
this.actor.connect('get-preferred-width', this._getPreferredWidth.bind(this));
this.actor.connect('get-preferred-height', this._getPreferredHeight.bind(this));
this.actor.connect('allocate', this._allocate.bind(this));
this.actor.connect('destroy', this._onDestroy.bind(this));
this.connect('destroy', this._onDestroy.bind(this));
Main.uiGroup.add_actor(this.actor);
Main.uiGroup.add_actor(this);
this._haveModal = false;
this._modifierMask = 0;
@ -64,42 +64,35 @@ var SwitcherPopup = new Lang.Class({
this._initialDelayTimeoutId = 0;
this._noModsTimeoutId = 0;
this.add_constraint(new Clutter.BindConstraint({
source: global.stage,
coordinate: Clutter.BindCoordinate.ALL,
}));
// Initially disable hover so we ignore the enter-event if
// the switcher appears underneath the current pointer location
this._disableHover();
},
_getPreferredWidth(actor, forHeight, alloc) {
let primary = Main.layoutManager.primaryMonitor;
vfunc_allocate(box, flags) {
this.set_allocation(box, flags);
alloc.min_size = primary.width;
alloc.natural_size = primary.width;
},
_getPreferredHeight(actor, forWidth, alloc) {
let primary = Main.layoutManager.primaryMonitor;
alloc.min_size = primary.height;
alloc.natural_size = primary.height;
},
_allocate(actor, box, flags) {
let childBox = new Clutter.ActorBox();
let primary = Main.layoutManager.primaryMonitor;
let leftPadding = this.actor.get_theme_node().get_padding(St.Side.LEFT);
let rightPadding = this.actor.get_theme_node().get_padding(St.Side.RIGHT);
let leftPadding = this.get_theme_node().get_padding(St.Side.LEFT);
let rightPadding = this.get_theme_node().get_padding(St.Side.RIGHT);
let hPadding = leftPadding + rightPadding;
// Allocate the switcherList
// We select a size based on an icon size that does not overflow the screen
let [childMinHeight, childNaturalHeight] = this._switcherList.actor.get_preferred_height(primary.width - hPadding);
let [childMinWidth, childNaturalWidth] = this._switcherList.actor.get_preferred_width(childNaturalHeight);
let [childMinHeight, childNaturalHeight] = this._switcherList.get_preferred_height(primary.width - hPadding);
let [childMinWidth, childNaturalWidth] = this._switcherList.get_preferred_width(childNaturalHeight);
childBox.x1 = Math.max(primary.x + leftPadding, primary.x + Math.floor((primary.width - childNaturalWidth) / 2));
childBox.x2 = Math.min(primary.x + primary.width - rightPadding, childBox.x1 + childNaturalWidth);
childBox.y1 = primary.y + Math.floor((primary.height - childNaturalHeight) / 2);
childBox.y2 = childBox.y1 + childNaturalHeight;
this._switcherList.actor.allocate(childBox, flags);
this._switcherList.allocate(childBox, flags);
},
_initialSelection(backward, binding) {
@ -115,31 +108,30 @@ var SwitcherPopup = new Lang.Class({
if (this._items.length == 0)
return false;
if (!Main.pushModal(this.actor)) {
if (!Main.pushModal(this)) {
// Probably someone else has a pointer grab, try again with keyboard only
if (!Main.pushModal(this.actor, { options: Meta.ModalOptions.POINTER_ALREADY_GRABBED })) {
if (!Main.pushModal(this, { options: Meta.ModalOptions.POINTER_ALREADY_GRABBED }))
return false;
}
}
this._haveModal = true;
this._modifierMask = primaryModifier(mask);
this.actor.connect('key-press-event', this._keyPressEvent.bind(this));
this.actor.connect('key-release-event', this._keyReleaseEvent.bind(this));
this.connect('key-press-event', this._keyPressEvent.bind(this));
this.connect('key-release-event', this._keyReleaseEvent.bind(this));
this.actor.connect('button-press-event', this._clickedOutside.bind(this));
this.actor.connect('scroll-event', this._scrollEvent.bind(this));
this.connect('button-press-event', this._clickedOutside.bind(this));
this.connect('scroll-event', this._scrollEvent.bind(this));
this.actor.add_actor(this._switcherList.actor);
this.add_actor(this._switcherList);
this._switcherList.connect('item-activated', this._itemActivated.bind(this));
this._switcherList.connect('item-entered', this._itemEntered.bind(this));
this._switcherList.connect('item-removed', this._itemRemoved.bind(this));
// Need to force an allocation so we can figure out whether we
// need to scroll when selecting
this.actor.opacity = 0;
this.actor.show();
this.actor.get_allocation_box();
this.opacity = 0;
this.visible = true;
this.get_allocation_box();
this._initialSelection(backward, binding);
@ -163,7 +155,7 @@ var SwitcherPopup = new Lang.Class({
this._initialDelayTimeoutId = Mainloop.timeout_add(POPUP_DELAY_TIMEOUT,
() => {
Main.osdWindowManager.hideAll();
this.actor.opacity = 255;
this.opacity = 255;
this._initialDelayTimeoutId = 0;
return GLib.SOURCE_REMOVE;
});
@ -195,7 +187,7 @@ var SwitcherPopup = new Lang.Class({
// 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();
this.fadeAndDestroy();
return Clutter.EVENT_STOP;
},
@ -215,7 +207,7 @@ var SwitcherPopup = new Lang.Class({
},
_clickedOutside(actor, event) {
this.destroy();
this.fadeAndDestroy();
return Clutter.EVENT_PROPAGATE;
},
@ -255,7 +247,7 @@ var SwitcherPopup = new Lang.Class({
let newIndex = Math.min(n, this._items.length - 1);
this._select(newIndex);
} else {
this.actor.destroy();
this.fadeAndDestroy();
}
},
@ -293,28 +285,29 @@ var SwitcherPopup = new Lang.Class({
_popModal() {
if (this._haveModal) {
Main.popModal(this.actor);
Main.popModal(this);
this._haveModal = false;
}
},
destroy() {
fadeAndDestroy() {
this._popModal();
if (this.actor.visible) {
Tweener.addTween(this.actor,
if (this.visible) {
Tweener.addTween(this,
{ opacity: 0,
time: POPUP_FADE_OUT_TIME,
transition: 'easeOutQuad',
onComplete: () => {
this.actor.destroy();
this.destroy();
}
});
} else
this.actor.destroy();
} else {
this.destroy();
}
},
_finish(timestamp) {
this.destroy();
this.fadeAndDestroy();
},
_onDestroy() {
@ -334,35 +327,53 @@ var SwitcherPopup = new Lang.Class({
}
});
var SwitcherButton = new Lang.Class({
Name: 'SwitcherButton',
Extends: St.Button,
_init(square) {
this.parent({ style_class: 'item-box',
reactive: true });
this._square = square;
},
vfunc_get_preferred_width(forHeight) {
if (this._square)
return this.get_preferred_height(-1);
else
return this.parent(forHeight);
}
});
var SwitcherList = new Lang.Class({
Name: 'SwitcherList',
Extends: St.Widget,
Signals: { 'item-activated': { param_types: [GObject.TYPE_INT] },
'item-entered': { param_types: [GObject.TYPE_INT] },
'item-removed': { param_types: [GObject.TYPE_INT] } },
_init(squareItems) {
this.actor = new Shell.GenericContainer({ style_class: 'switcher-list' });
this.actor.connect('get-preferred-width', this._getPreferredWidth.bind(this));
this.actor.connect('get-preferred-height', this._getPreferredHeight.bind(this));
this.actor.connect('allocate', this._allocateTop.bind(this));
this.parent({ style_class: 'switcher-list' });
this._list = new St.BoxLayout({ style_class: 'switcher-list-item-container',
vertical: false,
x_expand: true,
y_expand: true });
let layoutManager = this._list.get_layout_manager();
// Here we use a GenericContainer so that we can force all the
// children to have the same width.
this._list = new Shell.GenericContainer({ style_class: 'switcher-list-item-container' });
this._list.spacing = 0;
this._list.connect('style-changed', () => {
this._list.spacing = this._list.get_theme_node().get_length('spacing');
});
this._list.connect('get-preferred-width', this._getPreferredWidth.bind(this));
this._list.connect('get-preferred-height', this._getPreferredHeight.bind(this));
this._list.connect('allocate', this._allocate.bind(this));
this._scrollView = new St.ScrollView({ style_class: 'hfade',
enable_mouse_scrolling: false });
this._scrollView.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.NEVER);
let scrollBox = new St.BoxLayout();
scrollBox.add_actor(this._list);
this._scrollView.add_actor(scrollBox);
this.actor.add_actor(this._scrollView);
this._scrollView.add_actor(this._list);
this.add_actor(this._scrollView);
// Those arrows indicate whether scrolling in one direction is possible
this._leftArrow = new St.DrawingArea({ style_class: 'switcher-arrow',
@ -376,50 +387,20 @@ var SwitcherList = new Lang.Class({
drawArrow(this._rightArrow, St.Side.RIGHT);
});
this.actor.add_actor(this._leftArrow);
this.actor.add_actor(this._rightArrow);
this.add_actor(this._leftArrow);
this.add_actor(this._rightArrow);
this._items = [];
this._highlighted = -1;
this._squareItems = squareItems;
this._minSize = 0;
this._scrollableRight = true;
this._scrollableLeft = false;
},
_allocateTop(actor, box, flags) {
let leftPadding = this.actor.get_theme_node().get_padding(St.Side.LEFT);
let rightPadding = this.actor.get_theme_node().get_padding(St.Side.RIGHT);
let childBox = new Clutter.ActorBox();
let scrollable = this._minSize > box.x2 - box.x1;
box.y1 -= this.actor.get_theme_node().get_padding(St.Side.TOP);
box.y2 += this.actor.get_theme_node().get_padding(St.Side.BOTTOM);
this._scrollView.allocate(box, flags);
let arrowWidth = Math.floor(leftPadding / 3);
let arrowHeight = arrowWidth * 2;
childBox.x1 = leftPadding / 2;
childBox.y1 = this.actor.height / 2 - arrowWidth;
childBox.x2 = childBox.x1 + arrowWidth;
childBox.y2 = childBox.y1 + arrowHeight;
this._leftArrow.allocate(childBox, flags);
this._leftArrow.opacity = (this._scrollableLeft && scrollable) ? 255 : 0;
arrowWidth = Math.floor(rightPadding / 3);
arrowHeight = arrowWidth * 2;
childBox.x1 = this.actor.width - arrowWidth - rightPadding / 2;
childBox.y1 = this.actor.height / 2 - arrowWidth;
childBox.x2 = childBox.x1 + arrowWidth;
childBox.y2 = childBox.y1 + arrowHeight;
this._rightArrow.allocate(childBox, flags);
this._rightArrow.opacity = (this._scrollableRight && scrollable) ? 255 : 0;
layoutManager.homogeneous = squareItems;
},
addItem(item, label) {
let bbox = new St.Button({ style_class: 'item-box',
reactive: true });
let bbox = new SwitcherButton(this._squareItems);
bbox.set_child(item);
this._list.add_actor(bbox);
@ -472,8 +453,8 @@ var SwitcherList = new Lang.Class({
let adjustment = this._scrollView.hscroll.adjustment;
let [value, lower, upper, stepIncrement, pageIncrement, pageSize] = adjustment.get_values();
let [absItemX, absItemY] = this._items[index].get_transformed_position();
let [result, posX, posY] = this.actor.transform_stage_point(absItemX, 0);
let [containerWidth, containerHeight] = this.actor.get_transformed_size();
let [result, posX, posY] = this.transform_stage_point(absItemX, 0);
let [containerWidth, containerHeight] = this.get_transformed_size();
if (posX + this._items[index].get_width() > containerWidth)
this._scrollToRight();
else if (this._items[index].allocation.x1 - value < 0)
@ -500,7 +481,7 @@ var SwitcherList = new Lang.Class({
onComplete: () => {
if (this._highlighted == 0)
this._scrollableLeft = false;
this.actor.queue_relayout();
this.queue_relayout();
}
});
},
@ -524,7 +505,7 @@ var SwitcherList = new Lang.Class({
onComplete: () => {
if (this._highlighted == this._items.length - 1)
this._scrollableRight = false;
this.actor.queue_relayout();
this.queue_relayout();
}
});
},
@ -556,16 +537,15 @@ var SwitcherList = new Lang.Class({
return [maxChildMin, maxChildNat];
},
_getPreferredWidth(actor, forHeight, alloc) {
let [maxChildMin, maxChildNat] = this._maxChildWidth(forHeight);
vfunc_get_preferred_width(forHeight) {
let themeNode = this.get_theme_node();
let [maxChildMin, ] = this._maxChildWidth(forHeight);
let [minListWidth, ] = this._list.get_preferred_width(forHeight);
let totalSpacing = Math.max(this._list.spacing * (this._items.length - 1), 0);
alloc.min_size = this._items.length * maxChildMin + totalSpacing;
alloc.natural_size = alloc.min_size;
this._minSize = alloc.min_size;
return themeNode.adjust_preferred_width(maxChildMin, minListWidth);
},
_getPreferredHeight(actor, forWidth, alloc) {
vfunc_get_preferred_height(forWidth) {
let maxChildMin = 0;
let maxChildNat = 0;
@ -581,44 +561,46 @@ var SwitcherList = new Lang.Class({
maxChildNat = maxChildMin;
}
alloc.min_size = maxChildMin;
alloc.natural_size = maxChildNat;
let themeNode = this.get_theme_node();
return themeNode.adjust_preferred_height(maxChildMin, maxChildNat);
},
_allocate(actor, box, flags) {
let childHeight = box.y2 - box.y1;
vfunc_allocate(box, flags) {
this.set_allocation(box, flags);
let [maxChildMin, maxChildNat] = this._maxChildWidth(childHeight);
let totalSpacing = Math.max(this._list.spacing * (this._items.length - 1), 0);
let contentBox = this.get_theme_node().get_content_box(box);
let width = contentBox.x2 - contentBox.x1;
let height = contentBox.y2 - contentBox.y1;
let childWidth = Math.floor(Math.max(0, box.x2 - box.x1 - totalSpacing) / this._items.length);
let leftPadding = this.get_theme_node().get_padding(St.Side.LEFT);
let rightPadding = this.get_theme_node().get_padding(St.Side.RIGHT);
let [, natScrollViewWidth] = this._scrollView.get_preferred_width(height);
let x = 0;
let children = this._list.get_children();
let childBox = new Clutter.ActorBox();
let scrollable = natScrollViewWidth > width;
let primary = Main.layoutManager.primaryMonitor;
let parentRightPadding = this.actor.get_parent().get_theme_node().get_padding(St.Side.RIGHT);
this._scrollView.allocate(contentBox, flags);
for (let i = 0; i < children.length; i++) {
if (this._items.indexOf(children[i]) != -1) {
let [childMin, childNat] = children[i].get_preferred_height(childWidth);
let vSpacing = (childHeight - childNat) / 2;
childBox.x1 = x;
childBox.y1 = vSpacing;
childBox.x2 = x + childWidth;
childBox.y2 = childBox.y1 + childNat;
children[i].allocate(childBox, flags);
let arrowWidth = Math.floor(leftPadding / 3);
let arrowHeight = arrowWidth * 2;
childBox.x1 = leftPadding / 2;
childBox.y1 = this.height / 2 - arrowWidth;
childBox.x2 = childBox.x1 + arrowWidth;
childBox.y2 = childBox.y1 + arrowHeight;
this._leftArrow.allocate(childBox, flags);
this._leftArrow.opacity = (this._scrollableLeft && scrollable) ? 255 : 0;
x += this._list.spacing + childWidth;
} else {
// Something else, eg, AppSwitcher's arrows;
// we don't allocate it.
}
}
arrowWidth = Math.floor(rightPadding / 3);
arrowHeight = arrowWidth * 2;
childBox.x1 = this.width - arrowWidth - rightPadding / 2;
childBox.y1 = this.height / 2 - arrowWidth;
childBox.x2 = childBox.x1 + arrowWidth;
childBox.y2 = childBox.y1 + arrowHeight;
this._rightArrow.allocate(childBox, flags);
this._rightArrow.opacity = (this._scrollableRight && scrollable) ? 255 : 0;
}
});
Signals.addSignalMethods(SwitcherList.prototype);
function drawArrow(area, side) {
let themeNode = area.get_theme_node();

View File

@ -478,7 +478,6 @@ var TouchpadWorkspaceSwitchAction = new Lang.Class({
this._dx = 0;
this._dy = 0;
actor.connect('captured-event', this._handleEvent.bind(this));
this._touchpadSettings = new Gio.Settings({schema_id: 'org.gnome.desktop.peripherals.touchpad'});
},
_checkActivated() {
@ -516,11 +515,7 @@ var TouchpadWorkspaceSwitchAction = new Lang.Class({
// Scale deltas up a bit to make it feel snappier
this._dx += dx * 2;
if(!(this._touchpadSettings.get_boolean('natural-scroll')))
this._dy -= dy * 2;
else
this._dy += dy * 2;
this._dy += dy * 2;
this.emit('motion', this._dx, this._dy);
} else {
if ((event.get_gesture_phase() == Clutter.TouchpadGesturePhase.END && ! this._checkActivated()) ||
@ -1801,11 +1796,11 @@ var WindowManager = new Lang.Class({
if (direction == Meta.MotionDirection.UP ||
direction == Meta.MotionDirection.UP_LEFT ||
direction == Meta.MotionDirection.UP_RIGHT)
yDest = -global.screen_height + Main.panel.actor.height;
yDest = -global.screen_height + Main.panel.height;
else if (direction == Meta.MotionDirection.DOWN ||
direction == Meta.MotionDirection.DOWN_LEFT ||
direction == Meta.MotionDirection.DOWN_RIGHT)
yDest = global.screen_height - Main.panel.actor.height;
yDest = global.screen_height - Main.panel.height;
if (direction == Meta.MotionDirection.LEFT ||
direction == Meta.MotionDirection.UP_LEFT ||

View File

@ -465,8 +465,6 @@ var WindowOverlay = new Lang.Class({
title.clutter_text.ellipsize = Pango.EllipsizeMode.END;
windowClone.actor.label_actor = title;
this._maxTitleWidth = -1;
this._updateCaptionId = metaWindow.connect('notify::title', w => {
this.title.text = w.title;
this.title.text = this._getCaption();
@ -530,13 +528,6 @@ var WindowOverlay = new Lang.Class({
Math.max(this.borderSize, this.closeButton.width - this.closeButton._overlap)];
},
setMaxChromeWidth(max) {
if (this._maxTitleWidth == max)
return;
this._maxTitleWidth = max;
},
relayout(animate) {
let button = this.closeButton;
let title = this.title;
@ -563,26 +554,13 @@ var WindowOverlay = new Lang.Class({
else
button.set_position(Math.floor(buttonX), Math.floor(buttonY));
// Clutter.Actor.get_preferred_width() will return the fixed width if
// one is set, so we need to reset the width by calling set_width(-1),
// to forward the call down to StLabel.
// We also need to save and restore the current width, otherwise the
// animation starts from the wrong point.
let prevTitleWidth = title.width;
title.set_width(-1);
let [titleMinWidth, titleNatWidth] = title.get_preferred_width(-1);
let titleWidth = Math.max(titleMinWidth,
Math.min(titleNatWidth, this._maxTitleWidth));
title.width = prevTitleWidth;
let titleX = cloneX + (cloneWidth - titleWidth) / 2;
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), titleWidth);
this._animateOverlayActor(title, Math.floor(titleX), Math.floor(titleY), title.width);
} else {
title.width = titleWidth;
title.width = title.width;
title.set_position(Math.floor(titleX), Math.floor(titleY));
}
@ -1328,12 +1306,6 @@ var Workspace = new Lang.Class({
let cloneHeight = clone.actor.height * scale;
clone.slot = [x, y, cloneWidth, cloneHeight];
let cloneCenter = x + cloneWidth / 2;
let maxChromeWidth = 2 * Math.min(
cloneCenter - area.x,
area.x + area.width - cloneCenter);
overlay.setMaxChromeWidth(Math.round(maxChromeWidth));
if (overlay && (initialPositioning || !clone.positioned))
overlay.hide();

View File

@ -15,59 +15,33 @@ const Tweener = imports.ui.tweener;
var ANIMATION_TIME = 0.1;
var DISPLAY_TIMEOUT = 600;
var WorkspaceSwitcherPopup = new Lang.Class({
Name: 'WorkspaceSwitcherPopup',
var WorkspaceSwitcherPopupList = new Lang.Class({
Name: 'WorkspaceSwitcherPopupList',
Extends: St.Widget,
_init() {
this.actor = new St.Widget({ x: 0,
y: 0,
width: global.screen_width,
height: global.screen_height,
style_class: 'workspace-switcher-group' });
Main.uiGroup.add_actor(this.actor);
this.parent({ style_class: 'workspace-switcher' });
this._container = new St.BoxLayout({ style_class: 'workspace-switcher-container' });
this._list = new Shell.GenericContainer({ style_class: 'workspace-switcher' });
this._itemSpacing = 0;
this._childHeight = 0;
this._childWidth = 0;
this._timeoutId = 0;
this._list.connect('style-changed', () => {
this._itemSpacing = this._list.get_theme_node().get_length('spacing');
this.connect('style-changed', () => {
this._itemSpacing = this.get_theme_node().get_length('spacing');
});
this._list.connect('get-preferred-width', this._getPreferredWidth.bind(this));
this._list.connect('get-preferred-height', this._getPreferredHeight.bind(this));
this._list.connect('allocate', this._allocate.bind(this));
this._container.add(this._list);
this.actor.add_actor(this._container);
this._redisplay();
this.actor.hide();
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) {
let children = this._list.get_children();
vfunc_get_preferred_height(forWidth) {
let workArea = Main.layoutManager.getWorkAreaForMonitor(Main.layoutManager.primaryIndex);
let themeNode = this.get_theme_node();
let availHeight = workArea.height;
availHeight -= this.actor.get_theme_node().get_vertical_padding();
availHeight -= this._container.get_theme_node().get_vertical_padding();
availHeight -= this._list.get_theme_node().get_vertical_padding();
availHeight -= themeNode.get_vertical_padding();
let height = 0;
for (let i = 0; i < children.length; i++) {
let [childMinHeight, childNaturalHeight] = children[i].get_preferred_height(-1);
let [childMinWidth, childNaturalWidth] = children[i].get_preferred_width(childNaturalHeight);
for (let child of this.get_children()) {
let [childMinHeight, childNaturalHeight] = child.get_preferred_height(-1);
let [childMinWidth, childNaturalWidth] = child.get_preferred_width(childNaturalHeight);
height += childNaturalHeight * workArea.width / workArea.height;
}
@ -78,34 +52,74 @@ var WorkspaceSwitcherPopup = new Lang.Class({
this._childHeight = (height - spacing) / workspaceManager.n_workspaces;
alloc.min_size = height;
alloc.natural_size = height;
return themeNode.adjust_preferred_height(height, height);
},
_getPreferredWidth(actor, forHeight, alloc) {
vfunc_get_preferred_width(forHeight) {
let workArea = Main.layoutManager.getWorkAreaForMonitor(Main.layoutManager.primaryIndex);
this._childWidth = Math.round(this._childHeight * workArea.width / workArea.height);
alloc.min_size = this._childWidth;
alloc.natural_size = this._childWidth;
return [this._childWidth, this._childWidth];
},
_allocate(actor, box, flags) {
let children = this._list.get_children();
vfunc_allocate(box, flags) {
this.set_allocation(box, flags);
let themeNode = this.get_theme_node();
box = themeNode.get_content_box(box);
let childBox = new Clutter.ActorBox();
let y = box.y1;
let prevChildBoxY2 = box.y1 - this._itemSpacing;
for (let i = 0; i < children.length; i++) {
for (let child of this.get_children()) {
childBox.x1 = box.x1;
childBox.x2 = box.x1 + this._childWidth;
childBox.y1 = prevChildBoxY2 + this._itemSpacing;
childBox.y2 = Math.round(y + this._childHeight);
y += this._childHeight + this._itemSpacing;
prevChildBoxY2 = childBox.y2;
children[i].allocate(childBox, flags);
child.allocate(childBox, flags);
}
},
});
var WorkspaceSwitcherPopup = new Lang.Class({
Name: 'WorkspaceSwitcherPopup',
Extends: St.Widget,
_init() {
this.parent({ x: 0,
y: 0,
width: global.screen_width,
height: global.screen_height,
style_class: 'workspace-switcher-group' });
this.actor = this;
Main.uiGroup.add_actor(this);
this._timeoutId = 0;
this._container = new St.BoxLayout({ style_class: 'workspace-switcher-container' });
this.add_child(this._container);
this._list = new WorkspaceSwitcherPopupList();
this._container.add_child(this._list);
this._redisplay();
this.hide();
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)));
this.connect('destroy', this._onDestroy.bind(this));
},
_redisplay() {
let workspaceManager = global.workspace_manager;
@ -165,7 +179,7 @@ var WorkspaceSwitcherPopup = new Lang.Class({
return GLib.SOURCE_REMOVE;
},
destroy() {
_onDestroy() {
if (this._timeoutId)
Mainloop.source_remove(this._timeoutId);
this._timeoutId = 0;
@ -174,9 +188,6 @@ var WorkspaceSwitcherPopup = new Lang.Class({
for (let i = 0; i < this._workspaceManagerSignals.length; i++)
workspaceManager.disconnect(this._workspaceManagerSignals[i]);
this.actor.destroy();
this.emit('destroy');
this._workspaceManagerSignals = [];
}
});
Signals.addSignalMethods(WorkspaceSwitcherPopup.prototype);

View File

@ -615,14 +615,14 @@ Signals.addSignalMethods(WorkspaceThumbnail.prototype);
var ThumbnailsBox = new Lang.Class({
Name: 'ThumbnailsBox',
Extends: St.Widget,
_init() {
this.actor = new Shell.GenericContainer({ reactive: true,
style_class: 'workspace-thumbnails',
request_mode: Clutter.RequestMode.WIDTH_FOR_HEIGHT });
this.actor.connect('get-preferred-width', this._getPreferredWidth.bind(this));
this.actor.connect('get-preferred-height', this._getPreferredHeight.bind(this));
this.actor.connect('allocate', this._allocate.bind(this));
this.parent({ reactive: true,
style_class: 'workspace-thumbnails',
request_mode: Clutter.RequestMode.WIDTH_FOR_HEIGHT });
this.actor = this;
this.actor._delegate = this;
let indicator = new St.Bin({ style_class: 'workspace-thumbnail-indicator' });
@ -631,12 +631,12 @@ var ThumbnailsBox = new Lang.Class({
Shell.util_set_hidden_from_pick(indicator, true);
this._indicator = indicator;
this.actor.add_actor(indicator);
this.add_actor(indicator);
this._dropWorkspace = -1;
this._dropPlaceholderPos = -1;
this._dropPlaceholder = new St.Bin({ style_class: 'placeholder' });
this.actor.add_actor(this._dropPlaceholder);
this.add_actor(this._dropPlaceholder);
this._spliceIndex = -1;
this._targetScale = 0;
@ -652,9 +652,9 @@ var ThumbnailsBox = new Lang.Class({
this._thumbnails = [];
this.actor.connect('button-press-event', () => Clutter.EVENT_STOP);
this.actor.connect('button-release-event', this._onButtonRelease.bind(this));
this.actor.connect('touch-event', this._onTouchEvent.bind(this));
this.connect('button-press-event', () => Clutter.EVENT_STOP);
this.connect('button-release-event', this._onButtonRelease.bind(this));
this.connect('touch-event', this._onTouchEvent.bind(this));
Main.overview.connect('showing',
this._createThumbnails.bind(this));
@ -693,13 +693,13 @@ var ThumbnailsBox = new Lang.Class({
_updateSwitcherVisibility() {
let workspaceManager = global.workspace_manager;
this.actor.visible =
this.visible =
this._settings.get_boolean('dynamic-workspaces') ||
workspaceManager.n_workspaces > 1;
},
_activateThumbnailAtPoint(stageX, stageY, time) {
let [r, x, y] = this.actor.transform_stage_point(stageX, stageY);
let [r, x, y] = this.transform_stage_point(stageX, stageY);
for (let i = 0; i < this._thumbnails.length; i++) {
let thumbnail = this._thumbnails[i]
@ -753,7 +753,7 @@ var ThumbnailsBox = new Lang.Class({
},
_onDragMotion(dragEvent) {
if (!this.actor.contains(dragEvent.targetActor))
if (!this.contains(dragEvent.targetActor))
this._onLeave();
return DND.DragMotionResult.CONTINUE;
},
@ -767,7 +767,7 @@ var ThumbnailsBox = new Lang.Class({
return;
this._dropPlaceholderPos = -1;
this.actor.queue_relayout();
this.queue_relayout();
},
// Draggable target interface
@ -776,7 +776,7 @@ var ThumbnailsBox = new Lang.Class({
return DND.DragMotionResult.CONTINUE;
let canCreateWorkspaces = Meta.prefs_get_dynamic_workspaces();
let spacing = this.actor.get_theme_node().get_length('spacing');
let spacing = this.get_theme_node().get_length('spacing');
this._dropWorkspace = -1;
let placeholderPos = -1;
@ -814,7 +814,7 @@ var ThumbnailsBox = new Lang.Class({
if (this._dropPlaceholderPos != placeholderPos) {
this._dropPlaceholderPos = placeholderPos;
this.actor.queue_relayout();
this.queue_relayout();
}
if (this._dropWorkspace != -1)
@ -962,7 +962,7 @@ var ThumbnailsBox = new Lang.Class({
thumbnail.setPorthole(this._porthole.x, this._porthole.y,
this._porthole.width, this._porthole.height);
this._thumbnails.push(thumbnail);
this.actor.add_actor(thumbnail.actor);
this.add_actor(thumbnail.actor);
if (start > 0 && this._spliceIndex == -1) {
// not the initial fill, and not splicing via DND
@ -1011,7 +1011,7 @@ var ThumbnailsBox = new Lang.Class({
set scale(scale) {
this._scale = scale;
this.actor.queue_relayout();
this.queue_relayout();
},
get scale() {
@ -1020,7 +1020,7 @@ var ThumbnailsBox = new Lang.Class({
set indicatorY(indicatorY) {
this._indicatorY = indicatorY;
this.actor.queue_relayout();
this.queue_relayout();
},
get indicatorY() {
@ -1080,7 +1080,6 @@ var ThumbnailsBox = new Lang.Class({
// Once that's complete, we can start scaling to the new size and collapse any removed thumbnails
this._iterateStateThumbnails(ThumbnailState.ANIMATED_OUT, thumbnail => {
this.actor.set_skip_paint(thumbnail.actor, true);
this._setThumbnailState(thumbnail, ThumbnailState.COLLAPSING);
Tweener.addTween(thumbnail,
{ collapseFraction: 1,
@ -1132,39 +1131,36 @@ var ThumbnailsBox = new Lang.Class({
this._stateUpdateQueued = true;
},
_getPreferredHeight(actor, forWidth, alloc) {
vfunc_get_preferred_height(forWidth) {
// Note that for getPreferredWidth/Height we cheat a bit and skip propagating
// the size request to our children because we know how big they are and know
// that the actors aren't depending on the virtual functions being called.
if (!this._ensurePorthole()) {
alloc.min_size = -1;
alloc.natural_size = -1;
return;
}
if (!this._ensurePorthole())
return [0, 0];
let workspaceManager = global.workspace_manager;
let themeNode = this.actor.get_theme_node();
let themeNode = this.get_theme_node();
let spacing = themeNode.get_length('spacing');
let nWorkspaces = workspaceManager.n_workspaces;
let totalSpacing = (nWorkspaces - 1) * spacing;
alloc.min_size = totalSpacing;
alloc.natural_size = totalSpacing + nWorkspaces * this._porthole.height * MAX_THUMBNAIL_SCALE;
let naturalHeight = totalSpacing + nWorkspaces * this._porthole.height * MAX_THUMBNAIL_SCALE;
return themeNode.adjust_preferred_height(totalSpacing, naturalHeight);
},
_getPreferredWidth(actor, forHeight, alloc) {
if (!this._ensurePorthole()) {
alloc.min_size = -1;
alloc.natural_size = -1;
return;
}
vfunc_get_preferred_width(forHeight) {
if (!this._ensurePorthole())
return [0, 0];
let workspaceManager = global.workspace_manager;
let themeNode = this.actor.get_theme_node();
let themeNode = this.get_theme_node();
let spacing = this.actor.get_theme_node().get_length('spacing');
forHeight = themeNode.adjust_for_height(forHeight);
let spacing = themeNode.get_length('spacing');
let nWorkspaces = workspaceManager.n_workspaces;
let totalSpacing = (nWorkspaces - 1) * spacing;
@ -1174,8 +1170,8 @@ var ThumbnailsBox = new Lang.Class({
scale = Math.min(scale, MAX_THUMBNAIL_SCALE);
let width = Math.round(this._porthole.width * scale);
alloc.min_size = width;
alloc.natural_size = width;
return themeNode.adjust_preferred_width(width, width);
},
// The "porthole" is the portion of the screen that we show in the
@ -1190,14 +1186,18 @@ var ThumbnailsBox = new Lang.Class({
return true;
},
_allocate(actor, box, flags) {
vfunc_allocate(box, flags) {
this.set_allocation(box, flags);
let rtl = (Clutter.get_default_text_direction () == Clutter.TextDirection.RTL);
if (this._thumbnails.length == 0) // not visible
return;
let workspaceManager = global.workspace_manager;
let themeNode = this.actor.get_theme_node();
let themeNode = this.get_theme_node();
box = themeNode.get_content_box(box);
let portholeWidth = this._porthole.width;
let portholeHeight = this._porthole.height;

View File

@ -1,5 +1,5 @@
project('gnome-shell', 'c',
version: '3.30.2',
version: '3.30.1',
meson_version: '>= 0.47.0',
license: 'GPLv2+'
)

921
po/hr.po

File diff suppressed because it is too large Load Diff

936
po/it.po

File diff suppressed because it is too large Load Diff

940
po/lv.po

File diff suppressed because it is too large Load Diff

View File

@ -8,7 +8,7 @@ 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-10-10 19:07+0000\n"
"POT-Creation-Date: 2018-10-08 12:48+0000\n"
"PO-Revision-Date: 2018-09-16 08:42+0200\n"
"Last-Translator: Dušan Kazik <prescott66@gmail.com>\n"
"Language-Team: Slovak <gnome-sk-list@gnome.org>\n"
@ -686,12 +686,12 @@ msgstr "Pridať do obľúbených"
msgid "Show Details"
msgstr "Zobraziť podrobnosti"
#: js/ui/appFavorites.js:140
#: js/ui/appFavorites.js:141
#, javascript-format
msgid "%s has been added to your favorites."
msgstr "Aplikácia %s bola pridaná medzi obľúbené."
#: js/ui/appFavorites.js:174
#: js/ui/appFavorites.js:175
#, javascript-format
msgid "%s has been removed from your favorites."
msgstr "Aplikácia %s bola odstránená z obľúbených."
@ -855,12 +855,12 @@ msgid "Clear All"
msgstr "Vymazať všetko"
#. Translators: %s is an application name
#: js/ui/closeDialog.js:50
#: js/ui/closeDialog.js:47
#, javascript-format
msgid "“%s” is not responding."
msgstr "Aplikácia „%s“ neodpovedá."
#: js/ui/closeDialog.js:51
#: 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."
@ -868,19 +868,19 @@ msgstr ""
"Môžete chvíľu počkať na pokračovanie aplikácie, alebo vynútiť úplné "
"ukončenie aplikácie."
#: js/ui/closeDialog.js:67
#: js/ui/closeDialog.js:64
msgid "Force Quit"
msgstr "Vynútiť ukončenie"
#: js/ui/closeDialog.js:70
#: js/ui/closeDialog.js:67
msgid "Wait"
msgstr "Počkať"
#: js/ui/components/automountManager.js:91
#: js/ui/components/automountManager.js:90
msgid "External drive connected"
msgstr "Externá jednotka bola pripojená"
#: js/ui/components/automountManager.js:102
#: js/ui/components/automountManager.js:101
msgid "External drive disconnected"
msgstr "Externá jednotka bola odpojená"

606
po/sl.po

File diff suppressed because it is too large Load Diff

View File

@ -108,7 +108,6 @@ libshell_public_headers = [
'shell-app-system.h',
'shell-app-usage.h',
'shell-embedded-window.h',
'shell-generic-container.h',
'shell-glsl-quad.h',
'shell-gtk-embed.h',
'shell-global.h',
@ -144,7 +143,6 @@ libshell_sources = [
'shell-app-usage.c',
'shell-embedded-window.c',
'shell-embedded-window-private.h',
'shell-generic-container.c',
'shell-global.c',
'shell-glsl-quad.c',
'shell-gtk-embed.c',

View File

@ -1,433 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/**
* SECTION:shell-generic-container
* @short_description: A container class with signals for allocation
*
* #ShellGenericContainer is mainly a workaround for the current
* lack of GObject subclassing + vfunc overrides in gjs. We
* implement the container interface, but proxy the virtual functions
* into signals, which gjs can catch.
*
* #ShellGenericContainer is an #StWidget, and automatically takes its
* borders and padding into account during size request and allocation.
*/
#include "config.h"
#include "shell-generic-container.h"
#include <clutter/clutter.h>
#include <gtk/gtk.h>
#include <girepository.h>
static void shell_generic_container_iface_init (ClutterContainerIface *iface);
typedef struct _ShellGenericContainerPrivate ShellGenericContainerPrivate;
struct _ShellGenericContainer
{
StWidget parent;
ShellGenericContainerPrivate *priv;
};
struct _ShellGenericContainerPrivate {
GHashTable *skip_paint;
};
G_DEFINE_TYPE_WITH_CODE(ShellGenericContainer,
shell_generic_container,
ST_TYPE_WIDGET,
G_ADD_PRIVATE (ShellGenericContainer)
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTAINER,
shell_generic_container_iface_init));
/* Signals */
enum
{
GET_PREFERRED_WIDTH,
GET_PREFERRED_HEIGHT,
ALLOCATE,
LAST_SIGNAL
};
static guint shell_generic_container_signals [LAST_SIGNAL] = { 0 };
static gpointer
shell_generic_container_allocation_ref (ShellGenericContainerAllocation *alloc)
{
alloc->_refcount++;
return alloc;
}
static void
shell_generic_container_allocation_unref (ShellGenericContainerAllocation *alloc)
{
if (--alloc->_refcount == 0)
g_slice_free (ShellGenericContainerAllocation, alloc);
}
static void
shell_generic_container_allocate (ClutterActor *self,
const ClutterActorBox *box,
ClutterAllocationFlags flags)
{
StThemeNode *theme_node;
ClutterActorBox content_box;
clutter_actor_set_allocation (self, box, flags);
theme_node = st_widget_get_theme_node (ST_WIDGET (self));
st_theme_node_get_content_box (theme_node, box, &content_box);
g_signal_emit (G_OBJECT (self), shell_generic_container_signals[ALLOCATE], 0,
&content_box, flags);
}
static void
shell_generic_container_get_preferred_width (ClutterActor *actor,
gfloat for_height,
gfloat *min_width_p,
gfloat *natural_width_p)
{
ShellGenericContainerAllocation *alloc = g_slice_new0 (ShellGenericContainerAllocation);
StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor));
st_theme_node_adjust_for_height (theme_node, &for_height);
alloc->_refcount = 1;
g_signal_emit (G_OBJECT (actor), shell_generic_container_signals[GET_PREFERRED_WIDTH], 0,
for_height, alloc);
if (min_width_p)
*min_width_p = alloc->min_size;
if (natural_width_p)
*natural_width_p = alloc->natural_size;
shell_generic_container_allocation_unref (alloc);
st_theme_node_adjust_preferred_width (theme_node, min_width_p, natural_width_p);
}
static void
shell_generic_container_get_preferred_height (ClutterActor *actor,
gfloat for_width,
gfloat *min_height_p,
gfloat *natural_height_p)
{
ShellGenericContainerAllocation *alloc = g_slice_new0 (ShellGenericContainerAllocation);
StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor));
st_theme_node_adjust_for_width (theme_node, &for_width);
alloc->_refcount = 1;
g_signal_emit (G_OBJECT (actor), shell_generic_container_signals[GET_PREFERRED_HEIGHT], 0,
for_width, alloc);
if (min_height_p)
*min_height_p = alloc->min_size;
if (natural_height_p)
*natural_height_p = alloc->natural_size;
shell_generic_container_allocation_unref (alloc);
st_theme_node_adjust_preferred_height (theme_node, min_height_p, natural_height_p);
}
static void
shell_generic_container_paint (ClutterActor *actor)
{
ShellGenericContainer *self = (ShellGenericContainer*) actor;
ClutterActor *child;
st_widget_paint_background (ST_WIDGET (actor));
for (child = clutter_actor_get_first_child (actor);
child != NULL;
child = clutter_actor_get_next_sibling (child))
{
if (g_hash_table_lookup (self->priv->skip_paint, child))
continue;
clutter_actor_paint (child);
}
}
static void
shell_generic_container_pick (ClutterActor *actor,
const ClutterColor *color)
{
ShellGenericContainer *self = (ShellGenericContainer*) actor;
ClutterActor *child;
CLUTTER_ACTOR_CLASS (shell_generic_container_parent_class)->pick (actor, color);
for (child = clutter_actor_get_first_child (actor);
child != NULL;
child = clutter_actor_get_next_sibling (child))
{
if (g_hash_table_lookup (self->priv->skip_paint, child))
continue;
clutter_actor_paint (child);
}
}
static GList *
shell_generic_container_get_focus_chain (StWidget *widget)
{
ShellGenericContainer *self = SHELL_GENERIC_CONTAINER (widget);
ClutterActor *child;
GList *focus_chain;
focus_chain = NULL;
for (child = clutter_actor_get_first_child (CLUTTER_ACTOR (self));
child != NULL;
child = clutter_actor_get_next_sibling (child))
{
if (clutter_actor_is_visible (child) &&
!shell_generic_container_get_skip_paint (self, child))
focus_chain = g_list_prepend (focus_chain, child);
}
return g_list_reverse (focus_chain);
}
/**
* shell_generic_container_get_n_skip_paint:
* @self: A #ShellGenericContainer
*
* Returns: Number of children which will not be painted.
*/
guint
shell_generic_container_get_n_skip_paint (ShellGenericContainer *self)
{
return g_hash_table_size (self->priv->skip_paint);
}
/**
* shell_generic_container_get_skip_paint:
* @self: A #ShellGenericContainer
* @child: Child #ClutterActor
*
* Gets whether or not @actor is skipped when painting.
*
* Return value: %TRUE or %FALSE
*/
gboolean
shell_generic_container_get_skip_paint (ShellGenericContainer *self,
ClutterActor *child)
{
return g_hash_table_lookup (self->priv->skip_paint, child) != NULL;
}
/**
* shell_generic_container_set_skip_paint:
* @self: A #ShellGenericContainer
* @child: Child #ClutterActor
* @skip: %TRUE if we should skip painting
*
* Set whether or not we should skip painting @actor. Workaround for
* lack of gjs ability to override _paint vfunc.
*/
void
shell_generic_container_set_skip_paint (ShellGenericContainer *self,
ClutterActor *child,
gboolean skip)
{
gboolean currently_skipping;
currently_skipping = g_hash_table_lookup (self->priv->skip_paint, child) != NULL;
if ((!!skip) == currently_skipping)
return;
if (!skip)
g_hash_table_remove (self->priv->skip_paint, child);
else
g_hash_table_insert (self->priv->skip_paint, child, child);
clutter_actor_queue_redraw (CLUTTER_ACTOR (self));
}
static gboolean
shell_generic_container_get_paint_volume (ClutterActor *self,
ClutterPaintVolume *volume)
{
ClutterActorBox paint_box, alloc_box;
StThemeNode *theme_node;
ClutterVertex origin;
/* Setting the paint volume does not make sense when we don't have any allocation */
if (!clutter_actor_has_allocation (self))
return FALSE;
theme_node = st_widget_get_theme_node (ST_WIDGET (self));
clutter_actor_get_allocation_box (self, &alloc_box);
st_theme_node_get_paint_box (theme_node, &alloc_box, &paint_box);
origin.x = paint_box.x1 - alloc_box.x1;
origin.y = paint_box.y1 - alloc_box.y1;
origin.z = 0.0f;
clutter_paint_volume_set_origin (volume, &origin);
clutter_paint_volume_set_width (volume, paint_box.x2 - paint_box.x1);
clutter_paint_volume_set_height (volume, paint_box.y2 - paint_box.y1);
if (!clutter_actor_get_clip_to_allocation (self))
{
ClutterActor *child;
/* Based on ClutterGroup/ClutterBox; include the children's
* paint volumes, since they may paint outside our allocation.
*/
for (child = clutter_actor_get_first_child (self);
child != NULL;
child = clutter_actor_get_next_sibling (child))
{
const ClutterPaintVolume *child_volume;
if (!clutter_actor_is_visible (child))
continue;
if (shell_generic_container_get_skip_paint (SHELL_GENERIC_CONTAINER (self), child))
continue;
child_volume = clutter_actor_get_transformed_paint_volume (child, self);
if (!child_volume)
return FALSE;
clutter_paint_volume_union (volume, child_volume);
}
}
return TRUE;
}
static void
shell_generic_container_finalize (GObject *object)
{
ShellGenericContainer *self = (ShellGenericContainer*) object;
g_hash_table_destroy (self->priv->skip_paint);
G_OBJECT_CLASS (shell_generic_container_parent_class)->finalize (object);
}
static void
shell_generic_container_class_init (ShellGenericContainerClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
StWidgetClass *widget_class = ST_WIDGET_CLASS (klass);
gobject_class->finalize = shell_generic_container_finalize;
actor_class->get_preferred_width = shell_generic_container_get_preferred_width;
actor_class->get_preferred_height = shell_generic_container_get_preferred_height;
actor_class->allocate = shell_generic_container_allocate;
actor_class->paint = shell_generic_container_paint;
actor_class->pick = shell_generic_container_pick;
actor_class->get_paint_volume = shell_generic_container_get_paint_volume;
widget_class->get_focus_chain = shell_generic_container_get_focus_chain;
/**
* ShellGenericContainer::get-preferred-width:
* @self: the #ShellGenericContainer
* @for_height: as in clutter_actor_get_preferred_width()
* @alloc: a #ShellGenericContainerAllocation to be filled in
*
* Emitted when clutter_actor_get_preferred_width() is called
* on @self. You should fill in the fields of @alloc with the
* your minimum and natural widths. #ShellGenericContainer
* will deal with taking its borders and padding into account
* for you.
*
* @alloc's fields are initialized to 0, so unless you have a fixed
* width specified (via #ClutterActor:width or CSS), you must
* connect to this signal and fill in the values.
*/
shell_generic_container_signals[GET_PREFERRED_WIDTH] =
g_signal_new ("get-preferred-width",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL, NULL,
G_TYPE_NONE, 2, G_TYPE_FLOAT, SHELL_TYPE_GENERIC_CONTAINER_ALLOCATION);
/**
* ShellGenericContainer::get-preferred-height:
* @self: the #ShellGenericContainer
* @for_width: as in clutter_actor_get_preferred_height()
* @alloc: a #ShellGenericContainerAllocation to be filled in
*
* Emitted when clutter_actor_get_preferred_height() is called
* on @self. You should fill in the fields of @alloc with the
* your minimum and natural heights. #ShellGenericContainer
* will deal with taking its borders and padding into account
* for you.
*
* @alloc's fields are initialized to 0, so unless you have a fixed
* height specified (via #ClutterActor:height or CSS), you must
* connect to this signal and fill in the values.
*/
shell_generic_container_signals[GET_PREFERRED_HEIGHT] =
g_signal_new ("get-preferred-height",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL, NULL,
G_TYPE_NONE, 2, G_TYPE_FLOAT, SHELL_TYPE_GENERIC_CONTAINER_ALLOCATION);
/**
* ShellGenericContainer::allocate:
* @self: the #ShellGenericContainer
* @box: @self's content box
* @flags: the allocation flags.
*
* Emitted when @self is allocated, after chaining up to the parent
* allocate method.
*
* Note that @box is @self's content box (qv
* st_theme_node_get_content_box()), NOT its allocation.
*/
shell_generic_container_signals[ALLOCATE] =
g_signal_new ("allocate",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL, NULL,
G_TYPE_NONE, 2, CLUTTER_TYPE_ACTOR_BOX, CLUTTER_TYPE_ALLOCATION_FLAGS);
}
static void
shell_generic_container_actor_removed (ClutterContainer *container,
ClutterActor *actor)
{
ShellGenericContainerPrivate *priv = SHELL_GENERIC_CONTAINER (container)->priv;
g_hash_table_remove (priv->skip_paint, actor);
}
static void
shell_generic_container_iface_init (ClutterContainerIface *iface)
{
iface->actor_removed = shell_generic_container_actor_removed;
}
static void
shell_generic_container_init (ShellGenericContainer *area)
{
area->priv = shell_generic_container_get_instance_private (area);
area->priv->skip_paint = g_hash_table_new (NULL, NULL);
}
GType
shell_generic_container_allocation_get_type (void)
{
static GType gtype = G_TYPE_INVALID;
if (gtype == G_TYPE_INVALID)
{
gtype = g_boxed_type_register_static ("ShellGenericContainerAllocation",
(GBoxedCopyFunc)shell_generic_container_allocation_ref,
(GBoxedFreeFunc)shell_generic_container_allocation_unref);
}
return gtype;
}

View File

@ -1,30 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
#ifndef __SHELL_GENERIC_CONTAINER_H__
#define __SHELL_GENERIC_CONTAINER_H__
#include "st.h"
#define SHELL_TYPE_GENERIC_CONTAINER (shell_generic_container_get_type ())
G_DECLARE_FINAL_TYPE (ShellGenericContainer, shell_generic_container,
SHELL, GENERIC_CONTAINER, StWidget)
typedef struct {
float min_size;
float natural_size;
/* <private> */
guint _refcount;
} ShellGenericContainerAllocation;
#define SHELL_TYPE_GENERIC_CONTAINER_ALLOCATION (shell_generic_container_allocation_get_type ())
GType shell_generic_container_allocation_get_type (void);
guint shell_generic_container_get_n_skip_paint (ShellGenericContainer *self);
gboolean shell_generic_container_get_skip_paint (ShellGenericContainer *self,
ClutterActor *child);
void shell_generic_container_set_skip_paint (ShellGenericContainer *self,
ClutterActor *child,
gboolean skip);
#endif /* __SHELL_GENERIC_CONTAINER_H__ */

View File

@ -10,8 +10,6 @@
#include <pwd.h>
#define POLKIT_AGENT_I_KNOW_API_IS_SUBJECT_TO_CHANGE
#include <polkitagent/polkitagent.h>
#include "shell-polkit-authentication-agent.h"
#include <glib/gi18n.h>
@ -49,12 +47,6 @@ print_debug (const gchar *str, ...)
}
#endif
struct _ShellPolkitAuthenticationAgentClass
{
PolkitAgentListenerClass parent_class;
};
struct _AuthRequest;
typedef struct _AuthRequest AuthRequest;
@ -326,8 +318,11 @@ shell_polkit_authentication_agent_unregister (ShellPolkitAuthenticationAgent *ag
if (agent->current_request != NULL)
auth_request_dismiss (agent->current_request);
polkit_agent_listener_unregister (agent->handle);
agent->handle = NULL;
if (agent->handle)
{
polkit_agent_listener_unregister (agent->handle);
agent->handle = NULL;
}
}
static void maybe_process_next_request (ShellPolkitAuthenticationAgent *agent);

View File

@ -6,25 +6,23 @@
* Author: David Zeuthen <davidz@redhat.com>
*/
#ifndef __SHELL_POLKIT_AUTHENTICATION_AGENT_H__
#define __SHELL_POLKIT_AUTHENTICATION_AGENT_H__
#pragma once
#define POLKIT_AGENT_I_KNOW_API_IS_SUBJECT_TO_CHANGE
#include <polkitagent/polkitagent.h>
#include <glib-object.h>
G_BEGIN_DECLS
typedef struct _ShellPolkitAuthenticationAgent ShellPolkitAuthenticationAgent;
typedef struct _ShellPolkitAuthenticationAgentClass ShellPolkitAuthenticationAgentClass;
/* Polkit doesn't have g_autoptr support, thus we have to manually set the autoptr function here */
G_DEFINE_AUTOPTR_CLEANUP_FUNC (PolkitAgentListener, g_object_unref)
#define SHELL_TYPE_POLKIT_AUTHENTICATION_AGENT (shell_polkit_authentication_agent_get_type ())
#define SHELL_POLKIT_AUTHENTICATION_AGENT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), SHELL_TYPE_POLKIT_AUTHENTICATION_AGENT, ShellPolkitAuthenticationAgent))
#define SHELL_POLKIT_AUTHENTICATION_AGENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SHELL_TYPE_POLKIT_AUTHENTICATION_AGENT, ShellPolkitAuthenticationAgentClass))
#define SHELL_IS_POLKIT_AUTHENTICATION_AGENT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), SHELL_TYPE_POLKIT_AUTHENTICATION_AGENT))
#define SHELL_IS_POLKIT_AUTHENTICATION_AGENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SHELL_TYPE_POLKIT_AUTHENTICATION_AGENT))
#define SHELL_POLKIT_AUTHENTICATION_AGENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SHELL_TYPE_POLKIT_AUTHENTICATION_AGENT, ShellPolkitAuthenticationAgentClass))
#define SHELL_TYPE_POLKIT_AUTHENTICATION_AGENT (shell_polkit_authentication_agent_get_type())
G_DECLARE_FINAL_TYPE (ShellPolkitAuthenticationAgent, shell_polkit_authentication_agent, SHELL, POLKIT_AUTHENTICATION_AGENT, PolkitAgentListener)
ShellPolkitAuthenticationAgent *shell_polkit_authentication_agent_new (void);
GType shell_polkit_authentication_agent_get_type (void) G_GNUC_CONST;
ShellPolkitAuthenticationAgent *shell_polkit_authentication_agent_new (void);
void shell_polkit_authentication_agent_complete (ShellPolkitAuthenticationAgent *agent,
gboolean dismissed);
void shell_polkit_authentication_agent_register (ShellPolkitAuthenticationAgent *agent,
@ -33,4 +31,3 @@ void shell_polkit_authentication_agent_unregister (Sh
G_END_DECLS
#endif /* __SHELL_POLKIT_AUTHENTICATION_AGENT_H__ */

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

@ -282,13 +282,12 @@ st_box_layout_allocate (ClutterActor *actor,
StBoxLayoutPrivate *priv = ST_BOX_LAYOUT (actor)->priv;
StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor));
ClutterLayoutManager *layout = clutter_actor_get_layout_manager (actor);
ClutterActorBox viewport_content_box;
ClutterActorBox content_box;
gfloat avail_width, avail_height, min_width, natural_width, min_height, natural_height;
CLUTTER_ACTOR_CLASS (st_box_layout_parent_class)->allocate (actor, box, flags);
st_theme_node_get_content_box (theme_node, box, &content_box);
clutter_actor_box_get_size (&content_box, &avail_width, &avail_height);
st_theme_node_get_content_box (theme_node, box, &viewport_content_box);
clutter_actor_box_get_size (&viewport_content_box, &avail_width, &avail_height);
clutter_layout_manager_get_preferred_width (layout, CLUTTER_CONTAINER (actor),
avail_height,
@ -297,6 +296,18 @@ st_box_layout_allocate (ClutterActor *actor,
MAX (avail_width, min_width),
&min_height, &natural_height);
/* Because StBoxLayout implements StScrollable, the allocation box passed here
* may not match the minimum sizes reported by the layout manager. When that
* happens, the content box needs to be adjusted to match the reported minimum
* sizes before being passed to clutter_layout_manager_allocate() */
clutter_actor_set_allocation (actor, box, flags);
content_box = viewport_content_box;
content_box.x2 += MAX (0, min_width - avail_width);
content_box.y2 += MAX (0, min_height - avail_height);
clutter_layout_manager_allocate (layout, CLUTTER_CONTAINER (actor),
&content_box, flags);
/* update adjustments for scrolling */
if (priv->vadjustment)

View File

@ -455,14 +455,13 @@ _st_create_shadow_pipeline_from_actor (StShadow *shadow_spec,
CoglTexture *buffer;
CoglOffscreen *offscreen;
CoglFramebuffer *fb;
CoglContext *ctx;
CoglColor clear_color;
CoglError *catch_error = NULL;
float x, y;
buffer = cogl_texture_new_with_size (width,
height,
COGL_TEXTURE_NO_SLICING,
COGL_PIXEL_FORMAT_ANY);
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
buffer = cogl_texture_2d_new_with_size (ctx, width, height);
if (buffer == NULL)
return NULL;

View File

@ -66,10 +66,10 @@ st_scroll_view_fade_create_texture (ClutterOffscreenEffect *effect,
gfloat min_width,
gfloat min_height)
{
return cogl_texture_new_with_size (min_width,
min_height,
COGL_TEXTURE_NO_SLICING,
COGL_PIXEL_FORMAT_RGBA_8888_PRE);
CoglContext *ctx =
clutter_backend_get_cogl_context (clutter_get_default_backend ());
return cogl_texture_2d_new_with_size (ctx, min_width, min_height);
}
static char *

View File

@ -2220,12 +2220,15 @@ static void
st_theme_node_prerender_shadow (StThemeNodePaintState *state)
{
StThemeNode *node = state->node;
CoglContext *ctx;
guint border_radius[4];
int max_borders[4];
int center_radius, corner_id;
CoglHandle buffer, offscreen = COGL_INVALID_HANDLE;
CoglError *error = NULL;
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
/* Get infos from the node */
if (state->alloc_width < node->box_shadow_min_width ||
state->alloc_height < node->box_shadow_min_height)
@ -2261,10 +2264,9 @@ st_theme_node_prerender_shadow (StThemeNodePaintState *state)
}
/* Render offscreen */
buffer = cogl_texture_new_with_size (state->box_shadow_width,
state->box_shadow_height,
COGL_TEXTURE_NO_SLICING,
COGL_PIXEL_FORMAT_ANY);
buffer = cogl_texture_2d_new_with_size (ctx,
state->box_shadow_width,
state->box_shadow_height);
if (buffer == NULL)
return;

View File

@ -240,12 +240,14 @@ setup_framebuffers (StThemeNodeTransition *transition,
const ClutterActorBox *allocation)
{
StThemeNodeTransitionPrivate *priv = transition->priv;
CoglContext *ctx;
guint width, height;
CoglError *catch_error = NULL;
/* template material to avoid unnecessary shader compilation */
static CoglHandle material_template = COGL_INVALID_HANDLE;
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
width = priv->offscreen_box.x2 - priv->offscreen_box.x1;
height = priv->offscreen_box.y2 - priv->offscreen_box.y1;
@ -254,15 +256,11 @@ setup_framebuffers (StThemeNodeTransition *transition,
if (priv->old_texture)
cogl_handle_unref (priv->old_texture);
priv->old_texture = cogl_texture_new_with_size (width, height,
COGL_TEXTURE_NO_SLICING,
COGL_PIXEL_FORMAT_ANY);
priv->old_texture = cogl_texture_2d_new_with_size (ctx, width, height);
if (priv->new_texture)
cogl_handle_unref (priv->new_texture);
priv->new_texture = cogl_texture_new_with_size (width, height,
COGL_TEXTURE_NO_SLICING,
COGL_PIXEL_FORMAT_ANY);
priv->new_texture = cogl_texture_2d_new_with_size (ctx, width, height);
if (priv->old_texture == COGL_INVALID_HANDLE)
return FALSE;

View File

@ -32,26 +32,22 @@ const BOX_WIDTHS = [
const SPACING = 10;
function FlowedBoxes() {
this._init();
}
var FlowedBoxes = new Lang.Class({
Name: 'FlowedBoxes',
Extends: St.Widget,
FlowedBoxes.prototype = {
_init() {
this.actor = new Shell.GenericContainer();
this.actor.connect('get-preferred-width', this._getPreferredWidth.bind(this));
this.actor.connect('get-preferred-height', this._getPreferredHeight.bind(this));
this.actor.connect('allocate', this._allocate.bind(this));
this.parent();
for (let i = 0; i < BOX_WIDTHS.length; i++) {
let child = new St.Bin({ width: BOX_WIDTHS[i], height: BOX_HEIGHT,
style: 'border: 1px solid #444444; background: #00aa44' })
this.actor.add_actor(child);
this.add_actor(child);
}
},
_getPreferredWidth(actor, forHeight, alloc) {
let children = this.actor.get_children();
vfunc_get_preferred_width(forHeight) {
let children = this.get_children();
let maxMinWidth = 0;
let totalNaturalWidth = 0;
@ -65,12 +61,11 @@ FlowedBoxes.prototype = {
totalNaturalWidth += naturalWidth;
}
alloc.min_size = maxMinWidth;
alloc.natural_size = totalNaturalWidth;
return [maxMinWidth, totalNaturalWidth];
},
_layoutChildren(forWidth, callback) {
let children = this.actor.get_children();
let children = this.get_children();
let x = 0;
let y = 0;
@ -99,24 +94,26 @@ FlowedBoxes.prototype = {
},
_getPreferredHeight(actor, forWidth, alloc) {
vfunc_get_preferred_height(forWidth) {
let height = 0;
this._layoutChildren(forWidth,
function(child, x1, y1, x2, y2) {
height = Math.max(height, y2);
});
alloc.min_size = alloc.natural_size = height;
return [height, height];
},
_allocate(actor, box, flags) {
vfunc_allocate(box, flags) {
this.set_allocation(box, flags);
this._layoutChildren(box.x2 - box.x1,
function(child, x1, y1, x2, y2) {
child.allocate(new Clutter.ActorBox({ x1: x1, y1: y1, x2: x2, y2: y2 }),
flags);
});
}
};
});
/****************************************************************************/
@ -127,39 +124,34 @@ FlowedBoxes.prototype = {
//
// This is currently only written for the case where the child is height-for-width
function SizingIllustrator() {
this._init();
}
var SizingIllustrator = new Lang.Class({
Name: 'SizingIllustrator',
Extends: St.Widget,
SizingIllustrator.prototype = {
_init() {
this.actor = new Shell.GenericContainer();
this.actor.connect('get-preferred-width', this._getPreferredWidth.bind(this));
this.actor.connect('get-preferred-height', this._getPreferredHeight.bind(this));
this.actor.connect('allocate', this._allocate.bind(this));
this.parent();
this.minWidthLine = new St.Bin({ style: 'background: red' });
this.actor.add_actor(this.minWidthLine);
this.add_actor(this.minWidthLine);
this.minHeightLine = new St.Bin({ style: 'background: red' });
this.actor.add_actor(this.minHeightLine);
this.add_actor(this.minHeightLine);
this.naturalWidthLine = new St.Bin({ style: 'background: #4444ff' });
this.actor.add_actor(this.naturalWidthLine);
this.add_actor(this.naturalWidthLine);
this.naturalHeightLine = new St.Bin({ style: 'background: #4444ff' });
this.actor.add_actor(this.naturalHeightLine);
this.add_actor(this.naturalHeightLine);
this.currentWidthLine = new St.Bin({ style: 'background: #aaaaaa' });
this.actor.add_actor(this.currentWidthLine);
this.add_actor(this.currentWidthLine);
this.currentHeightLine = new St.Bin({ style: 'background: #aaaaaa' });
this.actor.add_actor(this.currentHeightLine);
this.add_actor(this.currentHeightLine);
this.handle = new St.Bin({ style: 'background: yellow; border: 1px solid black;',
reactive: true });
this.handle.connect('button-press-event', this._handlePressed.bind(this));
this.handle.connect('button-release-event', this._handleReleased.bind(this));
this.handle.connect('motion-event', this._handleMotion.bind(this));
this.actor.add_actor(this.handle);
this.add_actor(this.handle);
this._inDrag = false;
@ -168,13 +160,13 @@ SizingIllustrator.prototype = {
},
add(child) {
this.child = child;
this.actor.add_actor(this.child);
this.child.lower_bottom();
this.child = child;
this.add_child(child);
this.child.lower_bottom();
},
_getPreferredWidth(actor, forHeight, alloc) {
let children = this.actor.get_children();
vfunc_get_preferred_width(forHeight) {
let children = this.get_children();
for (let i = 0; i < children.length; i++) {
let child = children[i];
let [minWidth, naturalWidth] = child.get_preferred_width(-1);
@ -184,27 +176,28 @@ SizingIllustrator.prototype = {
}
}
alloc.min_size = 0;
alloc.natural_size = 400;
return [0, 400];
},
_getPreferredHeight(actor, forWidth, alloc) {
let children = this.actor.get_children();
vfunc_get_preferred_height(forWidth) {
let children = this.get_children();
for (let i = 0; i < children.length; i++) {
let child = children[i];
if (child == this.child) {
[this.minHeight, this.naturalHeight] = child.get_preferred_height(this.width);
} else {
let [minWidth, naturalWidth] = child.get_preferred_width(-1);
child.get_preferred_height(naturalWidth);
let [minWidth, naturalWidth] = child.get_preferred_height(naturalWidth);
}
}
alloc.min_size = 0;
alloc.natural_size = 400;
return [0, 400];
},
_allocate(actor, box, flags) {
vfunc_allocate(box, flags) {
this.set_allocation(box, flags);
box = this.get_theme_node().get_content_box(box);
let allocWidth = box.x2 - box.x1;
let allocHeight = box.y2 - box.y1;
@ -244,13 +237,13 @@ SizingIllustrator.prototype = {
_handleMotion(handle, event) {
if (this._inDrag) {
let [x, y] = event.get_coords();
let [actorX, actorY] = this.actor.get_transformed_position();
let [actorX, actorY] = this.get_transformed_position();
this.width = x - this._dragX - actorX;
this.height = y - this._dragY - actorY;
this.actor.queue_relayout();
this.queue_relayout();
}
}
};
});
/****************************************************************************/
@ -278,7 +271,7 @@ function test() {
mainBox.add(bin, { x_fill: true, y_fill: true, expand: true });
let illustrator = new SizingIllustrator();
bin.add_actor(illustrator.actor);
bin.add_actor(illustrator);
let scrollView = new St.ScrollView();
illustrator.add(scrollView);
@ -287,7 +280,7 @@ function test() {
scrollView.add_actor(box);
let flowedBoxes = new FlowedBoxes();
box.add(flowedBoxes.actor, { expand: false, x_fill: true, y_fill: true });
box.add(flowedBoxes, { expand: false, x_fill: true, y_fill: true });
let policyBox = new St.BoxLayout({ vertical: false });
mainBox.add(policyBox);