Compare commits

...

386 Commits

Author SHA1 Message Date
6393e90a5a theme: sync OSD colors with gtk 2019-04-16 16:47:59 +02:00
4e5ca6d376 dash: Fix messed up icon height
When determining the biggest icon size that fits the available height,
we first subtract the additional space requirements of icons (spacing,
padding, running indicator etc.) and then divide the result by the
number of icons to get the maximum size available to each icon texture.

In the above, the additional space requirement of each icon is taken
from the first icon (as all icons are assumed to be the same), and
calculated as the difference between the icon button's preferred height
and the currently used icon size.

To make sure that the icon is actually using the dash's current icon
size (even while animating to a new icon size), we enforce its height
during the size request and restore its original height afterwards.

However after some recent changes, that step is causing troubles:
For some reason, the original height may be 0, and when we restore it,
we end up forcing a fixed non-height that bypasses the regular size
request machinery.

While it is unclear where exactly the zero height comes from (maybe
waiting for a valid resource scale?), it is clear that it's best
to avoid forcing a fixed height. So instead of making the icon
texture comply with the assumed icon size, adjust the calculations
to use its current height request.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1053
2019-04-13 14:17:07 +00:00
2fab75f448 dateMenu: Make clock offsets relative to local time
We recently added offsets to world clocks that represent the location's
timezone as UTC offset. However for most users, that representation is
overly technical and less helpful than the difference to their local time.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1157
2019-04-13 12:11:14 +00:00
22883f2fa2 dateMenu: Make sure we always display a clock name
We currently use the city name for all location except named timezones.
However locations only have a city name if they are of level CITY or
DETACHED, or if they are of level WEATHER_STATION with a parent of level
CITY.

So when libgweather commit d7682676ac9 moved weather station locations from
cities to countries, it broke their names in the world clocks section.

To fix this, stop making assumptions about when we can use the city name
and simply try it first for all locations and fall back to the plain name
if its not available.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1150
2019-04-12 03:17:35 +02:00
5d9f80bc73 extensionPrefs: Fix pref button appearance
After the Adwaita refresh, the button shows up oval rather than
circular. To address this, make sure that the "image-button" class
is applied as well by using the dedicated setter function.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/482
2019-04-12 00:51:44 +02:00
f7d117488b appFavorites: Update RENAMED_DESKTOP_IDS
Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1160
2019-04-11 23:28:49 +02:00
244a329ee7 boxpointer: Compute source allocation and work area just once
Compute the source actor workarea and allocation when repositioning and keep it
cached so that we've not to calculating it again in _calculateArrowSide.

Since _calculateArrowSide only is called inside _updateFlip that is always
called just after reposition, we can be sure that the computed values are still
correct.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/435
2019-04-11 19:38:17 +00:00
044572cb60 boxpointer: Use X/Y actor positioning instead of an anchor point
Currently all the widgets using BoxPointer and so popup actors are always drawn
at screen origin and then shifted at paint time in the proper position.

This doesn't work when using resource scale, since the widgets need to know
in which monitor they currently are in order to use properly scaled resources.

So, basically revert commit 22c22e0d7 and go back using the actual actor
coordinates for positioning and the actor translation for animating it, as the
relayouting issues of the past seem to be gone now.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1008
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/435
2019-04-11 19:38:17 +00:00
746875258d layout: Use an invisible but mapped actor as dummy cursor
Since this could be used as boxpointer source, it should be marked as mapped,
or it will be ignored.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/435
2019-04-11 19:38:17 +00:00
4892a87dfe boxpointer: Compute arrowStride using sourceActor monitor as reference
I suppose this was also the goal of commit 96e14dc, but because it was checking
the value of the always-undefined this.sourceActor, it really never worked as
expected.

So, now since we assume that this._sourceActor is always defined just use it
as reference to compute the monitor menu position.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1029
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/435
2019-04-11 19:38:17 +00:00
8b9c8ddb1e windowManager: Don't move sticky windows when inserting workspace
Inserting a workspace is implemented by appending a new workspace, then
shifting all windows after the "new" workspace up. This has an unintended
side effect on sticky windows, as changing its workspace will unstick it.

Fix this by excluding sticky windows - there's little point in moving them
anyway, given that they should be on all workspaces (including the original
workspace and the target one).

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1151
2019-04-11 19:00:52 +00:00
eb9000576c shellDBus: Accept connector to restrict OSD to one monitor
The monitor index is not something that gnome-shell and
gnome-settings-daemon seem to be agreeing about. Using the connector
string is a much more reliable method of identifying a specific screen
and we are indeed using this already for monitor labling.

So switch over to use the connector rather than the monitor index. If a
user tries to use the old API, then the OSD will simply show up on all
monitors (which is the status quo currently anyway).

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/489
2019-04-11 18:53:53 +00:00
862aaf341e shellDBus: Remove ShowMonitorLabels API
This API has been broken for quite some time now as the corresponding
mutter function meta_monitor_manager_get_monitor_for_output was removed.
If anyone tries to use it, we would just run into a backtrace.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/490
2019-04-11 17:49:40 +00:00
a5c75ff58b screenshot: Don't pick up rubberband style from GTK
Selecting a screen area for a screenshot isn't the same as selecting
items in an icon view, so there's no strong rationale for picking
up the style from GTK. We stopped doing that for other elements like
tile previews long ago, so just use our own style here too.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/481
2019-04-11 17:27:50 +00:00
4541fb9819 perf: Stop using GTK
Instead of going through GtkSettings, we can just as well use the
underlying GSettings directly.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/481
2019-04-11 17:27:50 +00:00
9f8edd980c panel: Remove left-over Gtk.Settings
It has been unused since commit c334aa2a4c.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/481
2019-04-11 17:27:50 +00:00
e5b9043435 workspacesView: Support touch/touchpad gestures to switch workspaces
Now that the existing touch/touchpad gestures in windowManager only
handle normal mode, add corresponding gestures for the overview and
hook them up to the existing workspace scroll animations.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/516
2019-04-11 17:00:17 +00:00
c0012c2ea4 windowManager: Limit switch gestures to normal mode
The window group is hidden while in overview, so the stick-to-content
animation isn't visible either. Worse, the gestures messes up the
position of window actors in that case. Just limit the gesture to
normal mode for now, we will soon add it back in the overview with
its own animation handling.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/516
2019-04-11 17:00:17 +00:00
b77e4975f0 switchGestures: Do not hard-code allowed modes
The touch/touchpad gestures to switch workspace currently hard-code
the modes in which we want the gestures to work. While these modes
are correct, the existing switch animation only works in NORMAL mode,
not in the overview where the window group is hidden. The easiest way
to address this is to handle both cases completely separately, namely
use separate actions in- and outside the overview.

Make the existing usable in that way by making the list of allowed
modes a constructor parameter.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/516
2019-04-11 17:00:17 +00:00
e83f2344f6 windowManager: Allow disabling touchpad workspace switch action
Just like actual ClutterActions, it can make sense to temporarily
disable the touchpad action, so add an appropriate property.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/516
2019-04-11 17:00:17 +00:00
de6512be1a st: Add missing include
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/485
2019-04-08 18:17:46 +02:00
0b72ff1896 st: Add missing END_DECLS marker
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/485
2019-04-08 18:17:33 +02:00
fea0192772 weather: Handle missing permission store
Our weather integration is supposed to follow GNOME Weather's settings,
including its permission to use location services. However there's a
discrepancy in case xdg-desktop-portal is unavailable:

While our geoclue agent grants all applications access to location
services in that case, the weather integration treats it as if
access was denied.

Fix this by handling this case explicitly.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1130
2019-04-03 13:27:42 +00:00
f81ac498fb ci: Use custom image for commit log check
We can speed up the check a little bit by using an image that
already contains git, so do that.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/480
2019-04-03 13:50:35 +02:00
5357e0a18c st/settings: Add magnifier activation property and bind to settings
The same code for reading the current magnifier state is repeated in both
shell-recorder, shell-screenshot and magnifier itself.
So to move this inside a property of st-settings so that we can refer to it
all over the places removing duplications.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/473
2019-04-02 20:28:54 +00:00
d7632bbd3d Ignore '.vscode' folder for users of that editor
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/476
2019-04-02 17:37:31 +00:00
1b5e91e4b3 shell: Fallback on ISO 8601 datetime string for screenshot date info
If the locale doesn't honor strftime()'s %c argument, we would end up
feeding NULLs into GdkPixbuf tagging. Fallback to a sensible (although
not nicely localized) datetime string.

Closes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/1017
2019-04-02 00:25:39 +00:00
727195c767 magnifier: Use actor scaling filters on content texture node
Reuse the same filter values of the attached actor, instead of hardcoding the
defaults.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/454
2019-04-01 16:34:44 -04:00
9158f55360 magnifier: Track cursor sprite changes only when active
There's no point in keeping the cursor sprite texture around all the time,
and to listen for its changes, we just need this when the magnifier is active.

So, initialize the magnifier texture and monitor for the sprite changes on
activation, while disconnect from the signal and nullify the texture when
the magnifier is deactivated.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/443
2019-04-01 16:34:44 -04:00
8146e9d527 magnifier: Invalidate content size when it changes
In case the content size changes we need to invalidate its size in order to
trigger a full actor relayout.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/443
2019-04-01 16:34:44 -04:00
4247251020 magnifier: Use all color channels to paint content texture node
In order to paint all the color channels of the content texture we need to
set the color channels to 255, so instead of doing this manually we can just
reuse the static color definition for white.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1020
2019-04-01 22:13:50 +02:00
7eee0e0ed6 magnifier: Return all parameters on sprite content preferred size
ClutterContent's get_preferred_size should return a boolean weather the
preferred size is valid, so in javascript we've to return this state value
before out width and height.

Since this was not happening, clutter was considering the width as the state
(converting the non-zero value to true), the height as the width, while ignoring
the returned height (that was then defaulted to 0)

Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1020
2019-04-01 22:13:50 +02:00
4f0851ca77 Update Slovak translation 2019-04-01 15:09:41 +00:00
911ae49767 Updated Spanish translation 2019-04-01 10:29:36 +02:00
5af81d4057 Update Esperanto translation 2019-04-01 06:04:01 +00:00
c435889baa Update Chinese (Taiwan) translation 2019-03-31 15:34:17 +00:00
49f79d9d5d Update Chinese (Taiwan) translation 2019-03-31 15:12:01 +00:00
1767cd0f6c app: Consider "quit" action for quit
Just like we take a remote "new-window" action into account for
opening new windows, we should call an explicit "quit" action
before falling back to closing all the app's windows on quit.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/624
2019-03-28 00:02:20 +00:00
3e0915521a magnifier: Only connect to signals when ZoomRegion is active
There's no need to listen signals when the zoom region is inactive, so let's
just connect/disconnect them.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/472
2019-03-28 00:38:42 +01:00
a298943fac magnifier: Update screen position on activation
The default ZoomRegion is created at startup and only updated if it is active
when the monitor setup changes. Thus when reactivating the magnifier after a
display change, the viewport used is still the one that been computed with the
old screen geometry values.

Move screen update code inside a function and call it both when activating
the zoom region and when the monitor changes during a zoom session.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1120
2019-03-28 00:38:42 +01:00
df9ddf96a5 iconGrid: Chain up in style-changed
Commit 81ec8215a0 moved the handling of style changes from a signal
handler to a vfunc without chaining up to the parent, losing propagating
the change to children and queueing a paint update.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1117
2019-03-27 18:10:52 +01:00
4fa5d701d5 network: Catch errors when reading devices
NetworkManager added support for a new device - NMDeviceWifiP2P - but
did not add the corresponding enum value in NMDeviceType. The return
value for nm_device_get_device_type() is therefore "illegal" for the
newly added device, and gjs throws an exception.

This should ultimately be fixed in libnm, but as errors when adding
one device shouldn't interfere with adding any other devices, catching
exception is a good idea anyway, so do just that.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1023
2019-03-27 15:06:49 +00:00
b05683d586 Update Croatian translation 2019-03-26 11:34:00 +00:00
2f3f3fbcdb boxpointer: Calculate position using workarea
Take the workarea into consideration when calculating the position and the size
of box pointer and of its arrow.

Closes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/1102
2019-03-22 12:31:48 +00:00
611605a67f scripting: Don't use legacy API
The current scripting module makes heavy use of pre-standardized
iterator/generator/promise APIs, at least for some of those support
was pulled in SpiderMonkey 58.

Port to the new standardized replacements to get the module back into
a working state.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/440
2019-03-21 10:18:02 +00:00
0427a782be main: Wait for startup completion before running perf script
The scripts generally assume a functional shell, so wait until
that is the case.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/440
2019-03-21 10:18:02 +00:00
32baff5906 perf: Use var for METRICS
Each perf module exposes it to the scripting module to report metrics
after all tests have been run. The symbol's scope should allow that,
so declare it as var.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/440
2019-03-21 10:18:02 +00:00
0089143d06 aggregateMenu: Include action buttons in width computation again
Commit 1b169655ac removed the system indicator from the list of children
that are considered for the overall menu width, because we do want the
log-out submenu to adapt to the available width.

However as a side effect, action buttons no longer contribute to the
width either, so if extensions add additional buttons, the menu is
likely to overflow.

Avoid this by only adding the button group to the list of size children.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1094
2019-03-21 10:08:29 +00:00
05e55cee23 Update Arabic translation 2019-03-18 14:37:34 +02:00
31e7f0340f windowCycler: Create settings before chaining up
It's used in _getWindows() which is called from the parent's _init().

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1064
2019-03-18 09:48:02 +00:00
6e317a54fd screenShield: Handle signal 'StatusChanged' when lockscreen is active
When lockscreen is active, screen can't be dimed if signal
'StatusChanged' is ignored. We need to handle this signal.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/900
2019-03-18 08:32:54 +08:00
9c1f62c38c Update French translation 2019-03-17 18:59:32 +00:00
1341d5557f Fix Icon in Tajik translation 2019-03-16 18:21:38 +01:00
b7d79a5f06 Update British English translation 2019-03-16 11:19:57 +00:00
62233a4db4 dnd: Multiply drag threshold by output scale
So it comes out right on hidpi, and consistent with clients.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/455
2019-03-13 17:22:35 +00:00
4a7e2ddff5 dnd: Make startDrag() fail if there is a current grab
This call just went through stomping over previous drag operations if any,
_maybeStartDrag() accounted for this, but other callers (well, WindowClone
in workspace.js) don't. This must bail out early even if a drag operation is
requested, luckily all callers account for it already.

This broke shell state by preserving connected captured-event handlers if
one tried to drag multiple windows simultaneously through multitouch. We
of course don't support that, now more elegantly.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/455
2019-03-13 17:22:35 +00:00
fb737ebde0 Update Tajik Translation 2019-03-13 21:45:05 +05:00
bf77cb44e7 Merge branch 'master' of gitlab.gnome.org:GNOME/gnome-shell 2019-03-13 21:40:31 +05:00
c72e2bb4a9 Update Tajik Translation 2019-03-13 21:39:34 +05:00
68c182b1df Update Tajik Translation 2019-03-13 21:18:10 +05:00
348d303794 theme: Fix :checked:active page-indicator
Closes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1036
2019-03-12 11:58:36 +00:00
ede0fd8660 magnifier: Fix color argument
Clutter.TextureNode takes a Clutter.Color, not a Cogl.Color.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1020
2019-03-12 01:52:22 +00:00
187c2193e8 st-theme-node-transition: Exclude get_new_paint_state() from introspection
to silence a build warning.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/449
2019-03-12 01:14:52 +00:00
706bdd8059 st-widget: Add missing g_return_val_if_fail()
It's a public function, so it's good practice to sanity-check its
input (unless disabled at compile time of course).

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1018
2019-03-12 01:00:32 +00:00
436861edc8 theme: improve legibility of error messages
- the login dialog uses warning_color, so be consistent
- nevertheless increase lightness of the error_color

Fixes issue https://gitlab.gnome.org/GNOME/gnome-shell/issues/1016
2019-03-12 00:54:26 +00:00
9729a2e772 texture-cache: Apply resource scale to the right dimension
Size matters!

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/444
2019-03-12 00:48:11 +00:00
6b924c00c5 layout: Use custom actor for uiGroup
The bind constraint that replaced the Shell.GenericContainer in commit
f4682748fa is subtly different from the previous code:
It forces the actor to have the same size as the stage, rather than just
requesting that size.

This breaks the magnifier which relies on the UI being able to be bigger
than the display size. Fix by going back to using a custom actor.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/646
2019-03-12 00:39:40 +00:00
b90f4d29a4 userWidget: Fix avatar size
The texture cache now returns an actor with an appropriate ClutterContent
rather than a ClutterTexture. That actor uses the CONTENT_SIZE request
mode, which means that it will unconditionally request the preferred size
of the content. That is, setting an explicit size no longer has an effect.

Fix this by making sure the image is already loaded with the desired
dimensions.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1024
2019-03-12 00:34:04 +00:00
47915f8c11 Bump version to 3.32.0
Update NEWS.
2019-03-11 23:54:15 +01:00
5dfdeaa4ea theme: Fix menu arrows
After the latest texture cache changes, loading the icon at its preferred
size and scaling it via the actor size no longer works. Instead, use the
icon-size property which is applied when loading the icon.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/452
2019-03-10 22:03:05 +01:00
98a2a81f2a Update Estonian translation 2019-03-10 16:57:52 +00:00
c4850027bc Fix Icon in translations 2019-03-10 17:32:06 +01:00
d4202e7f38 theme: Handle fallback app icons in notifications
Since commit 3eb80dc6c0, the size of notification icons is determined
by the theme to make it font-relative. Also handle the case where the
icon isn't an StIcon, but a fallback window icon.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1027
2019-03-08 16:20:21 +01:00
4f65283f31 app: Set styleclass on fallback app icons
For window backed apps, create_icon_texture() doesn't return an StIcon
but a generic widget. Set an appropriate style class to make it easier
to apply a specific style only to fallback icons.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1027
2019-03-08 16:20:21 +01:00
d86d3bbe54 texture-cache: Fall back to actor size for bound textures
With StImageContent, the meaning of passing -1 as size parameter changed
from "load the image at its preferred size" to "abort the session". It
is therefore no longer possible to just load the image and then have it
scaled by applying a CSS size to the texture's parent.

Setting the size from CSS is useful though, so to still allow that, fall
back to the actor's size (which can be determined by the style).

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1027
2019-03-08 16:20:21 +01:00
6f794738e8 texture-cache: Load bound surfaces into StWidgets
Using widgets instead of plain actors will allow us to set the size
from CSS.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1027
2019-03-08 16:20:21 +01:00
ef7a93bb07 Update Japanese translation 2019-03-07 11:17:18 +00:00
5197a992a6 Update Tajik translation 2019-03-06 20:15:01 +05:00
49d8540f6d Update Tajik Translation 2019-03-06 20:08:28 +05:00
6e1a1f1a57 Update Tajik Translation 2019-03-06 20:06:55 +05:00
c73428247c build: Add mutter's private directory to libst's build-time RPATH
We need this to run `test-theme`, otherwise when run as part of the
build tests it fails like:

  error while loading shared libraries: libmutter-cogl-4.so.0: cannot
  open shared object file: No such file or directory

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/442
2019-03-06 12:45:48 +00:00
fc2caf5794 Update Hungarian translation 2019-03-05 22:05:20 +00:00
b117826ada keyboard: Add bottom emoji panel row to separate aspect container
So we ensure the row has the right aspect ratio, and buttons neatly aligned
with the bottom row in the alphanumeric view.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/439
2019-03-05 21:11:47 +00:00
26b44b48ab keyboard: align AspectContainer to bottom if restricting vertically
It is convenient for the OSK so it eg. doesn't appear centered in the
available space (eg. on very narrow portrait layouts), plus it will also
be convenient to align other AspectContainers to the same baseline.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/439
2019-03-05 21:11:47 +00:00
6349f0feb1 Bump version to 3.31.92
Update NEWS.
2019-03-05 05:07:44 +01:00
2ae17cfb50 userWidget: Remove frame around avatar
There's a push for round user images, for which the existing square
frame is a bad match. So remove the frame and enforce the shape.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/811
2019-03-04 22:50:29 +00:00
4785093a5c st-shadow: Remove unnecessary ';'
to silence a build warning.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/434
2019-03-04 22:29:33 +00:00
859aef78c4 osk-layouts: Fix French layout
The script to convert XML keyboard layouts to json has a small bug
that causes the French-Canadian layout to end up as French.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/997
2019-03-04 20:55:15 +00:00
20730a5465 data: Don't drop emoji layout on update
https://gitlab.gnome.org/GNOME/gnome-shell/issues/997
2019-03-04 20:55:15 +00:00
fc5f687afc Fix override for fr-CA 2019-03-04 20:55:15 +00:00
53e56f2395 Generate all json files for the android directory in a go 2019-03-04 20:55:15 +00:00
da314aff79 Add convert_xml test 2019-03-04 20:55:15 +00:00
fe89f7c5ac Add level modifiers in JSON
This is needed because some layouts don't have an uppercase level.
That shouldn't make symbols the 2nd level.
2019-03-04 20:55:15 +00:00
8b3be5e063 Remove garbage 2019-03-04 20:55:15 +00:00
58dc538510 Load mappings at module initialisation 2019-03-04 20:55:15 +00:00
6cbef9355d Add unit tests 2019-03-04 20:55:15 +00:00
22eac5c508 Add basic documentation 2019-03-04 20:55:15 +00:00
a2860e9c73 Remove useless test 2019-03-04 20:55:15 +00:00
1c5258ab68 Rename script 2019-03-04 20:55:15 +00:00
8641eaa538 Output JSON and work on directories 2019-03-04 20:55:14 +00:00
88436383c0 Add licence statement from Caribou 2019-03-04 20:55:14 +00:00
affdcdcb0e Import script from caribou source 2019-03-04 20:55:14 +00:00
06174be777 build: Include test-theme in tests
It's an existing test that doesn't require interaction, so there's
no reason why it shouldn't be run by `ninja test`.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/419
2019-03-04 20:10:07 +00:00
fde8401124 test-theme: Change presumed CWD
The executable is assumed to be run from $top_srcdir/src, which is
essentially an autotools left-over (it's where the program ended
up with srcdir == builddir).

Now with meson, its actual srcdir makes more senses.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/419
2019-03-04 20:10:07 +00:00
70ac33d58c test-theme: Force default resolution
Clutter no longer hard-codes a resolution of 96 DPI (although that's
still the default), so any assertions of sizes for physical units
may be off.

Fix this by setting up the test environment according to the
assumptions.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/419
2019-03-04 20:10:07 +00:00
5a897407d9 shell-tray-manager: Silence gdk_window_set_background_pattern warning
Apparently we can't get rid of it without breaking backward compatibility.
So let's stick to how GTK handles it and just silence the warning.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/423
2019-03-04 19:57:47 +00:00
1b3c26364b na-tray-child: Silence gdk_window_set_background_pattern warnings
Apparently we can't get rid of them without breaking backward compatibility.
So let's stick to how GTK handles it and just silence the warnings.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/423
2019-03-04 19:57:47 +00:00
ae07aa7864 gtk-embed: Hide window actors from pick
Since we started to support tray icons on wayland, the icon we show
is not the actual XEmbed window. Instead, we let mutter create a
MetaWindow for it, then use its window actor as source for a clone
we (or nowadays: extensions) can add, remove and destroy freely.

To not let the real icon get in the way, we set an empty input shape
and make its window actor fully transparent. This works OK on X11,
but on wayland all events still go through Clutter, so any reactive
surface actor inside the window actor will block events for any actors
underneath (and status icons go into the top-windows group, so almost
all actors are affected).

Luckily we can pile another hack onto the pile of status icon hacks ...

https://gitlab.gnome.org/GNOME/gnome-shell/issues/191
2019-03-04 19:52:24 +00:00
fb80831269 inputMethod: Handle OSK hiding after unfocus
Set a small timeout in order to let focus changes preserve OSK state. If
focus is eventually unset, the OSK will be hidden.

https://gitlab.gnome.org/GNOME/gtk/issues/1277
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/397
2019-03-04 18:24:38 +00:00
561cecf383 shellDBus: Add UngrabAccelerators
While it is possible to register accelerators in-bulk, there is no
proper way to unregister them again. This adds the corresponding call
for UngrabAccelerator to allow ungrabbing multiple accelerators at the
same time.

The idea is that g-s-d can use this in the future to simplify the
keybinding reload logic.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/429
2019-03-04 16:45:16 +00:00
60ccdc2deb dnd: Only handle touch events in wayland
There are serveral issues around touch passive grab and touch/pointer doubly
handling to use these on X11, so we stick to single-touch/pointer there.

Closes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/1015
2019-03-04 16:21:28 +00:00
d7d996b1d3 automountManager: Fix playing disconnected sound
A typo sneaked in in commit 9a35c990 ...

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/432
2019-03-04 14:39:40 +01:00
32b8bc39ac inhibitShortcuts: Save choice in permission store
Use the permission store to remember the user's decision as to whether
or not grant the shortcuts request when the application is known.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/382
2019-03-04 10:12:58 +01:00
9dc99ad611 Updated Lithuanian translation 2019-03-03 18:54:25 +02:00
628cb4d553 Update Latvian translation 2019-03-03 14:18:43 +00:00
ad80bce78d Update Dutch translation 2019-03-03 10:15:54 +00:00
1c9d821aa2 messageTray: Add source policy setter
Commit 8f15193b4 changed the `policy` property from a regular JS property to
a getter. This was necessary to avoid calling an overridden _createPolicy()
method before a subclass is properly initialized, but it broke the second
way of using notification sources:

Don't create a Source subclass, but use the base class directly and change
its `policy` property.

There's no good reason why we should no longer allow this, so add a setter.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/431
2019-03-03 08:58:56 +00:00
510b060947 Updated Vietnamese translation
Signed-off-by: Trần Ngọc Quân <vnwildman@gmail.com>
2019-03-03 13:48:55 +07:00
26e33ff093 windowAttentionHandler: Don't destroy on open
The activateWindow() call is expected to focus the window, which
already destroys the source. If we then destroy it again explicitly,
we get another "invalid access" warning.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/430
2019-03-02 22:09:33 +01:00
5f2bd70690 network: Don't destroy wireless dialog twice
The dialog doesn't change the `destroyOnClose` property from its default,
so it is already destroyed automatically on close. So if we also destroy
it explicitly, we end up (rightfully) with one of gjs' infamous "invalid
access" warnings.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/430
2019-03-02 22:09:20 +01:00
6dfa550663 Update German translation 2019-03-02 20:14:39 +00:00
252e2420ad Update Romanian translation 2019-03-02 19:55:56 +00:00
572d54981e appsMenu: Fix initial visibility of "Details" item
It is only supposed to be visible when Software is installed, but
we currently only update the visibility on changes.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/989
2019-03-02 18:13:38 +00:00
61471f9fb4 search: Hide the separator line of the last result
If a result is displayed at the end of the search results, there should
obviously not be a line separating it from the next result underneath
it. To fix this, always hide the separator for the last result visible.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/311
2019-03-02 12:29:41 +00:00
4d0a742d64 st: Only consider visible children for :first/:last-child
While mapping the :first/:last-child pseudo classes directly to the
ClutterActor:first-child/:last-child properties allows for an easy
implementation, it is unexpected that rules can appear to not have
an effect because the selected child is hidden. GTK's behavior of
applying the classes to visible children makes much more sense, so
change our implementation to do the same.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/312
2019-03-02 12:19:40 +00:00
5f4e0e5ff8 plugin: Style consistency fix
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/315
2019-03-02 11:57:21 +00:00
a4c159ecad plugin: Use G_DECLARE_FINAL_TYPE
libmutter-4 added support for this, so we can also drop the boilerplate.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/315
2019-03-02 11:57:21 +00:00
b1f893e998 plugin: Move class_init and init below methods
This allows us to get rid of all the forward declarations, tidying up
the file a bit.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/315
2019-03-02 11:57:21 +00:00
789dc165af plugin: Add some comments on its purpose
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/315
2019-03-02 11:57:21 +00:00
115eda9650 shell-screenshot: Apply monitor scale to cursor surface
When we grab a screenshot of a framebuffer scaled shell, we shoudl apply the
device scale to the image surface, while the monitor scaling should be applied
to the cursor surface, so that it's painted at proper coordinates and in proper
size in the generated image.

This is not needed for XWayland clients as they are not scaled anyways, while
for wayland clients that are painted in multiple monitors, this might cause
a lower quality cursor in the lower dpi monitor, because the cursor sprite is
generated for the monitor scale, and not for the surface scale.

https://bugzilla.gnome.org/show_bug.cgi?id=765011
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/5
2019-03-01 17:12:53 +00:00
d027e35cef shell-screenshot: Always use "actors-painted" signal
Since we don't care about all the stage to be painted here, we can just proceed
when all the actors have been put in place.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/5
2019-03-01 17:12:53 +00:00
b3e178af9d shell-screenshot: Use mutter paint signals to optionally draw cursor
Under wayland, if the cursor should be included when doing a fullscreen
screenshot, we can rely on mutter "paint" signal to have it composited for free.
Otherwise if it's not requested, we can use the "actors-painted" signal to get a
stage texture before the mouse overlay has been added.

Instead, under X11 or when only a window screenshot is requested, we still
need to draw it manually.

https://bugzilla.gnome.org/show_bug.cgi?id=765011
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/5
2019-03-01 17:12:53 +00:00
559ec8750a shell-screenshot: Add utility function to check when draw the cursor
Don't repeat the same logic in multiple places, just set include_cursor to the
proper value once depending on the settings we have.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/5
2019-03-01 17:12:53 +00:00
02c3980b83 shell-screenshot: Initialize cursor tracker in draw cursor function
Avoid code duplication, since we're using this only if the cursor has to be
painted differently.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/5
2019-03-01 17:12:53 +00:00
6f027ee7dc shell-util: Apply resource_scale on clipping when getting the meta texture image
https://bugzilla.gnome.org/show_bug.cgi?id=765011
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/5
2019-03-01 17:12:53 +00:00
6d6c2e5b99 shell-recorder: Use clutter-computed sizes and scaling for the capture
Get from clutter the capture sizes and scale and don't mind
about doing any rounding here, as it might be different
from the one done at clutter level (causing mismatch and
not-working videos). Delegate this to clutter, and forget
about the internal details.

These values are then used to composte the image and set the video caps.

https://bugzilla.gnome.org/show_bug.cgi?id=7650111
2019-03-01 17:12:53 +00:00
4a4f752459 dateMenu: Relayout IndicatorPad when parent size changes
This happens often in resource-scaled world

https://bugzilla.gnome.org/show_bug.cgi?id=765011
2019-03-01 17:12:53 +00:00
8f1fff1374 background: Don't set background actor sizing and scaling
Mutter BackgroundActor is able do detect this at lower level

https://bugzilla.gnome.org/show_bug.cgi?id=765011
2019-03-01 17:12:53 +00:00
deead2af97 layout: Add scale property to Monitor
https://bugzilla.gnome.org/show_bug.cgi?id=765011
2019-03-01 17:12:53 +00:00
9e881ab637 animation: Reload sliced texture on global scale change
When the scale has changed we need to reload the texture at proper size.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/5
2019-03-01 17:12:53 +00:00
b6ec02cef2 animation: Load sliced image using resource scale, and reload on change
Also make sure that the textures size is matching the container size.

https://bugzilla.gnome.org/show_bug.cgi?id=765011
2019-03-01 17:12:53 +00:00
26e3ccda49 loginDialog: Load logo file texture given resource scale
And reload the logo if the resource scale changes.

https://bugzilla.gnome.org/show_bug.cgi?id=765011
2019-03-01 17:12:53 +00:00
2bda79cb3a st-texture-cache: Use GSlice to manage memory of leaders data
This allows some memory optimizations when possible, so let's use it.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/5
2019-03-01 17:12:53 +00:00
19c60ff5c5 st-texture-cache: use StImageContent for cairo bound surface
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/5
2019-03-01 17:12:53 +00:00
e3c5c9a2e7 st-texture-cache: Cancel sliced image loading on target actor destroy
It might happen that the target clutter actor that we return on call
of st_texture_cache_load_sliced_image might be destroyed while the
loading task is still running. To protect from this, let's connect
to "destroy" signal and when this happens we use a cancellable to
stop the task.

This allows to safely reuse the return value of this function to
cancel the execution and avoiding that load_callback is called
even for a request that is not anymore under our control.

https://bugzilla.gnome.org/show_bug.cgi?id=765011
2019-03-01 17:12:53 +00:00
2c17c186b8 st-texture-cache: Load sliced contents with REQUEST_CONTENTENT_SIZE
When loading an actor for a sliced image actor, we can now use the
REQUEST_CONTENT_SIZE request-mode for the actor since we the content image
has now a predictable size and thus we can be sure that the size will be applied
taking care of the resource scale.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/5
2019-03-01 17:12:53 +00:00
ef1697d00d st-texture-cache: Set sliced actor size in logical size
The actor size should be set in logical size more than in the actual size
of the texture when using resource scale.

https://bugzilla.gnome.org/show_bug.cgi?id=765011
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/5
2019-03-01 17:12:53 +00:00
40e7638a4b st-icon: Add resource-scale support
This commit adds support for scaling the StIcon resource (the icon
texture) according to the resource scale.

https://bugzilla.gnome.org/show_bug.cgi?id=765011
2019-03-01 17:12:52 +00:00
aaf69b2898 st-texture-cache: Use StContentImage to create actor contents
This will allow to use resource-scale aware content that will use a preferred
size that takes in account the icon scaling and the resource scaling.

If no size is passed we should just divide the actual resource size by the
resource scale, as we assume that it's loaded with such scaling applied.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/5
https://bugzilla.gnome.org/show_bug.cgi?id=765011
2019-03-01 17:12:52 +00:00
0464361ca5 st-image-content: Wrap ClutterImage with explicit preferred size
Create StImageContent as a simple ClutterImage with preferred width/height
properties in order to be able to use explicit sizing when creating clutter
contents that will be applied to actors whose size depends on the content itself.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/5
2019-03-01 17:12:52 +00:00
420697693b st-texture-cache: Separate 'scale' to 'paint_scale' and 'resource_scale'
Instead of just passing a scale when getting a cached icon, pass both a
'paint_scale', the scale of which the icon will be painted on the
stage, and a 'resource_scale', the scale of the resource used for
painting.

In effect, the texture size will use the scale 'paint_scale * resource_scale'
in a ceiled value while the size of the actor will use 'paint_scale' when
determining the size.
this would load a bigger texture, but the downscaling would keep the visual
quality.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/5
https://bugzilla.gnome.org/show_bug.cgi?id=765011
2019-03-01 17:12:52 +00:00
37f53a42da st: Create shadow pipeline taking resource scale in account
The shadow pipeline is created doing software blurring of the texture so the
shadow spec blur parameter should be scaled accordingly with the texture scaling
otherwise we won't take enough pixels in account creating stronger shadows.

https://bugzilla.gnome.org/show_bug.cgi?id=765011
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/5
2019-03-01 17:12:52 +00:00
5617ffc79c st: Use scaled surfaces for creating cairo background shadows
Create the surfaces for background shadows at scaled sizes and then draw on them
using logical coordinates, by setting the surface device scale accordingly.

Use the said surface scale when generating the actual shadow cairo pattern
but in such case, to reduce the number of code changes, is better to work in
absolute coordinates, and to do so:
  1) Create a temporary shadow-spec copy with scaled values to absolute sizes
  2) Invert the scaling on the shadow matrix
  3) Do the actual painting in absolute coordinates
  4) Set the shadow matrix scaling back to the logical coordinates.

Finally scale down the created shadow pattern surface size when painting it,
applying again a reverse scale to the matrix.

https://bugzilla.gnome.org/show_bug.cgi?id=765011
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/5
2019-03-01 17:12:52 +00:00
ca4d86e9e5 st-shadow: Define autoptr cleanup function for StShadow
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/5
2019-03-01 17:12:52 +00:00
0141fef561 st-theme-node: Paint elements in resource-scale scaled surfaces
Pass resource-scale to drawing phase, and use it to create texture
surfaces scaled with the widget current scaling.
Also redraw by default widgets when the resource scale changes.

https://bugzilla.gnome.org/show_bug.cgi?id=765011
2019-03-01 17:12:52 +00:00
5d4a804c90 st-shadow: Ceil size before comparing with texture
A fractional resource scale would mean we never use the fast path for
creating the shadow, because we'd cast the int to a float before
comparing, which would never match.

Instead compare the expected texture size with the source texture, to
actually potentially trigger the fast path.

https://bugzilla.gnome.org/show_bug.cgi?id=765011
2019-03-01 17:12:52 +00:00
6bc3300e5a st-scroll-view-fade: Include outer bound of pixel on border
The fade shader will draw the fade effect up until the border pixel. If
we set the bottom right coordinate to the outer edge of the pixel we
might end up not drawing the fade effect on all of the pixels. This
could for example happen if one logical pixel (clutter stage pixel)
consists of more than one physical pixel.

https://bugzilla.gnome.org/show_bug.cgi?id=765011
2019-03-01 17:12:52 +00:00
15f69bdc3b st-label: Paint shadow using resource-scaled texture
https://bugzilla.gnome.org/show_bug.cgi?id=765011
2019-03-01 17:12:52 +00:00
0bcf76970a st-private: Scale shadows accordingly to actor resource scaling
Use scaled offscreen framebuffer to paint shadows so that it will match the
scaling applied to the actual actor.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/5
https://bugzilla.gnome.org/show_bug.cgi?id=765011
2019-03-01 17:12:52 +00:00
03c4628cad st-drawing-area: Draw content taking care of the resource_scale
https://bugzilla.gnome.org/show_bug.cgi?id=765011
2019-03-01 17:12:52 +00:00
9f4ae9618a st-widget: Introduce widget resource scale
This commit makes StWidget manage the scale of which its associated
resources should be multiplied with. The resource scale is calculated
by clutter, and is retrieved by clutter_actor_get_resource_scale(). Due
to the resource scale not always being available, the getter may fail,
and the actual widget that draws the content will have to deal with
this situation.

As the resource scale depends on where on the stage the widget is drawn,
the resource scale will in general be available once the widget is
mapped.

https://bugzilla.gnome.org/show_bug.cgi?id=765011
2019-03-01 17:12:52 +00:00
3590af15bb Update Indonesian translation 2019-03-01 15:32:29 +00:00
c5de7fd20e Updated Danish translation 2019-02-28 23:09:39 +01:00
7127fb1fa1 gvc: Update submodule to up-to-date version
This frees us from all remaining '‘g_type_class_add_private’ is deprecated'
warnings.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/427
2019-02-28 21:59:08 +01:00
7cf11abefc build: Bump gjs requirement
While we don't actually require a more recent version at build time,
we do need the latest stable version at runtime. There's no strong
reason for making that differentiation, so bump the requirement.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1006
2019-02-28 19:43:45 +01:00
d78b416e1a lookingGlass: Use symbolic icon for close button
As per commit 4d2dce2c, the actual close button is generated using custom css
and a symbolic icon.

Apply the same change to lookingGlass too.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/425
2019-02-28 16:21:38 +01:00
f5144ec899 Update Serbian translation 2019-02-28 13:26:19 +00:00
08d1ebe7ee Update Italian translation 2019-02-28 08:14:02 +00:00
a665801e9f Update French translation 2019-02-28 07:39:24 +00:00
112e3b110b Update Korean translation 2019-02-28 03:16:35 +00:00
94a674c008 na-tray-manager: Use gdk_screen_get_default() and gdk_x11_get_default_screen()
instead of explicit screen arguments and `gdk_screen_get_number()`, as nowadays there
is always only one screen. This silences some deprecation warnings and removes
deprecated API.

Bonus: some code style cleanups

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/422
2019-02-27 00:35:04 +01:00
72be8eeb31 ci: Use custom image for JS checks
Running dnf to update and install additional packages every time
the job is executed slows down the CI pipeline. Avoid this by
using another custom images for JS source checks.

In addition to the js shell we use for the existing syntax check,
also include eslint for future jobs and some extension-specific
tooling to make the image more useful to extension authors.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/408
2019-02-26 21:08:17 +00:00
ad8690bb2e ci: Check that pot file is generated correctly
This is to guard against the now infamous xgettext bug[0].

[0] https://savannah.gnu.org/bugs/?50920#comment5

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/408
2019-02-26 21:08:17 +00:00
76cb08a72a ci: Add test stage
We never gained a proper test suite, but run at least the tests we
have.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/408
2019-02-26 21:08:17 +00:00
2d4989e937 ci: Add build stage
So far we are only performing a basic syntax check on javascript
sources; it's time to test the C code as well. As mutter is tightly
coupled, we bite the bullet and build it as well, either using a
matching branch (if it exists), or current master.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/408
2019-02-26 21:08:17 +00:00
f248b91f82 ci: Skip source_check stage when appropriate
We don't have to run the static analyzer on javascript sources when
no javascript source was changed.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/408
2019-02-26 21:08:17 +00:00
d671eb1969 ci: Sync check-commit-log script with mutter
A couple of cleanups came out from the review in mutter, catch
up with those.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/408
2019-02-26 21:08:17 +00:00
70f4906ca5 aggregateLayout: Fix natural width computation
Ouch, this went unnoticed for a long time: As the minimum size of menu
items is generally small (because its label can be ellipsized), we are
requesting the unellipsized width of the last "size child" instead of
the widest one.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/996
2019-02-26 08:25:00 +00:00
ffb9aa1ace test-theme: Stop using ClutterCairoTexture
It's deprecated, so use one of our own types for testing type
inheritance.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/420
2019-02-26 03:04:00 +01:00
823fd855cf na-tray-child: Silence some deprecation warnings
Use `gdk_x11_display_error_trap_...` instead of `gdk_error_trap_...`

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/417
2019-02-26 01:37:54 +01:00
f5ee225362 shell-tray-icon: Silence some deprecation warnings
Use `gdk_x11_display_error_trap_...` instead of `gdk_error_trap_...`

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/417
2019-02-26 01:37:46 +01:00
ff1ea4b1c9 st-clipboard: Remove get/set_property functions.
Remove st_clipboard_get_property and st_clipboard_set_property because they are
identical to the default implementation.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/414
2019-02-26 00:23:36 +00:00
779b5afa51 theme: Add bottom padding for sub menus
Prevents overlapping sub menu borders with menu item background.

Closes https://gitlab.gnome.org/GNOME/gnome-shell/issues/987
2019-02-25 11:35:13 +01:00
6d870f6ae4 Update Russian translation 2019-02-24 20:48:43 +00:00
d3926cbca9 Update Basque translation 2019-02-23 20:43:56 +00:00
a308804679 Update Esperanto translation 2019-02-23 09:23:49 +00:00
a4e4da705a Bump version to 3.31.91
Update NEWS.
2019-02-21 19:58:25 +01:00
7a494ec027 Update Icelandic translation
(cherry picked from commit bfcfa64456)
2019-02-21 11:20:18 +00:00
d53ebb101a Update Brazilian Portuguese translation 2019-02-21 01:06:52 +00:00
f3168d22a6 shellDBus: Add grabFlags parameter
Add an grabFlags parameter to the GrabAccelerator and GrabAccelerators dbus
methods. This will allow e.g. Gnome Settings Daemon to create shortcuts that
should discard key-repeated events.

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

Fixes: https://gitlab.gnome.org/GNOME/gnome-settings-daemon/issues/68
2019-02-20 14:17:46 +01:00
be06101e9a Updated Danish translation 2019-02-16 20:56:32 +01:00
6e4178981a Update Kazakh translation 2019-02-16 10:54:56 +00:00
b85ea59cda Update Scottish Gaelic translation
(cherry picked from commit ea3d897439)
2019-02-16 09:34:25 +00:00
bbd68626cc ctrlAltTab: Fix more fallout from ES6 classes
Since ShellGenericContainer was removed, switcher popups and lists
are StWidget subclasses rather than plain JS classes.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/411
2019-02-15 20:26:16 +01:00
8490173879 Update Indonesian translation 2019-02-14 15:19:05 +00:00
baed9518c2 Update Scottish Gaelic translation
(cherry picked from commit 5979f87295)
2019-02-14 09:04:13 +00:00
27d0d9f2b3 gitlab-ci.yml: Add check for issue or MR URL
This adds a pipeline stage for merge requests that checks that the
commit message contains an URL to either a issue or a merge request.
This means that for merge requests without corresponding issues will
always fail initially, as the merge request URL is not known until after
it is created. This is still arguably better than accidentally merging
merge requests without URLs.

Taken from https://gitlab.gnome.org/GNOME/mutter/merge_requests/440.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/410
2019-02-13 20:41:02 +01:00
382282b931 README.md: Add contribution section
Include a link to where to create merge requests, and describe the
requirements regarding commit messages which we are about to enforce.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/410
2019-02-13 20:37:39 +01:00
23d233857e calendar: Load interface description from resource
Here's a template string with '/' that escaped commit 94423151b2,
resulting in an xgettext warning when generating the .pot file.

Simply move it into the resource like the other interface descriptions
to make xgettext happy again.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/407
2019-02-13 17:58:36 +00:00
9620bd0f22 Add a Taquin renamed desktop id.
Taquin is org.gnome.Taquin.
2019-02-13 13:37:07 +01:00
ecfe56ca63 Add the 2048 renamed desktop id.
gnome-2048 id is now set to
org.gnome.TwentyFortyEight.
2019-02-13 13:37:04 +01:00
eabb02d3da Change Iagno renamed desktop id.
Iagno is org.gnome.Reversi,
instead of org.gnome.Iagno.
2019-02-13 13:37:01 +01:00
da3953a388 Clean out some eclipse artefacts
Someone added those in the mists of time, likely by mistake.
2019-02-13 04:39:26 +01:00
2d26dbc96f Updated Slovenian translation 2019-02-12 12:29:23 +01:00
7073471302 Update Swedish translation 2019-02-11 18:01:01 +00:00
81f0e7de9e texture-cache: Use content size for returned images
Since commit deec0bf255, the texture cache is based on ClutterImage
rather than ClutterTexture. As ClutterImage (like all ClutterContent)
is only concerned with painting, it doesn't influence the size of the
actor it is added to at all, and the returned actor will now stay at
size 0x0 after the image has been loaded.

Set up the actor to follow the content's size instead, to get closer
to the previous behavior.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/402
2019-02-10 19:29:13 +00:00
33e05f5912 system: Always use default avatar in switch-user submenu
It is too small to be really useful, and sticks out being the
only color icon.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/957
2019-02-10 10:33:23 +00:00
c1d3e304cb windowManager: Only allow top-drag gesture if focus window is fullscreen
The top drag gesture is not of any use if the topmost window is not
a fullscreen window and will only block events near the important top
screen edge (i.e. the panel). To fix this, only enable this gesture if
the focus window is a fullscreen window.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/552
2019-02-10 10:06:11 +01:00
1b169655ac aggregateMenu: Don't use system menu for width computation
If the user's real name is too long to fit the menu comfortably, we are
supposed to use the username instead. However since commit f8e5e3e435,
we no longer set a max-width on the menu as a whole, but instead base
the width request on only "unellipsizable" children. For some reason
the system menu ended up there, so the name is now allowed to grow
indefinitely.

Remove it from the list of size children to get the intended behavior
back.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/400
2019-02-10 02:18:40 +00:00
67393e09c3 Update Turkish translation 2019-02-09 20:28:53 +00:00
1ec8d2c531 Update Finnish translation 2019-02-09 18:57:01 +00:00
a111bfb90a userWidget: Add back missing import
This was accidentally dropped in commit a1534dab02.
2019-02-09 18:51:14 +01:00
7dd326f090 keyboard: Make items in language menu unfocusable
The menu grabs the key focus when opened, which takes focus away from
whichever actor triggered the keyboard. And as the menu doesn't have
any text entries, the keyboard is popped down as a result.

Prevent this by making the menu items unfocusable, so the keyboard
focus just stays where it is. Considering that the menu is part
of the on-screen keyboard itself, not being keyboard-navigatable
isn't a big deal here.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/171
2019-02-09 14:48:27 +00:00
24a26e025b popupMenu: Respect items' :can-focus property
Menu items use a single 'active' state that follows both hover and
keyboard focus. It therefore makes sense for the active item to always
grab the focus, in particular as an item that is sensitive but not
focusable by keynav would be rather weird.

As it turns out, we do have a case that is weird enough where we want
exactly that, so only grab focus if the actor's :can-focus property
allows it.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/171
2019-02-09 14:48:27 +00:00
1eb7ba0506 Update Galician translation 2019-02-09 12:35:45 +00:00
d17d99bd6d lookingGlass: Include St in default imports instead of Gtk
Until commit 467b7c1bca, the import used to leak into the
eval() environment, but not anymore. Add it back (and remove
Gtk, as it's not *that* useful).

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/398
2019-02-09 12:22:14 +01:00
fd50b9a45e cleanup: Use destructuring for imports from GI
This is *much* nicer than repetitive "imports.gi" lines ...

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/399
2019-02-09 07:39:20 +01:00
a1534dab02 cleanup: Clean up unused imports
Spotted by eslint.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/399
2019-02-09 05:05:07 +01:00
7484458b7c Updated Czech translation 2019-02-08 09:41:49 +01:00
5ca039c1db Update Japanese translation 2019-02-07 13:10:37 +00:00
2294ae0c46 Update Catalan translation 2019-02-07 08:59:11 +01:00
4d2b2a12ea Bump version to 3.31.90
Update NEWS.
2019-02-07 02:46:51 +01:00
c6d57059ff tests: Work around import dependency loop
The markup unit test currently fails with the following message:

  TypeError: class heritage MessageList.Message is not an object or null

This is because MessageList imports other modules that end up importing
MessageList themselves in order to inherit from one of its classes. But
as the MessageList imports hasn't finished yet (it's still processing
its own imports), that class hasn't been defined yet.

Work around that by importing Main first, so that the importer can
process imports in a proper order.
2019-02-07 02:46:51 +01:00
5f13cf767e Update Polish translation 2019-02-06 21:57:54 +01:00
93425b0500 extensionUtils: Include some more helper functions
Those functions originated in gnome-shell-extension's Convenience
module which is copied by almost every extension out there. Let's
make people's life just a little bit easier by including the code
ourselves.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/150
2019-02-06 19:52:21 +01:00
a87ab6d0fc panel: Restrict app menu width
Window titles aren't restricted in length, so the menu may end up unwieldily
width. Commit 0bec76b6ee therefore limited the app context menus, but that
got accidentally dropped in commit 0ded0dbfd5. Add back the limitation and
extend it to the new app menu as well.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/624
2019-02-06 18:29:15 +01:00
1c117c469a panel: Desaturate appmenu icon
Top bar icons are supposed to by symbolic, but not all applications
provide a symbolic icon. Make the stick out less by desaturating
the appmenu icon if a symbolic style is requested.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/624
2019-02-06 18:29:15 +01:00
8003f8b803 build: Don't introspect ShellMenu
It is now only used internally by ShellApp to track remote actions,
so there's no need to expose it to javascript code.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/624
2019-02-06 18:29:15 +01:00
7df93458d7 build: Remove remote menu support
It is now unused.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/624
2019-02-06 18:29:15 +01:00
753618a19f app: Remove :menu property
It is now unused.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/624
2019-02-06 18:29:15 +01:00
e355756758 app: Don't rely on app menu to check for GtkApplications
As the app menu is being phased out, it is no longer a good indicator
for GtkApplications. Instead, base the check directly on the appropriate
D-Bus properties.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/624
2019-02-06 18:29:15 +01:00
62a3b9e6a3 windowMenu: Remove fallback app menu support
With the app menu being phased out entirely, there's no good reason to
keep support for the fallback app menu in decorations either - the number
of applications that set an app menu and haven't embraced client-side
decorations is extremely small, and they should already have alternative
fallbacks for non-GNOME environment in place.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/624
2019-02-06 18:29:15 +01:00
dc79393b27 panel: Replace remote app menu
Since the plans to retire the app menu were announced, nobody objected to
the removal of the menu content, however some concerns were raised about
the menu's secondary role as indicator.

Account for that by not removing the existing app menu, but replacing it
with a built-in menu similar to the existing app icon context menu.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/624
2019-02-06 18:29:12 +01:00
c334aa2a4c panel: Ignore shell-shows-app-menu setting
The GtkSettings was originally introduced to inform applications about
the desktop shell's capabilities, but users soon started to use it to
force GTK+ to show the app menu inside the application. We eventually
caved and also handled the setting ourselves to hide the in-shell app
menu to allow users to "move" it.

But now the remote app menu is in the process of being retired[0], and
will be replaced with a simple indicator that cannot be moved, so
stop following the GtkSetting.

[0] https://gitlab.gnome.org/GNOME/Initiatives/wikis/App-Menu-Retirement

https://gitlab.gnome.org/GNOME/gnome-shell/issues/624
2019-02-06 18:26:56 +01:00
9f61a4f5fd panel: Remove unused import
https://gitlab.gnome.org/GNOME/gnome-shell/issues/624
2019-02-06 18:26:56 +01:00
15d0050994 Update Japanese translation 2019-02-06 14:20:41 +00:00
1846f337d8 Update Catalan translation 2019-02-06 14:40:51 +01:00
a9e63039ce Update Japanese translation 2019-02-06 12:00:12 +00:00
7edd5f27d1 Updated Czech translation 2019-02-06 12:01:59 +01:00
9b47195974 Updated Spanish translation 2019-02-06 11:40:43 +01:00
4ef8041be0 Update Hungarian translation 2019-02-05 20:06:11 +00:00
f0a7395b30 shellActionModes: disable POPUP keybindings in unlock screen
Certain keybindings should continue to work even when a popup
menu is on screen. For instance, the keybinding for showing
the app menu and the keyinding for showing the calendar are
examples.

This is achieved by putting in place a special "POPUP" action
mode, whenever a popup menu is active.  This mode replaces
the (e.g., "NORMAL" or "OVERVIEW") action mode that was in place
for as long as the popup menu is active.

But those keybindings should not work when the user is at the
unlock dialog (which uses an action mode of "UNLOCK").

Unfortunately, since commit c79d24b6 they do.

This commit addresses the problem by forcing the action mode
to NONE at the unlock screen when popups are visible.

CVE-2019-3820

Closes https://gitlab.gnome.org/GNOME/gnome-shell/issues/851
2019-02-05 11:09:40 -05:00
c1a6effea0 panel: Don't allow opening hidden menus via keybindings
We shouldn't allow toggling menus that aren't supported by the
current session mode, but as indicators are hidden rather than
destroyed on mode switches, it is not enough to check for an
indicator's existence.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/851
2019-02-05 11:08:45 -05:00
f78efc46e7 keyboard: Implement keypad OSK panel
This is pretty ad-hoc, the panel is hooked so it shows right away on the
right Clutter.InputContentPurpose.
2019-02-05 16:25:57 +01:00
42ae052da7 keyboard: Add Emoji keyboard
This keyboard works similar to GTK+'s emoji chooser (actually, both pull
from the same JSON file). Emojis are categorized in sections and variants
and kept in a "model".

The EmojiPager actor then uses this model to generate pages on-the-fly as
the user swipes around. This is an important optimization since the amount
of actors would rival with the rest of the shell otherwise.

The EmojiSelection object puts the EmojiPager, the page indicators and
a KeyContainer with the bottom row of emoji section shortcuts together to
implement the emoji panel as a whole.

The Keyboard object hooked this to an "emoji" key, which is just visible
on the Clutter.InputContentPurpose where showing an emoji would be
meaningful. Otherwise the surrounding buttons are made a bit wider to
cover up for it (i.e. as it was before).
2019-02-05 16:25:57 +01:00
fab390826e appDisplay: Separate PageIndicators to a separate file
In order to cater for emoji panel usage, we want something like PageIndicators
except:
- It should have horizontal disposition
- It should not be animatable (?)
- It should not be reactive

Separated PageIndicators into a base, non-animated widget, and an
AnimatedPageIndicators that can be used on appDisplay.js. Reactiveness is
set through an extra method, and layout is set as a construct argument.
2019-02-05 16:25:54 +01:00
2a9923628b keyboard: Separate aspect ratio control to a container actor
This will be useful as we want other panels (eg. emoji) to preserve aspect
ratio with the rest of the OSK. Separate the aspect ratio management logic
into this container that will be the parent of them all.
2019-02-05 16:25:54 +01:00
291aa0b053 keyboard: Remove unused code
This signal does not exist, the Suggestions.add() method allows to attach
per-element callbacks instead.
2019-02-05 16:25:54 +01:00
83eb75ad7a keyboard: Fix JS warning
Iterate correctly through the array, instead of stepping on the possibly
non existent first element.
2019-02-05 16:25:54 +01:00
bb215966e5 keyboard: Fix JS warning
The label field may be empty here (eg. buttons fully styled through css),
just resort to an empty string then.
2019-02-05 16:25:54 +01:00
545d49c70d keyboard: Fix JS warning
The solution is pointed out by the warning itself.
2019-02-05 16:25:54 +01:00
ace44af815 theme: Reduce minimum OSK key width/height
The OSK panel uses 1/3rd of the monitor height, plus we specify a minimum
size for the keys. This doesn't play along if contents won't fit (short
monitor, big fonts, ...) pushing contents offscreen. Reduce the minimum
size a bit so there's better chances to fit.

Closes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/675
2019-02-05 16:25:54 +01:00
699e97559d windowManager: Disable bottom edge swipe gesture if OSK is enabled
It does not make sense then, plus it eats events close to the edge.
2019-02-05 16:25:54 +01:00
4aecf4c973 keyboard: Avoid sequence grabs on touch
We can do without these. Since grabs prevent gestures in parent containers
from happening, we actively don't want these for emoji scrolling/paging.
2019-02-05 16:25:54 +01:00
b092c5f37d st: Honor button mask on touch events
Even though it's not a "button", we use button1 to map to actions. Seems
fair to refuse to press the StButton if it would not react to button1.
2019-02-05 16:25:54 +01:00
aca8aec94b Update Friulian translation 2019-02-05 15:00:15 +00:00
9cfb51c106 panel: Remove panel translucency
Since commit 447bf55e45 we turn the top bar translucent when
free-floating. While this looks fancy and reduces the appearance
of cutting into the available screen space, it has also had a
negative effect on legibility.

Nobody stepped up to address those issues in two years, so revert
back to the fully opaque top bar.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/408
2019-02-05 12:08:57 +00:00
e2352f5126 theme: basic color sync
- sync colors to the gtk palette

Addresses issue #841
2019-02-05 11:56:39 +00:00
40e624444c dateMenu: Refresh world clocks section
Update the section styling to accentuate the most relevant information,
and include the timezone.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/262
2019-02-05 11:36:38 +00:00
3cf67b1236 dateMenu: Show weather location in section header
It is useful information, in particular when the location is set
automatically via geoclue.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/262
2019-02-05 11:36:38 +00:00
5dedb97fcc dateMenu: Use graphical weather forecasts
While the current textual forecast is non-intrusive, it may be too
much so, making it less effective to spot the current conditions
at a glance.

Refresh the section to use a more conventional graphical representation,
similar to the one used by gnome-weather itself.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/262
2019-02-05 11:36:38 +00:00
4590094605 windowManager: Add switch-to-application-n keybindings
Having Unity-like shortcuts for activating the first nine applications
in the dash has been a long requested feature, but somehow nobody got
around to implement it.

As the shortcut is most useful outside the overview where the dash is
not visible, only consider favorite apps as they have a predictable
order.

https://bugzilla.gnome.org/show_bug.cgi?id=648000
2019-02-05 11:33:30 +00:00
15e7625c80 cleanup: Remove erroneous vfunc parameters
Unlike in C or signal handlers, vfuncs don't include the this-object
in their arguments.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/388
2019-02-05 02:21:40 +00:00
cdd2803498 Don't mistake GObject.registerClass() for a constructor
Those slipped through when porting from Lang.Class to ES6 classes.

Very indirectly spotted by eslint.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/388
2019-02-05 02:21:40 +00:00
43fb2b38b1 screenshot: Remove bogus parameter
Expecting a callback argument over D-Bus doesn't make any sense at
all, whoops.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/388
2019-02-05 02:21:40 +00:00
95224bd006 objectManager: Fix index mix-up
Spotted by eslint.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/388
2019-02-05 02:21:40 +00:00
446183adee app: Remove unused code
This was overlooked back in the day when application search moved into GIO.
2019-02-05 01:54:17 +01:00
345a8fe748 thunderbolt: ensure failure msg is translatable
Swap the gettext() and format() calls to ensure that the message
is translatable.
2019-02-04 18:53:42 +00:00
d8593c5b4a st: Init icon theme in StSettings
This was not initialized, leaving a default icon theme unless
changed later.

Closes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/953
2019-02-04 17:13:36 +00:00
f89d721c12 Update Friulian translation 2019-02-04 15:57:07 +00:00
af34b7c25e Update Hungarian translation 2019-02-03 17:10:51 +00:00
b108aa1ace Update Polish translation 2019-02-03 17:30:15 +01:00
5dbf09c008 extensionPrefs: Work around xgettext bug
xgettext is thrown off by the combination of backticks and slashes,
which makes template string a fun trap to fall into. Just use
String.format() for now ...

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/383
2019-02-03 16:11:09 +00:00
680dc18c6b Updated Lithuanian translation 2019-02-03 16:52:13 +02:00
73413ac6c0 Update Hungarian translation 2019-02-03 14:29:17 +00:00
f61c8e5e1d Fix Catalan date formatter 2019-02-02 19:42:36 +01:00
36713db990 Update Friulian translation 2019-02-02 10:19:36 +00:00
6bb7d4002f Update Catalan translation 2019-02-02 11:13:35 +01:00
aa28d487d3 Update Hungarian translation 2019-02-02 07:55:58 +00:00
a7d974481c workspace: Update a wrong comment
We showed the app icon there back then, nowadays it's a close button and
the title of the window.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/346
2019-01-31 17:36:25 +00:00
3730314dd5 workspace: Use ES6 findIndex() method for getting window index
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/346
2019-01-31 17:36:25 +00:00
6b0c8c9fe0 workspace: Rename show-close-button signal to chrome-visible
Since we no longer only show the close button but the whole window
chrome on hover, change the name of the signal.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/346
2019-01-31 17:36:25 +00:00
28a56d24ad workspace: Some style changes to match guidelines
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/346
2019-01-31 17:36:25 +00:00
5e6629e1a7 workspace: Remove some unnecessary variables and functions
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/346
2019-01-31 17:36:25 +00:00
a00b967df0 workspace: Rename some variables for clarity
Since the overlays we show on hover above the window clones are no
longer only a close button, but the window title, a border and a close
button, rename a few variables so it's easier to understand what they're
for.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/346
2019-01-31 17:36:25 +00:00
193e4ae31e workspace: Use globals for delays and animation times
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/346
2019-01-31 17:36:25 +00:00
409a27c3b8 weather: Change Weather app ID
As of 9f7f5a68d4 Weather uses
org.gnome.Weather everywhere instead of org.gnome.Weather.Application.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/379
2019-01-31 12:33:10 -05:00
ba97e8da7a magnifier: Add missing import
This was missing from commit a7bb8ee639.
2019-01-31 14:10:30 +01:00
c47e672eea a11y: Don't set WM theme
We've been using GTK to draw server-side decorations according to the
GTK theme for a long time, so no need to configure the HighContrast
theme for a setting we don't use.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/377
2019-01-31 08:29:15 +01:00
43a19739ab extensionPrefs: Improve error UI
Currently when a preference widget fails to load, we throw a raw
backtrace at the user. While that is undoubtedly useful information
for extension developers and bug reports, it is gibberish to most
users and hardly the first thing they should be exposed to.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/193
2019-01-31 00:38:19 +01:00
36f9147b21 extensionPrefs: Add blank state
We currently show a big white window in case no extensions are
installed, which clearly isn't helpful. Add a small blank state
that explains what's going on.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/193
2019-01-31 00:38:19 +01:00
8647922df9 st: Use StSettings for primary-paste setting
If middle-click happens, check whether the setting is enabled
and paste primary selection if so.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/317
2019-01-30 23:18:53 +01:00
df3068d9ca st: Use StSettings for enable-animations check
Keep a statically allocated one so all widgets will use a single
object.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/317
2019-01-30 23:18:53 +01:00
036e67049b st-texture-cache: Use GtkIconTheme separate from GTK+
Using the default icon theme just has automatic theme updates as an added
value. We can do that ourselves, and stop relying on XSettings internally.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/317
2019-01-30 23:18:53 +01:00
f02033acb7 main: Use StSettings instead of GtkSettings
Cut a middle man by listening to dconf settings directly, and stop relying
on XSettings for it.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/317
2019-01-30 23:18:53 +01:00
91d73d65c3 tweener: Use StSettings instead of GtkSettings
Cut a middle man by listening to dconf settings directly, and stop relying
on XSettings for it.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/317
2019-01-30 23:18:53 +01:00
81c4c23016 dnd: Use StSettings instead of GtkSettings
Cut a middle man by listening to dconf settings directly, and stop relying
on XSettings for it.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/317
2019-01-30 23:18:53 +01:00
fef2bac8ab st: Add StSettings object
This is a GtkSettings lookalike, so the shell can fetch the relevant
settings.
2019-01-30 23:18:53 +01:00
c59c5eb893 st: Add StDirectionType enum
In order to replace GTK+'s GtkDirectionType. It's bit-compatible with it,
too. All callers have been updated to use it.

This is a purely accessory change in terms of X11 Display usage cleanup,
but helps see better what is left.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/317
2019-01-30 22:50:01 +01:00
a977c1388a st: Add StPolicyType enum
In order to replace GTK+'s GtkPolicyType. It's bit-compatible with it, too.
All callers have been updated to use it.

This is a purely accessory change in terms of X11 Display usage cleanup,
but helps see better what is left.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/317
2019-01-30 22:50:01 +01:00
0f799ae313 environment: No need to set Gdk version
The Gdk module is no longer used.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/317
2019-01-30 22:50:01 +01:00
23c3f3fdea overview: Do not warp pointer to fake crossing event
This is actually papering over bugs in toolkits. On X11 the Xserver will
send crossing events when the stage input shape changes. As those go
end up ignored in GTK+, this warp call aims (and randomly manages) to send
a motion event that wouldn't go unlistened by the drag source window (the
one holding the grab).

This bug actually manifests in other ways, eg. by changing the window
beneath the pointer with alt-tab while DnDing. This should be fixed
altogether in the client side.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/317
2019-01-30 22:50:01 +01:00
82c7090e9e modalDialog: Do not sync display here
This gdk_display_sync() call was added in commit a40daa3c22 so the alt-f2
dialog is able to spawn commands that trigger grabs on startup (eg. xmag/
xkill).

This seems worthwhile to do only on the X11 backend, and handling it in
mutter backend code seems cleaner.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/317
2019-01-30 22:50:01 +01:00
0fdfebdb67 shell: Drop some unused headers and Gdk variables
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/317
2019-01-30 22:50:01 +01:00
208c551787 js: Drop unused Gdk/Gtk imports
There's nothing from those modules used in those JS files.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/317
2019-01-30 22:50:01 +01:00
b10606e884 keyboard: Drop GDK API usage
Use the misnamed but equivalent Clutter function.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/317
2019-01-30 22:50:01 +01:00
f4a64f77f2 util: Use (thread-safe) uselocale()
Our helper method to translate a string according to the LC_TIME
setting uses the no-thread-safe setlocale(). While that's not an
issue in practice given that all JS code shares a single thread,
I was pointed to a better alternative when adopting the same
handling in gnome-desktop's wallclock[0].

[0] https://gitlab.gnome.org/GNOME/gnome-desktop/merge_requests/17

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/292
2019-01-30 20:35:04 +01:00
e92477a752 screenShield: Show detailed notification data if notifications hint it
Allow notifications to set a x-gnome-privacy-scope hint, with values in
['system', 'user']. If all the notifications in a particular source hint
that their privacy scope is ‘system’, don’t hide the notification
details on the lock screen.

This is aimed at fixing the particular case of power notifications: they
contain information which is not private to the user (it relates to the
system: battery state or AC state, which is obvious to anyone who can
see the machine), so hiding the details of a power management
notification when the screen is locked is pointless.

Signed-off-by: Philip Withnall <withnall@endlessm.com>

https://gitlab.gnome.org/GNOME/gnome-shell/issues/726
2019-01-30 19:14:40 +00:00
37e0a73c8f iconGrid: Remove unreachable code
Throwing an exception already aborts a function, so there's no need
for a return statement in that case.

Spotted by eslint.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/375
2019-01-30 16:13:17 +00:00
4f76e05058 keyboard: Fix undefined variable in fall-through message
Spotted by eslint.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/375
2019-01-30 16:13:17 +00:00
3134222d27 keyboard: Add back constructor parameter
This was accidentally dropped in commit bacfdbbb03.

Spotted by eslint.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/375
2019-01-30 16:13:17 +00:00
a9ed128dce ibusCandidatePopup: Clarify assignment in condition
Most often it is a bug if the condition part of a for-loop contains the
assignment operator rather than the comparison one, so tools rightfully
emit a warning.

Clarify that the assignment is intentional in this case by adding
parentheses.

Spotted by eslint.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/375
2019-01-30 16:13:16 +00:00
c264cc4131 objectManager: Fix undefined variable
Spotted by eslint.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/375
2019-01-30 16:13:16 +00:00
a7943ff934 iconGrid: Fix nonsense condition
Just like the "in" operator in the previous patch, "instanceof" has
a lower precedence than negation, resulting in the nonsense condition
of "true instanceof BaseIcon".

Add parentheses to get the intended behavior.

Spotted by eslint.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/375
2019-01-30 16:13:16 +00:00
c353914dd0 appFavorites: Fix nonsense condition
The "in" operator has a lower precedence than negation, so we are
actually testing whether the favorites map contains "false".

Add parentheses to get the intended behavior.

Spotted by eslint.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/375
2019-01-30 16:13:16 +00:00
91319e3963 networkAgent: Fix mobile broadband notifications
Currently their body message is assigned to an undefined variable
that isn't used for anything later.

Spotted by eslint.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/375
2019-01-30 16:13:16 +00:00
dc4ff941bd networkAgent: Fix showing the WPS message
The message was introduced in commit dfa0750ffd, but added to a
non-existent container, whoops.

Spotted by eslint.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/375
2019-01-30 16:13:16 +00:00
b597d5faf0 shell-global: Use MetaLaunchContext instead of GdkLaunchContext
Is functionally the same, without requiring the MetaX11Display.
2019-01-30 13:11:29 +01:00
f6da36ad3a workspaceThumbnail: Clean up porthole/workarea setting and updating
Instead of unnecessarily updating the porthole on every call to the
layout vfuncs and returning widths and heights of 0 when the overview is
hidden, only update it on actual workarea changes.

Also use the stage size for the porthole in case no monitor is available
to make sure we don't try to allocate a 0-sized box.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/892, https://gitlab.gnome.org/GNOME/gnome-shell/issues/517

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/343
2019-01-30 10:07:14 +01:00
5f4e2749a2 overview: Remove unneeded check if primary monitor exists
This check is no longer needed because we're using the stage size
instead of the monitor size here.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/374
2019-01-30 00:33:46 +00:00
69b1fb699f app: Replace ClutterTexture by ClutterActor
It apparently uses no ClutterTexture specifics, and instead
only tries to match what StTextureCache used to return.

Since StTextureCache now returns ClutterActor, also use a
ClutterActor on ShellApp.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/373
2019-01-29 17:11:13 -02:00
259f90bbf6 texture-cache: Fix documentation error
It now returns a ClutterActor, not a ClutterTexture.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/371
2019-01-29 16:38:04 -02:00
8665045326 st: Check for ClutterImage when creating shadow pipelines
_st_create_shadow_pipeline_from_actor creates shadow pipelines
from actors. This function special-cases ClutterTexture as a
small performance improvement, since we can have access to the
CoglTexture easily with it. However, recent commits removed all
usage of ClutterTexture from GNOME Shell, rendering this optimization
useless. Instead, actors now may have a ClutterImage set as
their content, that can be used instead.

Replace the check for ClutterTexture with a check for ClutterImage,
and use the texture of the image when it is available.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/371
2019-01-29 16:38:04 -02:00
a7bb8ee639 magnifier: Use a ClutterContent to render mouse sprite
The Magnifier class uses a small subtree of actors to track the
current cursor's position and sprite. Specifically, it uses the
deprecated ClutterTexture to paint the cursor sprites.

Add a new, very simple ClutterContent implementation to track the
cursor sprite, and replace the ClutterTexture by a ClutterActor.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/371
2019-01-29 16:31:57 -02:00
8f732e4f45 messageTray: Disconnect signals when resetting notification
Just like we did for the parent class in commit b57832716a, we should
disconnect any notification signals when the notification is reset
to null to avoid warnings later.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/942
2019-01-29 16:49:48 +00:00
95a31b0c31 st: Use ClutterKeymap to detect caps lock state changes
This drops usage of Gtk/X11, replacing it with code that is dependent
of the Clutter backend in use. Another positive side effect is that
the keymap state will now be correct on wayland, since there were no
guarantees that X11 key state would reflect the current reality.

https://bugzilla.gnome.org/show_bug.cgi?id=762881
2019-01-29 16:03:22 +00:00
36b9f45368 ci: Add minimal continuous integration
Building gnome-shell is tricky due to the tight coupling with mutter,
but until we figure out the best way forward, we can at least perform
some basic syntax checking on the javascript bits.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/367
2019-01-28 17:29:35 +00:00
46575804cc perf: Stop using legacy generator functions
This was a non-standard Mozilla extension that is no longer supported.
Simply switch to the standardized generator syntax to fix.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/367
2019-01-28 17:29:35 +00:00
86a00b6872 shell-global: Make saving of persistent state asynchronous
This is an expensive operation that is best avoided in the main loop. Given
the call doesn't care much about returning error or status, it can just
be made async within.

Every operation on a given file will be destructive wrt previous
operations on the same file, so we just cancel any pending operation on
it before batching the current one.

Closes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/815
2019-01-28 14:56:08 +00:00
23d6d13d80 st-shadow: Add a CoglFramebuffer argument
The last patch in the series, this one adapts StShadowHelper
to received a CoglFramebuffer. This is where we first touch
JavaScript with Cogl types, and as such, it depends on the
latest Mutter. Earlier versions of Mutter didn't have its
Mutter-Clutter GIR to generate types for various Cogl types.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/283
2019-01-28 12:35:54 -02:00
09addfc87c st-private: Receive a CoglFramebuffer
Same case of the previous patch; _st_paint_shadow_with_opacity()
uses cogl_get_draw_framebuffer(), and this patch makes it receive
a CoglFramebuffer as a parameter instead.

The cautious reader might notice that this commit apparently goes
against the long-term goal, for it introduces more instances of
cogl_get_draw_framebuffer(). This is not wrong, but these introduced
ones will be removed later on, when ClutterActor.paint() receives
a CoglFramebuffer as a parameter instead.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/283
2019-01-28 12:35:51 -02:00
a2f27a9409 theme-node-transition: Receive a CoglFramebuffer
This is in preparation for a future where only explicit frambuffer
APIs are available, i.e., cogl_get_draw_framebuffer() does not
exist.

There is absolutely no functional changes in this patch (nor the
following ones in this series), only rearrangements so that various
functions receive a CoglFramebuffer instead of using the draw
framebuffer.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/283
2019-01-28 12:35:41 -02:00
412003efbf Updated Spanish translation 2019-01-28 13:08:55 +01:00
582b3aacf4 dnd: Fix syntax error which led into g-s not starting anymore
With the recent port to JS6 classes, the trailing
comma after functions in the syntax of classes has
been removed.
However commit c2961f21 accidentally reintroduces
one trailing comma after a newly created function,
leading into g-s throwing an exception and not
starting anymore.

Therefore, remove this trailing comma to solve
this problem.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/366
2019-01-28 01:44:07 +01:00
1af0b54c1e Update Punjabi translation 2019-01-27 22:17:11 +00:00
74ba2e6634 Update Hungarian translation 2019-01-27 14:49:37 +00:00
78608a5080 dnd: Prevent simultaneous DnD operations from happening
Besides the device grab on the drag device, also set up a captured-event
handler to catch other devices (except the keyboard) while the DnD
operation is ongoing. This makes DnD operations exclusive to others.

Also, disallow it in less aggressive ways if maybeStartDrag() gets called
while there is a current draggable.

This might definitely be nicer (eg. having other grabbed devices emit
leave/end events), but can't be done without major surgery to Clutter.
2019-01-26 23:38:50 +00:00
7a86637f8d dnd: Avoid breaking drag state on cancellation
In the case where the draggable has an actor of its own, state could be
left broken when dragging on a place that would not accept the DnD op.
After button release, drag state is set to "cancelled" and the animation
begins. After the animation is finished, the drag actor would be destroyed
before disconnecting from its destroy handler.

Within the destroy handler, the grab would be undone but drag state would
be left on "cancelled" state for subsequent operations. This results in
DnD oddities and stuck grabs.

In order to fix this, double check in the actor destroy handler that we
are actually dragging before setting the "cancelled" state.

Closes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/540
2019-01-26 23:38:50 +00:00
c2961f2152 dnd: Get dragging device from the triggering events
Instead of fetching the CLUTTER_POINTER_DEVICE device. It will
be wrong if drags get initiated from tablet pointers. This allows
for DnD operations to be started, moved, and more importantly
finished through tablet devices.

Closes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/540
2019-01-26 23:38:50 +00:00
6845c6f958 Update Galician translation 2019-01-26 23:18:10 +00:00
794a056819 appDisplay: Use GAppInfo list from ShellAppSystem
It is now cached there, so the number of g_app_info_get_all() calls
is reduced to one per change.
2019-01-26 22:55:31 +01:00
69ad75cf48 shell-app-system: Cache GAppInfos around
This was called here just to end up emitting ::installed-changed,
which would trigger other g_app_info_get_all() calls. Cache it here
so it may be reused later on.
2019-01-26 22:55:31 +01:00
3db52155dd appDisplay: Reduce g_app_info_get_all() calls
Whenever the AllView needs (re)populating, we used to do one general
g_app_info_get_all() to get all GAppInfo, plus one per app folder in order
to check the ones that fall within that category. This calls results in a
fair amount of I/O blocking the main loop.

In order to ease this, keep the GAppInfo list around in AllView, and make
the AppFolders use it when figuring out the contained apps. Since reloading
the AllView results in AppFolders regenerated from scratch, the app info
list is ensured to be up-to-date for any later change within the AppFolder
(eg. through the GSettings key changing).

As the list was already filtered in the first place, we can also remove
the try{}catch() in AppFolder in order to discard desktop files with
invalid encoding.

Related: https://gitlab.gnome.org/GNOME/gnome-shell/issues/832
2019-01-26 16:40:48 +01:00
38805ae662 Updated Slovenian translation 2019-01-25 21:29:15 +01:00
dfa0750ffd networkAgent: Advise the user to push a WPS button on their router
When connecting to a Wi-Fi router that supports the WPS button method
(PBC, push button connection) the user can simply press the button on
the router. Show an explanation in the PSK prompt when this is
possible.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/329
2019-01-25 15:25:26 +01:00
d80e7e0118 lookingGlass: Don't import Lang by default
With arrow functions, Function.prototype.bind() and ES6 classes, the
Lang module is rarely needed nowadays.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/361
2019-01-25 14:02:44 +00:00
b7e2718bdc docs: Update HACKING
We no longer use Lang.Class(), so update the guidelines accordingly.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/361
2019-01-25 14:02:44 +00:00
e68dfed1f7 cleanup: Port GObject classes to JS6 classes
GJS added API for defining GObject classes with ES6 class syntax
last cycle, use it to port the remaining Lang.Class classes to
the new syntax.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/361
2019-01-25 14:02:44 +00:00
bacfdbbb03 cleanup: Port non-GObject classes to JS6 classes
ES6 finally adds standard class syntax to the language, so we can
replace our custom Lang.Class framework with the new syntax. Any
classes that inherit from GObject will need special treatment,
so limit the port to regular javascript classes for now.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/361
2019-01-25 14:02:44 +00:00
99ce3deeb0 st-button: Handle touch-cancel events
Handling those events is neccessary if a touch event that pressed down a
button turns out to be a gesture. In this case the button should be
released without emitting the clicked signal.
2019-01-25 10:31:41 +00:00
d75a3484d6 windowManager: detect change to a non-existent WS
When using dynamic workspaces, it is possible to try to change to a
non-existent one if the user defines hotkeys for changing to desktop
1, 2, 3... This case is not detected, and gnome shell shows an error:

JS ERROR: TypeError: workspace is null
actionMoveWorkspace@resource:///org/gnome/shell/ui/windowManager.js:2130:13
wrapper@resource:///org/gnome/gjs/modules/_legacy.js:82:22
_showWorkspaceSwitcher@resource:///org/gnome/shell/ui/windowManager.js:2104:13
wrapper@resource:///org/gnome/gjs/modules/_legacy.js:82:22

This patch adds a check before trying to change the workspace, to avoid
switching to a non-existent one.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/365
2019-01-24 23:59:23 +01:00
3dcb593a71 texture-cache: Simplify function with g_autoptr
st_texture_cache_reset_texture() is slightly easier to
read and follow by using g_autoptr, so use that.
2019-01-24 16:23:58 -02:00
1847a4f4cc texture-cache: Avoid creating unnecessary ClutterImages
After loading the GdkPixbuf, StTextureCache unconditionally
creates a ClutterImage and, if it's not in the cache, add
it to the cache. That's a waste of resources when the image
is already committed to the texture cache.

Fix that by reusing the ClutterImage of the cache if it is
already there; otherwise, create a new ClutterImage as we
were previously doing.
2019-01-24 16:23:58 -02:00
deec0bf255 texture-cache: Replace ClutterTexture by ClutterImage
ClutterTexture is a deprecated class that is simultaneously
an actor, and the content of the actor. Clutter's new model
is to separate painting (via ClutterContent) from actors.

Currently, StTextureCache relies on ClutterTexture to store
the loaded textures. This not only does not match the latest
practices of Clutter, but also generates various compile-time
warnings.

Port StTextureCache to store ClutterImages instead of storing
ClutterTextures. ClutterImage exposes the internal CoglTexture,
so no helpers are needed to match the current StTextureCache
API. Aspect ratio was dropped, but from my testing, it doesn't
change anything.
2019-01-24 16:23:58 -02:00
8bb9eb0fc9 keyboard: Disconnect from input source manager when destroying indicator
When an InputSourceIndicator is destroyed, the InputSourceManager it was
connected to could (and probably will) outlive it (since the manager is
a singleton). If the InputSourceManager emits any subsequent signals,
the callbacks from the finalised InputSourceIndicator could be invoked,
and will reference finalised objects.

This can be triggered by running `pkexec true` from a gnome-terminal
window, then calling `pkill pkexec` from another terminal (on a
different VT or via SSH). This causes the dialogue to be cancelled by
polkitd.

Signed-off-by: Philip Withnall <withnall@endlessm.com>

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/357
2019-01-24 14:48:48 +00:00
21de3c327b polkitAgent: Disconnect from user signals when closing dialogue
Otherwise the user object could outlive the dialogue, emit a subsequent
signal, and the callback from that signal could reference finalised
objects/widgets from the dialogue. The likely mechanism for the user
outliving the dialogue is caching of user objects within
libaccountsservice.

This can be triggered by running `pkexec true` from a gnome-terminal
window, then calling `pkill pkexec` from another terminal (on a
different VT or via SSH). This causes the dialogue to be cancelled by
polkitd.

Signed-off-by: Philip Withnall <withnall@endlessm.com>

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/357
2019-01-24 14:48:48 +00:00
081d94e0f6 polkitAgent: Destroy session from dialogue closed handler
Rather than explicitly destroying the session after calling close(),
destroy it from the `closed` signal handler.

This also means we can make the method internal.

Signed-off-by: Philip Withnall <withnall@endlessm.com>

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/357
2019-01-24 14:48:48 +00:00
ddd1825162 polkitAgent: Drop close() override in favour of closed signal
In case there are any internal ways the dialogue can close itself
without calling its own close() method, it’s probably better to do all
our cleanup on a handler for the `closed` signal instead.

This should introduce no functional changes except ensuring the
polkitAgent cleanup is always done.

Signed-off-by: Philip Withnall <withnall@endlessm.com>

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/357
2019-01-24 14:48:48 +00:00
5f223e0bd8 polkitAgent: Disconnect session signal handlers when destroying session
Otherwise the session could outlive the dialogue, emit a subsequent
signal, and its callback would reference finalised objects/widgets from
the dialogue. The PolkitSession object is implemented by
libpolkit-gobject, so we have no guarantees about its reference counting
— the session object could keep itself alive in another thread, or be a
singleton. In all likelihood, the session hangs around for longer than
the dialogue due to differences in when the two objects are garbage
collected.

This can be triggered by running `pkexec true` from a gnome-terminal
window, then calling `pkill pkexec` from another terminal (on a
different VT or via SSH). This causes the dialogue to be cancelled by
polkitd.

Signed-off-by: Philip Withnall <withnall@endlessm.com>

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/357
2019-01-24 14:48:48 +00:00
809d92129b search: Initialise searchInProgress when search providers are registered
This avoids the following warning sometimes happening later:

JS WARNING: [resource:///org/gnome/shell/ui/search.js 701]: reference to undefined property "searchInProgress"

Signed-off-by: Philip Withnall <withnall@endlessm.com>

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/357
2019-01-24 14:48:48 +00:00
8840608a25 Update Catalan translation 2019-01-24 11:31:05 +01:00
edbb204332 animation: Disable spinner animations when actor is destroyed
There's nothing to animate anymore, just a source for warnings when
trying to access a destroyed object.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/362
2019-01-24 00:20:58 +01:00
9dc3b73ef9 calendar: Rename "Clear All" button
While it hasn't really cleared everything previously (media notifications),
it does less so now. Update the button label to reflect that.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/262
2019-01-22 21:35:52 +00:00
a7d618915c calendar: Remove ability to hide events
The functionality is no longer exposed, so remove it altogether.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/262
2019-01-22 21:35:52 +00:00
3e3da8e2f8 calendar: Don't allow event messages to be closed
The built-in calendar isn't meant to replace a full-fledged calendar
app, which is why clearing event messages only hides the event in
gnome-shell rather than deleting the actual event. This has turned out
to not be overly useful and often confusing - it creates a discrepancy
with visible events in apps, isn't revertible in a non-obscure fashion
and non-obviously limited to the current date.

As we are considering moving events out of the message list and back to
the calendar, it looks like a good time to remove that ability and keep
notifications as the only removable messages.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/262
2019-01-22 21:35:52 +00:00
a6763e7731 messageTray: Chain up in NotificationPolicy constructor
We currently deliberately avoid chaining up in derived policy
constructors to not override properties with their defaults.
That's a neat trick that will stop working when porting to ES6
classes, as chaining up is necessary to actually initialize the
object there (including "this").

Address this by turning all properties into (overridable) getters
that are backed by private properties by default.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/350
2019-01-22 21:33:46 +00:00
8f15193b40 messageTray: Split out policy creation
The _createPolicy() method of a subclass usually depends on some
constructor parameters that need to be set before chaining up to
the parent. This works fine with Lang.Class, but will break with
ES6 classes, as "this" is only initialized after chaining up.

Prepare for this by not creating the policy in the constructor,
but when it is first accessed.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/350
2019-01-22 21:33:46 +00:00
467b7c1bca lookingGlass: Stop using eval()
Its use is not only strongly discouraged[0], we also rely on it injecting
variables into the global scope to get command-line-like behavior. That
behavior is incompatible with strict mode[1], and in extension with ES6
classes (which imply strict mode).

So to prepare for porting to ES6 classes, replace it with a somewhat less
evil construct that is compatible with strict mode.

[0] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval#Do_not_ever_use_eval!
[1]
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode#Simplifying_variable_uses

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/350
2019-01-22 21:33:46 +00:00
97963a1ca8 docs: Remove obsolete Lang references
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/350
2019-01-22 21:33:46 +00:00
2fc1f1adbe cleanup: Remove obsolete Lang imports
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/350
2019-01-22 21:33:46 +00:00
200f4908d5 Update Afrikaans translation 2019-01-20 23:04:31 +00:00
1f864c905d thunderbolt: only try to enroll if we are allowed
Check via Polkit if the current user is actually allowed to enroll
devices before trying to do so. If not, show a notification that
explains that a system administrator needs to authorize the device.
Clicking on the notification will guide the user to the thunderbolt
control center panel. Before this patch, when the current user was
not allowed to enroll a device a polkit dialog would pop up which
is confusing because it did not contain any information why it was
shown. This patch implements the behavior as designed (see [1],
section "Multi-user environments").

[1] https://wiki.gnome.org/Design/Whiteboards/ThunderboltAccess
2019-01-18 22:10:23 +01:00
df77fb6793 media section: Change size of the fallback cover
Fallback cover used to be larger than the non-fallback one,
making the media controls look inconsistent.
2019-01-18 21:36:10 +03:00
3fa3889fa5 Update French translation
(cherry picked from commit ee97f73521)
2019-01-17 16:58:43 +00:00
4b28b90e0f notificationDaemon.js: Fix a typo (missing ')')
Introduced in e0a992af73 it was preventing gnome-shell from starting.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/915
2019-01-17 11:55:04 +08:00
e0a992af73 notificationDaemon: Fix warning
Since commit 33b8537bf5, we unconditionally access the 'image-path'
hint, resulting in a gjs warning if the hint is not defined.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/309
2019-01-16 18:57:04 +01:00
7c4e43c84f Remove deprecated CoglHandle
Prefer something a bit more type-safe instead and in the meantime use
the newly available `cogl_clear_object` to simplify some code a bit.
2019-01-16 17:54:29 +00:00
b57832716a calendar: Disconnect signals when resetting notification
Since commit 5fb8d4f730, a NotificationMessage's notification property
is reset to null when the notification is destroyed. However at that
point we still have connected signal handlers around that we'll try
to disconnect later.

Avoid the warnings by disconnecting and resetting the handler IDs at
the same time as the notification.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/308
2019-01-16 17:46:09 +00:00
945a019974 animation: Optionally animate spinner start/stop
In contrast to generic animated icons, it is reasonable to expect
spinners to be invisible while inactive. Implement that behavior
in the new Spinner class and optionally animate the transitions.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/316
2019-01-16 17:44:42 +00:00
22e21ad7d1 animation: Add dedicated Spinner class
We use AnimatedIcon with the same resource all over the place, cut
down on the duplication by providing a dedicated class.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/316
2019-01-16 17:44:42 +00:00
ae48f8bda9 inputMethod: Delete the enabled member since it's not used
When `ibus restart` runs, InputMethod.enabled is changed to false
and no longer enable ibus but 'enabled' and 'disabled' signals
are not used in the current IBus clients and it's good to delete
the member simply.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/295
2019-01-16 17:33:58 +00:00
62abf3edc7 audioDeviceSelection: Only include settings button when allowed
https://gitlab.gnome.org/GNOME/gnome-shell/issues/909
2019-01-16 00:30:46 +00:00
f8ce47c24d keyboard: Use addSettingsItem() in language menu
If the session mode doesn't allow access to Settings, the language
menu should respect that and not expose the "Region & Languages"
panel. Using the dedicated method instead of manually constructing
the menu item takes care of that and makes for less code.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/780
2019-01-16 00:29:23 +00:00
ddb3a5c625 Add Iagno to appFavorites 2019-01-15 15:31:13 +00:00
c6d2bc4c57 Update Esperanto translation 2019-01-14 21:48:02 +00:00
e3a0b6d4ee Updated Spanish translation 2019-01-14 15:43:41 +01:00
279 changed files with 51363 additions and 31662 deletions

1
.gitignore vendored
View File

@ -80,3 +80,4 @@ tests/run-test.sh
*~
*.patch
*.sw?
.vscode

86
.gitlab-ci.yml Normal file
View File

@ -0,0 +1,86 @@
stages:
- review
- source_check
- build
- test
variables:
JS_LOG: "js-report.txt"
POT_LOG: "pot-update.txt"
.only_default: &only_default
only:
- branches
- tags
- merge_requests
check_commit_log:
image: registry.gitlab.gnome.org/gnome/mutter/master:v1
stage: review
script:
- ./.gitlab-ci/check-commit-log.sh
only:
- merge_requests
js_check:
image: registry.gitlab.gnome.org/gnome/gnome-shell/extension-ci:v1
stage: source_check
script:
- find js -name '*.js' -exec js60 -c -s '{}' ';' 2>&1 | tee $JS_LOG
- (! grep -q . $JS_LOG)
<<: *only_default
only:
changes:
- js/**/*
artifacts:
paths:
- ${JS_LOG}
when: on_failure
build:
image: registry.gitlab.gnome.org/gnome/gnome-shell/master:v1
stage: build
before_script:
- .gitlab-ci/checkout-mutter.sh
- meson mutter mutter/build --prefix=/usr -Dtests=false
- ninja -C mutter/build install
script:
- meson . build -Dbuiltype=debugoptimized
- ninja -C build
- ninja -C build install
<<: *only_default
artifacts:
expire_in: 1 day
paths:
- mutter
- build
test:
image: registry.gitlab.gnome.org/gnome/gnome-shell/master:v1
stage: test
before_script:
- ninja -C mutter/build install
script:
- xvfb-run meson test -C build --no-rebuild
<<: *only_default
artifacts:
expire_in: 1 day
paths:
- build/meson-logs/testlog.txt
when: on_failure
test-pot:
image: registry.gitlab.gnome.org/gnome/gnome-shell/master:v1
stage: test
before_script:
- ninja -C mutter/build install
script:
# Check that pot files are generated correctly:
# https://savannah.gnu.org/bugs/?50920#comment5
- ninja -C build gnome-shell-pot 2>&1 | awk '
BEGIN { start=0; }
start==1 { print $0; }
/gnome-shell-pot/ { start=1; }
' | tee $POT_LOG
- (! grep -q . $POT_LOG)
<<: *only_default

19
.gitlab-ci/Dockerfile Normal file
View File

@ -0,0 +1,19 @@
FROM registry.gitlab.gnome.org/gnome/mutter/master:v1
RUN dnf -y update && dnf -y upgrade && \
dnf install -y 'dnf-command(copr)' && \
dnf copr enable -y fmuellner/gnome-shell-ci && \
dnf builddep -y gnome-shell --setopt=install_weak_deps=False && \
# bt only exports HAVE_BLUETOOTH to js, rest are outdated build-requires
dnf remove -y gnome-bluetooth-libs-devel dbus-glib-devel \
upower-devel python3-devel && \
# We'll build mutter ourselves
dnf remove -y --noautoremove mutter mutter-devel && \
# Needed for tests
dnf install -y '*/xvfb-run' gdm-lib accountsservice-libs && \
dnf clean all && \
rm -rf /var/cache/dnf

View File

@ -0,0 +1,18 @@
FROM registry.fedoraproject.org/fedora:latest
RUN dnf -y update && dnf -y upgrade && \
dnf install -y 'dnf-command(copr)' && \
# For syntax checks with `find . -name '*.js' -exec js60 -c -s '{}' ';'`
dnf install -y findutils mozjs60-devel && \
# For static analysis with eslint
dnf install -y nodejs && \
npm install -g eslint && \
# Shameless plug for my own tooling; useful for generating zip
dnf copr enable -y fmuellner/gnome-shell-ci && \
dnf install -y gnome-extensions-tool meson && \
dnf clean all && \
rm -rf /var/cache/dnf

31
.gitlab-ci/check-commit-log.sh Executable file
View File

@ -0,0 +1,31 @@
#!/usr/bin/env bash
if [ -z "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" ]; then
echo Cannot review non-merge request
exit 1
fi
git fetch $CI_MERGE_REQUEST_PROJECT_URL.git $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
branch_point=$(git merge-base HEAD FETCH_HEAD)
commits=$(git log --format='format:%H' $branch_point..$CI_COMMIT_SHA)
if [ -z "$commits" ]; then
echo Commit range empty
exit 1
fi
function commit_message_has_url() {
commit=$1
commit_message=$(git show -s --format='format:%b' $commit)
echo "$commit_message" | grep -qe "\($CI_MERGE_REQUEST_PROJECT_URL/\(issues\|merge_requests\)/[0-9]\+\|https://bugzilla.gnome.org/show_bug.cgi?id=[0-9]\+\)"
return $?
}
for commit in $commits; do
if ! commit_message_has_url $commit; then
echo "Missing merge request or issue URL on commit $(echo $commit | cut -c -8)"
exit 1
fi
done

31
.gitlab-ci/checkout-mutter.sh Executable file
View File

@ -0,0 +1,31 @@
#!/usr/bin/bash
shell_branch=$(git describe --contains --all HEAD)
mutter_target=
git clone https://gitlab.gnome.org/GNOME/mutter.git
if [ $? -ne 0 ]; then
echo Checkout failed
exit 1
fi
cd mutter
if [ "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" ]; then
merge_request_remote=${CI_MERGE_REQUEST_SOURCE_PROJECT_URL//gnome-shell/mutter}
merge_request_branch=$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME
echo Looking for $merge_request_branch on remote ...
if git fetch $merge_request_remote $merge_request_branch >/dev/null 2>&1; then
mutter_target=FETCH_HEAD
fi
fi
if [ -z "$mutter_target" ]; then
mutter_target=$(git branch -r -l $shell_branch)
mutter_target=${mutter_target:-origin/master}
echo Using $mutter_target instead
fi
git checkout $mutter_target

View File

@ -1,31 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>gnome-shell</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.wst.jsdt.core.javascriptValidator</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.linuxtools.cdt.autotools.genmakebuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
<nature>org.eclipse.linuxtools.cdt.autotools.autotoolsNature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
<nature>org.eclipse.cdt.core.cnature</nature>
<nature>org.eclipse.wst.jsdt.core.jsNature</nature>
</natures>
</projectDescription>

View File

@ -1,148 +0,0 @@
#Fri Nov 28 14:33:30 EST 2008
eclipse.preferences.version=1
org.eclipse.cdt.core.formatter.alignment_for_arguments_in_method_invocation=16
org.eclipse.cdt.core.formatter.alignment_for_base_clause_in_type_declaration=80
org.eclipse.cdt.core.formatter.alignment_for_compact_if=0
org.eclipse.cdt.core.formatter.alignment_for_conditional_expression=80
org.eclipse.cdt.core.formatter.alignment_for_declarator_list=16
org.eclipse.cdt.core.formatter.alignment_for_enumerator_list=48
org.eclipse.cdt.core.formatter.alignment_for_expression_list=0
org.eclipse.cdt.core.formatter.alignment_for_expressions_in_array_initializer=16
org.eclipse.cdt.core.formatter.alignment_for_parameters_in_method_declaration=16
org.eclipse.cdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
org.eclipse.cdt.core.formatter.brace_position_for_array_initializer=next_line_shifted
org.eclipse.cdt.core.formatter.brace_position_for_block=next_line_shifted
org.eclipse.cdt.core.formatter.brace_position_for_block_in_case=next_line_shifted
org.eclipse.cdt.core.formatter.brace_position_for_method_declaration=next_line
org.eclipse.cdt.core.formatter.brace_position_for_namespace_declaration=next_line
org.eclipse.cdt.core.formatter.brace_position_for_switch=next_line_shifted
org.eclipse.cdt.core.formatter.brace_position_for_type_declaration=next_line
org.eclipse.cdt.core.formatter.compact_else_if=true
org.eclipse.cdt.core.formatter.continuation_indentation=2
org.eclipse.cdt.core.formatter.continuation_indentation_for_array_initializer=2
org.eclipse.cdt.core.formatter.format_guardian_clause_on_one_line=false
org.eclipse.cdt.core.formatter.indent_access_specifier_compare_to_type_header=false
org.eclipse.cdt.core.formatter.indent_body_declarations_compare_to_access_specifier=true
org.eclipse.cdt.core.formatter.indent_body_declarations_compare_to_namespace_header=true
org.eclipse.cdt.core.formatter.indent_breaks_compare_to_cases=true
org.eclipse.cdt.core.formatter.indent_declaration_compare_to_template_header=true
org.eclipse.cdt.core.formatter.indent_empty_lines=false
org.eclipse.cdt.core.formatter.indent_statements_compare_to_block=true
org.eclipse.cdt.core.formatter.indent_statements_compare_to_body=true
org.eclipse.cdt.core.formatter.indent_switchstatements_compare_to_cases=true
org.eclipse.cdt.core.formatter.indent_switchstatements_compare_to_switch=false
org.eclipse.cdt.core.formatter.indentation.size=8
org.eclipse.cdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
org.eclipse.cdt.core.formatter.insert_new_line_after_template_declaration=insert
org.eclipse.cdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
org.eclipse.cdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert
org.eclipse.cdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
org.eclipse.cdt.core.formatter.insert_new_line_before_else_in_if_statement=insert
org.eclipse.cdt.core.formatter.insert_new_line_before_identifier_in_function_declaration=insert
org.eclipse.cdt.core.formatter.insert_new_line_before_while_in_do_statement=insert
org.eclipse.cdt.core.formatter.insert_new_line_in_empty_block=insert
org.eclipse.cdt.core.formatter.insert_space_after_assignment_operator=insert
org.eclipse.cdt.core.formatter.insert_space_after_binary_operator=insert
org.eclipse.cdt.core.formatter.insert_space_after_closing_angle_bracket_in_template_arguments=insert
org.eclipse.cdt.core.formatter.insert_space_after_closing_angle_bracket_in_template_parameters=insert
org.eclipse.cdt.core.formatter.insert_space_after_closing_brace_in_block=insert
org.eclipse.cdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
org.eclipse.cdt.core.formatter.insert_space_after_colon_in_base_clause=insert
org.eclipse.cdt.core.formatter.insert_space_after_colon_in_case=insert
org.eclipse.cdt.core.formatter.insert_space_after_colon_in_conditional=insert
org.eclipse.cdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
org.eclipse.cdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
org.eclipse.cdt.core.formatter.insert_space_after_comma_in_base_types=insert
org.eclipse.cdt.core.formatter.insert_space_after_comma_in_declarator_list=insert
org.eclipse.cdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
org.eclipse.cdt.core.formatter.insert_space_after_comma_in_expression_list=insert
org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
org.eclipse.cdt.core.formatter.insert_space_after_comma_in_template_arguments=insert
org.eclipse.cdt.core.formatter.insert_space_after_comma_in_template_parameters=insert
org.eclipse.cdt.core.formatter.insert_space_after_opening_angle_bracket_in_template_arguments=do not insert
org.eclipse.cdt.core.formatter.insert_space_after_opening_angle_bracket_in_template_parameters=do not insert
org.eclipse.cdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
org.eclipse.cdt.core.formatter.insert_space_after_opening_bracket=do not insert
org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
org.eclipse.cdt.core.formatter.insert_space_after_postfix_operator=do not insert
org.eclipse.cdt.core.formatter.insert_space_after_prefix_operator=do not insert
org.eclipse.cdt.core.formatter.insert_space_after_question_in_conditional=insert
org.eclipse.cdt.core.formatter.insert_space_after_semicolon_in_for=insert
org.eclipse.cdt.core.formatter.insert_space_after_unary_operator=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_assignment_operator=insert
org.eclipse.cdt.core.formatter.insert_space_before_binary_operator=insert
org.eclipse.cdt.core.formatter.insert_space_before_closing_angle_bracket_in_template_arguments=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_closing_angle_bracket_in_template_parameters=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
org.eclipse.cdt.core.formatter.insert_space_before_closing_bracket=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_colon_in_base_clause=insert
org.eclipse.cdt.core.formatter.insert_space_before_colon_in_case=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_colon_in_conditional=insert
org.eclipse.cdt.core.formatter.insert_space_before_colon_in_default=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_comma_in_base_types=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_comma_in_declarator_list=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_comma_in_expression_list=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_comma_in_template_arguments=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_comma_in_template_parameters=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_angle_bracket_in_template_arguments=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_angle_bracket_in_template_parameters=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_block=insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_namespace_declaration=insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_bracket=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_for=insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_if=insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_while=insert
org.eclipse.cdt.core.formatter.insert_space_before_postfix_operator=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_prefix_operator=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_question_in_conditional=insert
org.eclipse.cdt.core.formatter.insert_space_before_semicolon=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_unary_operator=do not insert
org.eclipse.cdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
org.eclipse.cdt.core.formatter.insert_space_between_empty_brackets=do not insert
org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
org.eclipse.cdt.core.formatter.keep_else_statement_on_same_line=false
org.eclipse.cdt.core.formatter.keep_empty_array_initializer_on_one_line=false
org.eclipse.cdt.core.formatter.keep_imple_if_on_one_line=false
org.eclipse.cdt.core.formatter.keep_then_statement_on_same_line=false
org.eclipse.cdt.core.formatter.lineSplit=80
org.eclipse.cdt.core.formatter.number_of_empty_lines_to_preserve=1
org.eclipse.cdt.core.formatter.put_empty_statement_on_new_line=true
org.eclipse.cdt.core.formatter.tabulation.char=space
org.eclipse.cdt.core.formatter.tabulation.size=2
org.eclipse.cdt.core.formatter.use_tabs_only_for_leading_indentations=false

View File

@ -1,4 +0,0 @@
#Fri Nov 28 14:33:30 EST 2008
eclipse.preferences.version=1
formatter_profile=org.eclipse.cdt.ui.default.gnu_profile
formatter_settings_version=1

View File

@ -1,315 +0,0 @@
#Fri Nov 28 14:43:43 EST 2008
eclipse.preferences.version=1
org.eclipse.wst.jsdt.core.codeComplete.argumentPrefixes=
org.eclipse.wst.jsdt.core.codeComplete.argumentSuffixes=
org.eclipse.wst.jsdt.core.codeComplete.fieldPrefixes=
org.eclipse.wst.jsdt.core.codeComplete.fieldSuffixes=
org.eclipse.wst.jsdt.core.codeComplete.localPrefixes=
org.eclipse.wst.jsdt.core.codeComplete.localSuffixes=
org.eclipse.wst.jsdt.core.codeComplete.staticFieldPrefixes=
org.eclipse.wst.jsdt.core.codeComplete.staticFieldSuffixes=
org.eclipse.wst.jsdt.core.compiler.codegen.inlineJsrBytecode=disabled
org.eclipse.wst.jsdt.core.compiler.codegen.targetPlatform=1.2
org.eclipse.wst.jsdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.wst.jsdt.core.compiler.compliance=1.4
org.eclipse.wst.jsdt.core.compiler.debug.lineNumber=generate
org.eclipse.wst.jsdt.core.compiler.debug.localVariable=generate
org.eclipse.wst.jsdt.core.compiler.debug.sourceFile=generate
org.eclipse.wst.jsdt.core.compiler.problem.assertIdentifier=warning
org.eclipse.wst.jsdt.core.compiler.problem.deprecation=warning
org.eclipse.wst.jsdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
org.eclipse.wst.jsdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
org.eclipse.wst.jsdt.core.compiler.problem.discouragedReference=warning
org.eclipse.wst.jsdt.core.compiler.problem.emptyStatement=ignore
org.eclipse.wst.jsdt.core.compiler.problem.enumIdentifier=warning
org.eclipse.wst.jsdt.core.compiler.problem.fallthroughCase=ignore
org.eclipse.wst.jsdt.core.compiler.problem.fieldHiding=ignore
org.eclipse.wst.jsdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
org.eclipse.wst.jsdt.core.compiler.problem.forbiddenReference=ignore
org.eclipse.wst.jsdt.core.compiler.problem.hiddenCatchBlock=warning
org.eclipse.wst.jsdt.core.compiler.problem.indirectStaticAccess=ignore
org.eclipse.wst.jsdt.core.compiler.problem.localVariableHiding=ignore
org.eclipse.wst.jsdt.core.compiler.problem.looseVarDecleration=warning
org.eclipse.wst.jsdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
org.eclipse.wst.jsdt.core.compiler.problem.noEffectAssignment=warning
org.eclipse.wst.jsdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
org.eclipse.wst.jsdt.core.compiler.problem.nullReference=ignore
org.eclipse.wst.jsdt.core.compiler.problem.optionalSemicolon=warning
org.eclipse.wst.jsdt.core.compiler.problem.parameterAssignment=ignore
org.eclipse.wst.jsdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
org.eclipse.wst.jsdt.core.compiler.problem.potentialNullReference=ignore
org.eclipse.wst.jsdt.core.compiler.problem.redundantNullCheck=ignore
org.eclipse.wst.jsdt.core.compiler.problem.undefinedField=warning
org.eclipse.wst.jsdt.core.compiler.problem.undocumentedEmptyBlock=ignore
org.eclipse.wst.jsdt.core.compiler.problem.unnecessaryElse=ignore
org.eclipse.wst.jsdt.core.compiler.problem.unresolvedFieldReference=ignore
org.eclipse.wst.jsdt.core.compiler.problem.unresolvedMethodReference=ignore
org.eclipse.wst.jsdt.core.compiler.problem.unresolvedTypeReference=ignore
org.eclipse.wst.jsdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
org.eclipse.wst.jsdt.core.compiler.problem.unusedLabel=warning
org.eclipse.wst.jsdt.core.compiler.problem.unusedLocal=warning
org.eclipse.wst.jsdt.core.compiler.problem.unusedParameter=ignore
org.eclipse.wst.jsdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
org.eclipse.wst.jsdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
org.eclipse.wst.jsdt.core.compiler.problem.unusedPrivateMember=warning
org.eclipse.wst.jsdt.core.compiler.source=1.3
org.eclipse.wst.jsdt.core.formatter.align_type_members_on_columns=false
org.eclipse.wst.jsdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.wst.jsdt.core.formatter.alignment_for_arguments_in_enum_constant=16
org.eclipse.wst.jsdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
org.eclipse.wst.jsdt.core.formatter.alignment_for_arguments_in_method_invocation=16
org.eclipse.wst.jsdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
org.eclipse.wst.jsdt.core.formatter.alignment_for_assignment=0
org.eclipse.wst.jsdt.core.formatter.alignment_for_binary_expression=16
org.eclipse.wst.jsdt.core.formatter.alignment_for_compact_if=16
org.eclipse.wst.jsdt.core.formatter.alignment_for_conditional_expression=80
org.eclipse.wst.jsdt.core.formatter.alignment_for_enum_constants=0
org.eclipse.wst.jsdt.core.formatter.alignment_for_expressions_in_array_initializer=16
org.eclipse.wst.jsdt.core.formatter.alignment_for_multiple_fields=16
org.eclipse.wst.jsdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
org.eclipse.wst.jsdt.core.formatter.alignment_for_parameters_in_method_declaration=16
org.eclipse.wst.jsdt.core.formatter.alignment_for_selector_in_method_invocation=16
org.eclipse.wst.jsdt.core.formatter.alignment_for_superclass_in_type_declaration=16
org.eclipse.wst.jsdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
org.eclipse.wst.jsdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
org.eclipse.wst.jsdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
org.eclipse.wst.jsdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
org.eclipse.wst.jsdt.core.formatter.blank_lines_after_imports=1
org.eclipse.wst.jsdt.core.formatter.blank_lines_after_package=1
org.eclipse.wst.jsdt.core.formatter.blank_lines_before_field=0
org.eclipse.wst.jsdt.core.formatter.blank_lines_before_first_class_body_declaration=0
org.eclipse.wst.jsdt.core.formatter.blank_lines_before_imports=1
org.eclipse.wst.jsdt.core.formatter.blank_lines_before_member_type=1
org.eclipse.wst.jsdt.core.formatter.blank_lines_before_method=1
org.eclipse.wst.jsdt.core.formatter.blank_lines_before_new_chunk=1
org.eclipse.wst.jsdt.core.formatter.blank_lines_before_package=0
org.eclipse.wst.jsdt.core.formatter.blank_lines_between_import_groups=1
org.eclipse.wst.jsdt.core.formatter.blank_lines_between_type_declarations=0
org.eclipse.wst.jsdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
org.eclipse.wst.jsdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
org.eclipse.wst.jsdt.core.formatter.brace_position_for_array_initializer=end_of_line
org.eclipse.wst.jsdt.core.formatter.brace_position_for_block=end_of_line
org.eclipse.wst.jsdt.core.formatter.brace_position_for_block_in_case=end_of_line
org.eclipse.wst.jsdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
org.eclipse.wst.jsdt.core.formatter.brace_position_for_enum_constant=end_of_line
org.eclipse.wst.jsdt.core.formatter.brace_position_for_enum_declaration=end_of_line
org.eclipse.wst.jsdt.core.formatter.brace_position_for_method_declaration=end_of_line
org.eclipse.wst.jsdt.core.formatter.brace_position_for_objlit_initializer=end_of_line
org.eclipse.wst.jsdt.core.formatter.brace_position_for_switch=end_of_line
org.eclipse.wst.jsdt.core.formatter.brace_position_for_type_declaration=end_of_line
org.eclipse.wst.jsdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
org.eclipse.wst.jsdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
org.eclipse.wst.jsdt.core.formatter.comment.format_block_comments=true
org.eclipse.wst.jsdt.core.formatter.comment.format_header=false
org.eclipse.wst.jsdt.core.formatter.comment.format_html=true
org.eclipse.wst.jsdt.core.formatter.comment.format_javadoc_comments=true
org.eclipse.wst.jsdt.core.formatter.comment.format_line_comments=true
org.eclipse.wst.jsdt.core.formatter.comment.format_source_code=true
org.eclipse.wst.jsdt.core.formatter.comment.indent_parameter_description=true
org.eclipse.wst.jsdt.core.formatter.comment.indent_root_tags=true
org.eclipse.wst.jsdt.core.formatter.comment.insert_new_line_before_root_tags=insert
org.eclipse.wst.jsdt.core.formatter.comment.insert_new_line_for_parameter=insert
org.eclipse.wst.jsdt.core.formatter.comment.line_length=80
org.eclipse.wst.jsdt.core.formatter.compact_else_if=true
org.eclipse.wst.jsdt.core.formatter.continuation_indentation=2
org.eclipse.wst.jsdt.core.formatter.continuation_indentation_for_array_initializer=2
org.eclipse.wst.jsdt.core.formatter.continuation_indentation_for_objlit_initializer=1
org.eclipse.wst.jsdt.core.formatter.format_guardian_clause_on_one_line=false
org.eclipse.wst.jsdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
org.eclipse.wst.jsdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
org.eclipse.wst.jsdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
org.eclipse.wst.jsdt.core.formatter.indent_body_declarations_compare_to_type_header=true
org.eclipse.wst.jsdt.core.formatter.indent_breaks_compare_to_cases=true
org.eclipse.wst.jsdt.core.formatter.indent_empty_lines=false
org.eclipse.wst.jsdt.core.formatter.indent_statements_compare_to_block=true
org.eclipse.wst.jsdt.core.formatter.indent_statements_compare_to_body=true
org.eclipse.wst.jsdt.core.formatter.indent_switchstatements_compare_to_cases=true
org.eclipse.wst.jsdt.core.formatter.indent_switchstatements_compare_to_switch=false
org.eclipse.wst.jsdt.core.formatter.indentation.size=4
org.eclipse.wst.jsdt.core.formatter.insert_new_line_after_annotation=insert
org.eclipse.wst.jsdt.core.formatter.insert_new_line_after_comma_in_objlit_initializer=insert
org.eclipse.wst.jsdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_new_line_after_opening_brace_in_objlit_initializer=insert
org.eclipse.wst.jsdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_closing_brace_in_objlit_initializer=insert
org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_block=insert
org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_method_body=insert
org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_and_in_type_parameter=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_assignment_operator=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_at_in_annotation=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_binary_operator=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_closing_brace_in_block=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_colon_in_assert=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_colon_in_case=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_colon_in_conditional=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_colon_in_for=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_annotation=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_for_increments=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_for_inits=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_ellipsis=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_postfix_operator=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_prefix_operator=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_question_in_conditional=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_semicolon_in_for=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_unary_operator=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_and_in_type_parameter=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_assignment_operator=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_binary_operator=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_assert=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_case=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_conditional=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_default=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_for=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_ellipsis=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_block=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_for=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_if=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_while=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_postfix_operator=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_prefix_operator=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_question_in_conditional=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_semicolon=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_unary_operator=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
org.eclipse.wst.jsdt.core.formatter.keep_else_statement_on_same_line=false
org.eclipse.wst.jsdt.core.formatter.keep_empty_array_initializer_on_one_line=false
org.eclipse.wst.jsdt.core.formatter.keep_empty_objlit_initializer_on_one_line=false
org.eclipse.wst.jsdt.core.formatter.keep_imple_if_on_one_line=false
org.eclipse.wst.jsdt.core.formatter.keep_then_statement_on_same_line=false
org.eclipse.wst.jsdt.core.formatter.lineSplit=80
org.eclipse.wst.jsdt.core.formatter.never_indent_block_comments_on_first_column=false
org.eclipse.wst.jsdt.core.formatter.never_indent_line_comments_on_first_column=false
org.eclipse.wst.jsdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
org.eclipse.wst.jsdt.core.formatter.number_of_empty_lines_to_preserve=1
org.eclipse.wst.jsdt.core.formatter.put_empty_statement_on_new_line=true
org.eclipse.wst.jsdt.core.formatter.tabulation.char=space
org.eclipse.wst.jsdt.core.formatter.tabulation.size=4
org.eclipse.wst.jsdt.core.formatter.use_tabs_only_for_leading_indentations=false
org.eclipse.wst.jsdt.core.formatter.wrap_before_binary_operator=true

View File

@ -1,10 +0,0 @@
#Fri Nov 28 14:39:12 EST 2008
eclipse.preferences.version=1
formatter_profile=_gjs
formatter_settings_version=11
org.eclipse.wst.jsdt.ui.exception.name=e
org.eclipse.wst.jsdt.ui.gettersetter.use.is=true
org.eclipse.wst.jsdt.ui.javadoc=false
org.eclipse.wst.jsdt.ui.keywordthis=false
org.eclipse.wst.jsdt.ui.overrideannotation=true
org.eclipse.wst.jsdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates/>

View File

@ -1 +0,0 @@
org.eclipse.wst.jsdt.launching.baseBrowserLibrary

View File

@ -1 +0,0 @@
Window

View File

@ -80,10 +80,7 @@ e.g. `imports.ui.popupMenu`.
Each import block should be sorted alphabetically. Don't import modules you
don't use.
```javascript
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const St = imports.gi.St;
const { GLib, Gio, St } = imports.gi;
const Main = imports.ui.main;
const Params = imports.misc.params;
@ -121,40 +118,34 @@ See [What's new in JavaScript 1.7](https://developer.mozilla.org/en/JavaScript/N
## Classes
There are many approaches to classes in JavaScript. We use our own class framework
(sigh), which is built in gjs. The advantage is that it supports inheriting from
GObjects, although this feature isn't used very often in the Shell itself.
There are many approaches to classes in JavaScript. We use standard ES6 classes
whenever possible, that is when not inheriting from GObjects.
```javascript
var IconLabelMenuItem = new Lang.Class({
Name: 'IconLabelMenuItem',
Extends: PopupMenu.PopupMenuBaseItem,
_init(icon, label) {
this.parent({ reactive: false });
var IconLabelMenuItem = class extends PopupMenu.PopupMenuBaseItem {
constructor(icon, label) {
super({ reactive: false });
this.actor.add_child(icon);
this.actor.add_child(label);
},
}
open() {
log("menu opened!");
}
});
};
```
* 'Name' is required. 'Extends' is optional. If you leave it out, you will
automatically inherit from Object.
For GObject inheritence, we use the GObject.registerClass() function provided
by gjs.
```javascript
var MyActor = GObject.registerClass(
class MyActor extends Clutter.Actor {
_init(params) {
super._init(params);
* Leave a blank line between the "class header" (Name, Extends, and other
things) and the "class body" (methods). Leave a blank line between each
method.
* No space before the colon, one space after.
* No trailing comma after the last item.
* Make sure to use a semicolon after the closing paren to the class. It's
still a giant function call, even though it may resemble a more
conventional syntax.
this.name = 'MyCustomActor';
}
});
```
## GObject Introspection
@ -162,19 +153,18 @@ GObject Introspection is a powerful feature that allows us to have native
bindings for almost any library built around GObject. If a library requires
you to inherit from a type to use it, you can do so:
```javascript
var MyClutterActor = new Lang.Class({
Name: 'MyClutterActor',
Extends: Clutter.Actor,
var MyClutterActor = GObject.registerClass(
class MyClutterActor extends Clutter.Actor {
vfunc_get_preferred_width(actor, forHeight) {
vfunc_get_preferred_width(forHeight) {
return [100, 100];
},
}
vfunc_get_preferred_height(actor, forWidth) {
vfunc_get_preferred_height(forWidth) {
return [100, 100];
},
}
vfunc_paint(actor) {
vfunc_paint() {
let alloc = this.get_allocation_box();
Cogl.set_source_color4ub(255, 0, 0, 255);
Cogl.rectangle(alloc.x1, alloc.y1,
@ -207,20 +197,18 @@ that has a property called `actor`. We call this wrapper class the "delegate".
We sometimes use expando properties to set a property called `_delegate` on
the actor itself:
```javascript
var MyClass = new Lang.Class({
Name: 'MyClass',
_init() {
var MyClass = class {
constructor() {
this.actor = new St.Button({ text: "This is a button" });
this.actor._delegate = this;
this.actor.connect('clicked', this._onClicked.bind(this));
},
}
_onClicked(actor) {
actor.set_label("You clicked the button!");
}
});
};
```
The 'delegate' property is important for anything which trying to get the
@ -246,8 +234,6 @@ variable that can be captured in closures.
All closures should be wrapped with Function.prototype.bind or use arrow
notation.
```javascript
const Lang = imports.lang;
let closure1 = () => { this._fnorbate(); };
let closure2 = this._fnorbate.bind(this);
```
@ -255,19 +241,18 @@ notation.
A more realistic example would be connecting to a signal on a method of a
prototype:
```javascript
const Lang = imports.lang;
const FnorbLib = imports.fborbLib;
var MyClass = new Lang.Class({
var MyClass = class {
_init() {
let fnorb = new FnorbLib.Fnorb();
fnorb.connect('frobate', this._onFnorbFrobate.bind(this));
},
}
_onFnorbFrobate(fnorb) {
this._updateFnorb();
}
});
};
```
## Object literal syntax
@ -301,23 +286,21 @@ property.
```javascript
var ANIMATION_TIME = 2000;
var MyClass = new Lang.Class({
Name: 'MyClass',
_init() {
var MyClass = class {
constructor() {
this.actor = new St.BoxLayout();
this._position = 0;
},
}
get position() {
return this._position;
},
}
set position(value) {
this._position = value;
this.actor.set_position(value, value);
}
});
};
let myThing = new MyClass();
Tweener.addTween(myThing,

95
NEWS
View File

@ -1,3 +1,98 @@
3.32.0
======
* Fix sizing issues in on-screen-keyboard emoji panel [Carlos; !439]
* Fix test linker failure on Debian/Ubuntu [Iain; !442]
* Avoid assertion when sizing fallback app icons from CSS [Florian; #1027]
* Fix mis-sized menu arrows after texture cache changes [Florian; !452]
Contributors:
Carlos Garnacho, Iain Lane, Florian Müllner
Translators:
Gábor Kelemen [hu], Victor Ibragimov [tg], Ryuta Fujii [ja], Piotr Drąg [af,
tg], Mart Raudsepp [et]
3.31.92
=======
* Fix visual glitch in submenus [Alex; #987]
* Support fractional scaling [Jonas, Marco; #765011, !5]
* Only consider visible children for :first-child/:last-child [Florian; !312]
* Hide trailing separator in search results [verdre; !311]
* Remember choice in inhibit-shortcuts dialogue [Olivier; !382]
* Don't toggle on-screen keyboard on every focus change [Carlos; !397]
* Fix legacy tray icons not responding to events on wayland [Florian; #191]
* Fix generating French OSK layout [Florian; #997]
* Use borderless round user images [Florian; #811]
* Misc. bug fixes and cleanups [Andrea, Robert, Florian, Marco, Niels,
Benjamin; !414, !417, !420, #996, !408, !422, !425, #1006, !427, !315,
#989, !430, !431, !432, #1015, !429, !423, !419, !434]
Contributors:
Jonas Ådahl, Alan, Andrea Azzarone, Benjamin Berg, Olivier Fourdan,
Carlos Garnacho, Niels De Graef, Robert Mader, Alex Monday, Florian Müllner,
Marco Trevisan (Treviño), verdre
Translators:
Carmen Bianca BAKKER [eo], Asier Sarasua Garmendia [eu], Stas Solovey [ru],
Changwoo Ryu [ko], Julien Humbert [fr], Milo Casagrande [it],
Марко Костић [sr], Ask Hjorth Larsen [da], Kukuh Syafaat [id],
Daniel Șerbănescu [ro], Bernd Homuth [de], Trần Ngọc Quân [vi],
Nathan Follens [nl], Rūdolfs Mazurs [lv], Aurimas Černius [lt]
3.31.91
=======
* Don't close on-screen-keyboard's language menu on hover [Florian; #171]
* Don't let unfullscreen gesture interfere with top bar taps [Jonas D.; #552]
* Always use symbolic user icon in system menu [Florian; #957]
* Add flags parameter in GrabAccelerators API [Andrea; #68]
* Misc. bug fixes and cleanups [Florian, Jonas A.; !399, !398, !400, !402,
!407, !410, !411]
Contributors:
Jonas Ådahl, Andrea Azzarone, Arnaud Bonatti, Jonas Dreßler, Florian Müllner
Translators:
Jordi Mas [ca], Ryuta Fujii [ja], Marek Cernocky [cs], Fran Dieguez [gl],
Jiri Grönroos [fi], Serdar Sağlam [tr], Anders Jonsson [sv],
Matej Urbančič [sl], Gun Chleoc [gd], Kukuh Syafaat [id],
Baurzhan Muftakhidinov [kk], Alan Mortensen [da], Rafael Fontenelle [pt_BR],
Sveinn í Felli [is]
3.31.90
=======
* Fix input methods after ibus restarts [Takao; #295]
* Refresh world clocks and weather sections [Florian; #262]
* Port to ES6 classes (update your extensions!) [Florian; !361]
* networkAgent: Advise users when WPS support is available [Lubomir; !329]
* Performance improvements [Carlos; #832, #815]
* Fix drag-and-drop with wacom pens [Carlos; #540]
* Fix CAPS LOCK indication on wayland [Carlos; #762881]
* Show details of non-sensitive notifications on lock screen [Philip; #726]
* Refine extension-prefs' error UI [Florian; !193]
* Add switch-to-application-n keybindings [Florian; #648000]
* Remove top bar translucency [Florian; #408]
* Support emojis and keypads in on-screen keyboard [Carlos; #675]
* Don't allow popups to re-enable keyboard shortcuts on lock screen
(CVE-2019-3820) [Florian, Ray; #851]
* Replace app menu [Florian; #624]
* Include commonly copied+pasted extension helpers [Florian; !150]
* Misc. bug fixes and cleanups [Florian, Daniel, Philip, Sergio, Pascal,
Georges, verdre, Carlos, Christopher; #780, #909, !316, !308, !309, #915,
!350, !362, !357, !365, !366, !283, !367, #942, !371, !373, !374, !343,
!375, !292, !317, !377, !379, !346, !383, #953, !388]
Contributors:
Sergio Costas, Christopher Davis, Bilal Elmoussaoui, Takao Fujiwara,
Carlos Garnacho, Niels De Graef, Christian Kellner, Ignat Loskutov,
Florian Müllner, Georges Basile Stavracas Neto, Pascal Nowack, Lubomir Rintel,
Jakub Steiner, Ray Strode, verdre, Daniel van Vugt, Philip Withnall
Translators:
Daniel Mustieles [es], Carmen Bianca BAKKER [eo], Charles Monzat [fr],
Pieter Schalk Schoeman [af], Jordi Mas [ca], Matej Urbančič [sl],
Fran Dieguez [gl], Balázs Úr [hu], A S Alam [pa], Fabio Tomat [fur],
Aurimas Černius [lt], Piotr Drąg [pl], Marek Cernocky [cs], Ryuta Fujii [ja]
3.31.4
======
* Improve icon grid performance [Daniel; #174]

View File

@ -11,6 +11,14 @@ see the [project wiki][project-wiki].
Bugs should be reported to the GNOME [bug tracking system][bug-tracker].
## Contributing
To contribute, open merge requests at https://gitlab.gnome.org/GNOME/gnome-shell.
Commit messages should follow the [GNOME commit message
guidelines](https://wiki.gnome.org/Git/CommitMessages). We require an URL
to either an issue or a merge request in each commit.
## License
GNOME Shell is distributed under the terms of the GNU General Public License,
version 2 or later. See the [COPYING][license] file for details.

40
README.mdwn Normal file
View File

@ -0,0 +1,40 @@
cldr2json
=========
This script converts Unicode CLDR android keyboard layouts to JSON usable by
GNOME Shell.
CLDR keyboard layouts can be found at
<http://www.unicode.org/Public/cldr/latest/keyboards.zip>
Usage
=====
./cldr2json <input file or directory> <output directory>
example:
./cldr2json cldr/keyboards/android/ json_layouts/
Keyboard layout mapping
=======================
Unicode CLDR layout identifiers are language codes, while XKB layout
identifiers are... something else. The mapping between the two currently uses
heuristic based on the layout descriptions, in this order:
- if the CLDR layout description matches an XKB layout description, chose its
XKB identifier
- if one word of the CLDR layout description matches an XKB layout
description, chose its XKB identifier
- if the CLDR layout description matches one word of an XKB layout description,
chose its XKB identifier
That doesn't always work. For instance it fails for "en" language, that should
match "us" XKB identifier. For such cases, there is a mapping in
LOCALE_TO_XKB_OVERRIDES at the top of the script. If you discover a weird
mapping of if you get a "failed to find XKB mapping for <locale>" warning then
please consider adding an override there.

208
cldr2json.py Executable file
View File

@ -0,0 +1,208 @@
#!/usr/bin/python3
#
# Copyright 2015 Daiki Ueno <dueno@src.gnome.org>
# 2016 Parag Nemade <pnemade@redhat.com>
# 2017 Alan <alan@boum.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation; either version 2 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program; if not, see
# <http://www.gnu.org/licenses/>.
import glob
import json
import locale
import logging
import os
import re
import sys
import xml.etree.ElementTree
import gi
gi.require_version('GnomeDesktop', '3.0') # NOQA: E402
from gi.repository import GnomeDesktop
ESCAPE_PATTERN = re.compile(r'\\u\{([0-9A-Fa-f]+?)\}')
ISO_PATTERN = re.compile(r'[A-E]([0-9]+)')
LOCALE_TO_XKB_OVERRIDES = {
'af': 'za',
'en': 'us',
'en-GB': 'uk',
'es-US': 'latam',
'fr-CA': 'ca',
'hi': 'in+bolnagri',
'ky': 'kg',
'nl-BE': 'be',
'zu': None
}
def parse_single_key(value):
def unescape(m):
return chr(int(m.group(1), 16))
value = ESCAPE_PATTERN.sub(unescape, value)
return value
def parse_rows(keymap):
unsorted_rows = {}
for _map in keymap.iter('map'):
value = _map.get('to')
key = [parse_single_key(value)]
iso = _map.get('iso')
if not ISO_PATTERN.match(iso):
sys.stderr.write('invalid ISO key name: %s\n' % iso)
continue
if not iso[0] in unsorted_rows:
unsorted_rows[iso[0]] = []
unsorted_rows[iso[0]].append((int(iso[1:]), key))
# add subkeys
longPress = _map.get('longPress')
if longPress:
for value in longPress.split(' '):
subkey = parse_single_key(value)
key.append(subkey)
rows = []
for k, v in sorted(list(unsorted_rows.items()),
key=lambda x: x[0],
reverse=True):
row = []
for key in sorted(v, key=lambda x: x):
row.append(key[1])
rows.append(row)
return rows
def convert_xml(tree):
root = {}
for xml_keyboard in tree.iter("keyboard"):
locale_full = xml_keyboard.get("locale")
locale, sep, end = locale_full.partition("-t-")
root["locale"] = locale
for xml_name in tree.iter("name"):
name = xml_name.get("value")
root["name"] = name
root["levels"] = []
# parse levels
for index, keymap in enumerate(tree.iter('keyMap')):
# FIXME: heuristics here
modifiers = keymap.get('modifiers')
if not modifiers:
mode = 'default'
modifiers = ''
elif 'shift' in modifiers.split(' '):
mode = 'latched'
modifiers = 'shift'
else:
mode = 'locked'
level = {}
level["level"] = modifiers
level["mode"] = mode
level["rows"] = parse_rows(keymap)
root["levels"].append(level)
return root
def locale_to_xkb(locale, name):
if locale in sorted(LOCALE_TO_XKB_OVERRIDES.keys()):
xkb = LOCALE_TO_XKB_OVERRIDES[locale]
logging.debug("override for %s%s",
locale, xkb)
if xkb:
return xkb
else:
raise KeyError("layout %s explicitely disabled in overrides"
% locale)
xkb_names = sorted(name_to_xkb.keys())
if name in xkb_names:
return name_to_xkb[name]
else:
logging.debug("name %s failed" % name)
for sub_name in name.split(' '):
if sub_name in xkb_names:
xkb = name_to_xkb[sub_name]
logging.debug("dumb mapping failed but match with locale word: "
"%s (%s) → %s (%s)",
locale, name, xkb, sub_name)
return xkb
else:
logging.debug("sub_name failed")
for xkb_name in xkb_names:
for xkb_sub_name in xkb_name.split(' '):
if xkb_sub_name.strip('()') == name:
xkb = name_to_xkb[xkb_name]
logging.debug("dumb mapping failed but match with xkb word: "
"%s (%s) → %s (%s)",
locale, name, xkb, xkb_name)
return xkb
raise KeyError("failed to find XKB mapping for %s" % locale)
def convert_file(source_file, destination_path):
logging.info("Parsing %s", source_file)
itree = xml.etree.ElementTree.ElementTree()
itree.parse(source_file)
root = convert_xml(itree)
try:
xkb_name = locale_to_xkb(root["locale"], root["name"])
except KeyError as e:
logging.warn(e)
return False
destination_file = os.path.join(destination_path, xkb_name + ".json")
with open(destination_file, 'w', encoding="utf-8") as dest_fd:
json.dump(root, dest_fd, ensure_ascii=False, indent=2, sort_keys=True)
logging.debug("written %s", destination_file)
def load_xkb_mappings():
xkb = GnomeDesktop.XkbInfo()
layouts = xkb.get_all_layouts()
name_to_xkb = {}
for layout in layouts:
name = xkb.get_layout_info(layout).display_name
name_to_xkb[name] = layout
return name_to_xkb
locale.setlocale(locale.LC_ALL, "C")
name_to_xkb = load_xkb_mappings()
if __name__ == "__main__":
if "DEBUG" in os.environ:
logging.basicConfig(level=logging.DEBUG)
if len(sys.argv) < 2:
print("supply a CLDR keyboard file")
sys.exit(1)
if len(sys.argv) < 3:
print("supply an output directory")
sys.exit(1)
source = sys.argv[1]
destination = sys.argv[2]
if os.path.isfile(source):
convert_file(source, destination)
elif os.path.isdir(source):
for path in glob.glob(source + "/*-t-k0-android.xml"):
convert_file(path, destination)

View File

@ -0,0 +1,12 @@
<node>
<interface name="org.gnome.Shell.CalendarServer">
<method name="GetEvents">
<arg type="x" direction="in" />
<arg type="x" direction="in" />
<arg type="b" direction="in" />
<arg type="a(sssbxxa{sv})" direction="out" />
</method>
<property name="HasCalendars" type="b" access="read" />
<signal name="Changed" />
</interface>
</node>

View File

@ -9,9 +9,6 @@
<method name="ShowOSD">
<arg type="a{sv}" direction="in" name="params"/>
</method>
<method name="ShowMonitorLabels">
<arg type="a{uv}" direction="in" name="params"/>
</method>
<method name="ShowMonitorLabels2">
<arg type="a{sv}" direction="in" name="params"/>
</method>
@ -22,17 +19,22 @@
<method name="ShowApplications"/>
<method name="GrabAccelerator">
<arg type="s" direction="in" name="accelerator"/>
<arg type="u" direction="in" name="flags"/>
<arg type="u" direction="in" name="modeFlags"/>
<arg type="u" direction="in" name="grabFlags"/>
<arg type="u" direction="out" name="action"/>
</method>
<method name="GrabAccelerators">
<arg type="a(su)" direction="in" name="accelerators"/>
<arg type="a(suu)" direction="in" name="accelerators"/>
<arg type="au" direction="out" name="actions"/>
</method>
<method name="UngrabAccelerator">
<arg type="u" direction="in" name="action"/>
<arg type="b" direction="out" name="success"/>
</method>
<method name="UngrabAccelerators">
<arg type="au" direction="in" name="action"/>
<arg type="b" direction="out" name="success"/>
</method>
<signal name="AcceleratorActivated">
<arg name="action" type="u"/>
<arg name="parameters" type="a{sv}"/>

15740
data/emoji.json Normal file

File diff suppressed because it is too large Load Diff

View File

@ -39,6 +39,7 @@
<file preprocess="xml-stripblanks">org.gnome.SettingsDaemon.Rfkill.xml</file>
<file preprocess="xml-stripblanks">org.gnome.SettingsDaemon.Wacom.xml</file>
<file preprocess="xml-stripblanks">org.gnome.Shell.AudioDeviceSelection.xml</file>
<file preprocess="xml-stripblanks">org.gnome.Shell.CalendarServer.xml</file>
<file preprocess="xml-stripblanks">org.gnome.Shell.Extensions.xml</file>
<file preprocess="xml-stripblanks">org.gnome.Shell.Introspect.xml</file>
<file preprocess="xml-stripblanks">org.gnome.Shell.HotplugSniffer.xml</file>

View File

@ -6,6 +6,7 @@
<file>be.json</file>
<file>bg.json</file>
<file>by.json</file>
<file>ca.json</file>
<file>cz.json</file>
<file>de.json</file>
<file>dk.json</file>
@ -54,5 +55,6 @@
<file>us.json</file>
<file>vn.json</file>
<file>za.json</file>
<file>emoji.json</file>
</gresource>
</gresources>

View File

@ -145,6 +145,42 @@
<summary>Keybinding that pauses and resumes all running tweens, for debugging purposes</summary>
<description></description>
</key>
<key name="switch-to-application-1" type="as">
<default>["&lt;Super&gt;1"]</default>
<summary>Switch to application 1</summary>
</key>
<key name="switch-to-application-2" type="as">
<default>["&lt;Super&gt;2"]</default>
<summary>Switch to application 2</summary>
</key>
<key name="switch-to-application-3" type="as">
<default>["&lt;Super&gt;3"]</default>
<summary>Switch to application 3</summary>
</key>
<key name="switch-to-application-4" type="as">
<default>["&lt;Super&gt;4"]</default>
<summary>Switch to application 4</summary>
</key>
<key name="switch-to-application-5" type="as">
<default>["&lt;Super&gt;5"]</default>
<summary>Switch to application 5</summary>
</key>
<key name="switch-to-application-6" type="as">
<default>["&lt;Super&gt;6"]</default>
<summary>Switch to application 6</summary>
</key>
<key name="switch-to-application-7" type="as">
<default>["&lt;Super&gt;7"]</default>
<summary>Switch to application 7</summary>
</key>
<key name="switch-to-application-8" type="as">
<default>["&lt;Super&gt;8"]</default>
<summary>Switch to application 8</summary>
</key>
<key name="switch-to-application-9" type="as">
<default>["&lt;Super&gt;9"]</default>
<summary>Switch to application 9</summary>
</key>
</schema>
<schema id="org.gnome.shell.keyboard" path="/org/gnome/shell/keyboard/"

599
data/osk-layouts/ca.json Normal file
View File

@ -0,0 +1,599 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"q"
],
[
"w"
],
[
"e",
"é",
"è",
"ê",
"ë",
"%",
"ę",
"ė",
"ē"
],
[
"r"
],
[
"t"
],
[
"y",
"%",
"ÿ"
],
[
"u",
"ù",
"û",
"%",
"ü",
"ú",
"ū"
],
[
"i",
"î",
"%",
"ï",
"ì",
"í",
"į",
"ī"
],
[
"o",
"ô",
"œ",
"%",
"ö",
"ò",
"ó",
"õ",
"ø",
"ō",
"º"
],
[
"p"
]
],
[
[
"a",
"à",
"â",
"%",
"æ",
"á",
"ä",
"ã",
"å",
"ā",
"ª"
],
[
"s"
],
[
"d"
],
[
"f"
],
[
"g"
],
[
"h"
],
[
"j"
],
[
"k"
],
[
"l"
]
],
[
[
"z"
],
[
"x"
],
[
"c",
"ç",
"ć",
"č"
],
[
"v"
],
[
"b"
],
[
"n"
],
[
"m"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "shift",
"mode": "latched",
"rows": [
[
[
"Q"
],
[
"W"
],
[
"E",
"É",
"È",
"Ê",
"Ë",
"%",
"Ę",
"Ė",
"Ē"
],
[
"R"
],
[
"T"
],
[
"Y",
"%",
"Ÿ"
],
[
"U",
"Ù",
"Û",
"%",
"Ü",
"Ú",
"Ū"
],
[
"I",
"Î",
"%",
"Ï",
"Ì",
"Í",
"Į",
"Ī"
],
[
"O",
"Ô",
"Œ",
"%",
"Ö",
"Ò",
"Ó",
"Õ",
"Ø",
"Ō",
"º"
],
[
"P"
]
],
[
[
"A",
"À",
"Â",
"%",
"Æ",
"Á",
"Ä",
"Ã",
"Å",
"Ā",
"ª"
],
[
"S"
],
[
"D"
],
[
"F"
],
[
"G"
],
[
"H"
],
[
"J"
],
[
"K"
],
[
"L"
]
],
[
[
"Z"
],
[
"X"
],
[
"C",
"Ç",
"Ć",
"Č"
],
[
"V"
],
[
"B"
],
[
"N"
],
[
"M"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"$",
"¢",
"£",
"€",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"¢"
],
[
"€"
],
[
"¥"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
}
],
"locale": "fr-CA",
"name": "French Canada"
}

View File

@ -6,10 +6,20 @@
"rows": [
[
[
"q"
"a",
"à",
"â",
"%",
"æ",
"á",
"ä",
"ã",
"å",
"ā",
"ª"
],
[
"w"
"z"
],
[
"e",
@ -71,17 +81,7 @@
],
[
[
"a",
"à",
"â",
"%",
"æ",
"á",
"ä",
"ã",
"å",
"ā",
"ª"
"q"
],
[
"s"
@ -106,11 +106,14 @@
],
[
"l"
],
[
"m"
]
],
[
[
"z"
"w"
],
[
"x"
@ -131,7 +134,11 @@
"n"
],
[
"m"
"'",
"",
"",
"",
""
]
],
[
@ -161,10 +168,20 @@
"rows": [
[
[
"Q"
"A",
"À",
"Â",
"%",
"Æ",
"Á",
"Ä",
"Ã",
"Å",
"Ā",
"ª"
],
[
"W"
"Z"
],
[
"E",
@ -226,17 +243,7 @@
],
[
[
"A",
"À",
"Â",
"%",
"Æ",
"Á",
"Ä",
"Ã",
"Å",
"Ā",
"ª"
"Q"
],
[
"S"
@ -261,11 +268,14 @@
],
[
"L"
],
[
"M"
]
],
[
[
"Z"
"W"
],
[
"X"
@ -286,7 +296,11 @@
"N"
],
[
"M"
"'",
"",
"",
"",
""
]
],
[
@ -369,10 +383,10 @@
"#"
],
[
"$",
"",
"¢",
"£",
"",
"$",
"¥",
"₱"
],
@ -511,13 +525,14 @@
"£"
],
[
"¥"
],
[
"$",
"¢"
],
[
""
],
[
"¥"
"¢"
],
[
"^",
@ -594,6 +609,6 @@
]
}
],
"locale": "fr-CA",
"name": "French Canada"
"locale": "fr",
"name": "French"
}

View File

@ -2,29 +2,26 @@
// it gets @if ed depending on $variant
$base_color: if($variant =='light', #ffffff, #292929);
$bg_color: if($variant =='light', #ededed, #393f3f);
$fg_color: if($variant =='light', #2e3436, #eeeeec);
$base_color: if($variant == 'light', #ffffff, lighten(desaturate(#241f31, 20%), 2%));
$bg_color: if($variant == 'light', #f6f5f4, desaturate(#3d3846, 10%));
$fg_color: if($variant == 'light', #2e3436, #eeeeec);
$selected_fg_color: #ffffff;
$selected_bg_color: if($variant == 'light', #4a90d9, darken(#4a90d9,20%));
$selected_borders_color: if($variant=='light', darken($selected_bg_color, 30%),
darken($selected_bg_color, 20%));
$borders_color: if($variant =='light', darken($bg_color,30%), darken($bg_color,12%));
$borders_edge: if($variant =='light', white, transparentize($fg_color, 0.9));
$link_color: if($variant == 'light', darken($selected_bg_color,10%),
lighten($selected_bg_color,20%));
$link_visited_color: if($variant == 'light', darken($selected_bg_color,20%),
lighten($selected_bg_color,10%));
$selected_bg_color: if($variant == 'light', #3584e4, darken(#3584e4, 20%));
$selected_borders_color: if($variant== 'light', darken($selected_bg_color, 15%), darken($selected_bg_color, 30%));
$borders_color: if($variant == 'light', darken($bg_color, 18%), darken($bg_color, 10%));
$borders_edge: if($variant == 'light', transparentize(white, 0.2), transparentize($fg_color, 0.93));
$link_color: if($variant == 'light', darken($selected_bg_color, 10%), lighten($selected_bg_color, 20%));
$link_visited_color: if($variant == 'light', darken($selected_bg_color, 20%), lighten($selected_bg_color, 10%));
$top_hilight: $borders_edge;
$warning_color: #f57900;
$error_color: #cc0000;
$success_color: if($variant =='light', #73d216, darken(#73d216,10%));
$destructive_color: if($variant =='light', #ef2929, darken(#ef2929,10%));
$error_color: #ff8080;
$success_color: if($variant == 'light', #33d17a, darken(#33d17a, 10%));
$destructive_color: if($variant == 'light', #e01b24, darken(#e01b24, 10%));
$osd_fg_color: #eeeeec;
$osd_bg_color: #2e3436;
$osd_bg_color: transparentize(darken(desaturate(#3d3846, 100%), 15%),0.3);
$osd_borders_color: transparentize(black, 0.3);
$osd_outer_borders_color: transparentize(white, 0.9);

View File

@ -29,7 +29,7 @@ $panel-corner-radius: 6px;
/* GLOBALS */
$font-size: 11;
$font-family: Cantarell, Sans-Serif;
$_bubble_bg_color: opacify($osd_bg_color,0.25);
$_bubble_bg_color: $osd_bg_color;
$_bubble_fg_color: $osd_fg_color;
$_bubble_borders_color: transparentize($osd_fg_color,0.8);
@ -184,7 +184,7 @@ StScrollBar {
.modal-dialog {
border-radius: 9px;
color: $osd_fg_color;
background-color: transparentize(darken($osd_bg_color,10%),0.05);
background-color: $osd_bg_color;
border: 1px solid $_bubble_borders_color;
.modal-dialog-content-box {
padding: 24px;
@ -267,8 +267,7 @@ StScrollBar {
}
.end-session-dialog-logout-icon {
//border: 2px solid #8b8b8b;
border-radius: 5px;
border-radius: 99px;
width: 48px;
height: 48px;
background-size: contain;
@ -393,7 +392,7 @@ StScrollBar {
.prompt-dialog-error-label {
font-size: 10pt;
color: $error_color;
color: $warning_color;
padding-bottom: 8px;
}
@ -428,7 +427,7 @@ StScrollBar {
}
.polkit-dialog-user-icon {
border-radius: 5px;
border-radius: 99px;
background-size: contain;
width: 48px;
height: 48px;
@ -508,6 +507,7 @@ StScrollBar {
.popup-menu-arrow { } //defined globally in the TOP BAR
.popup-sub-menu {
padding-bottom: 1px;
background-color: darken($bg_color,2%);
box-shadow: inset 0 -1px 0px lighten($borders_color,5%);
}
@ -729,9 +729,7 @@ StScrollBar {
/* TOP BAR */
#panel {
background-color: rgba(0, 0, 0, 0.35);
/* transition from solid to transparent */
transition-duration: 500ms;
background-color: black;
font-weight: bold;
height: 1.86em;
font-feature-settings: "tnum";
@ -748,7 +746,7 @@ StScrollBar {
.panel-corner {
-panel-corner-radius: $panel-corner-radius;
-panel-corner-background-color: rgba(0, 0, 0, 0.35);
-panel-corner-background-color: black;
-panel-corner-border-width: 2px;
-panel-corner-border-color: transparent;
@ -767,9 +765,7 @@ StScrollBar {
-natural-hpadding: 12px;
-minimum-hpadding: 6px;
font-weight: bold;
color: #eee;
text-shadow: 0px 1px 2px rgba(0, 0, 0, 0.9);
transition-duration: 100ms;
color: #ccc;
.app-menu-icon {
-st-icon-style: symbolic;
@ -778,21 +774,8 @@ StScrollBar {
//dimensions of the icon are hardcoded
}
.system-status-icon,
.app-menu-icon > StIcon,
.popup-menu-arrow {
icon-shadow: 0px 1px 2px rgba(0, 0, 0, 0.9);
}
&:hover {
color: lighten($fg_color, 10%);
text-shadow: 0px 1px 6px rgba(0, 0, 0, 1);
.system-status-icon,
.app-menu-icon > StIcon,
.popup-menu-arrow {
icon-shadow: 0px 1px 6px rgba(0, 0, 0, 1);
}
}
&:active, &:overview, &:focus, &:checked {
@ -801,8 +784,6 @@ StScrollBar {
background-color: rgba(0, 0, 0, 0.01);
box-shadow: inset 0 -2px 0px lighten($selected_bg_color,5%);
color: lighten($fg_color,10%);
& > .system-status-icon { icon-shadow: black 0 2px 2px; }
}
.system-status-icon { icon-size: 1.09em; padding: 0 5px; }
@ -827,31 +808,6 @@ StScrollBar {
.screencast-indicator { color: $warning_color; }
.remote-access-indicator { color: $warning_color; }
&.solid {
background-color: black;
/* transition from transparent to solid */
transition-duration: 300ms;
.panel-corner {
-panel-corner-background-color: black;
}
.panel-button {
color: #ccc;
text-shadow: none;
&:hover, &:active, &:overview, &:focus, &:checked {
color: lighten($fg_color, 10%);
}
}
.system-status-icon,
.app-menu-icon > StIcon,
.popup-menu-arrow {
icon-shadow: none;
}
}
}
// calendar popover
@ -922,14 +878,47 @@ StScrollBar {
font-weight: bold;
}
.world-clocks-grid {
.weather-header.location {
font-weight: normal;
font-size: 0.9em;
}
.world-clocks-grid,
.weather-grid {
spacing-rows: 0.4em;
spacing-columns: 0.8em;
}
.weather-box {
spacing: 0.4em;
}
.world-clocks-city {
font-weight: bold;
font-size: 0.9em;
}
.world-clocks-time {
color: darken($fg_color,20%);
font-feature-settings: "tnum";
font-size: 1.2em;
}
.world-clocks-timezone {
color: darken($fg_color,40%);
font-feature-settings: "tnum";
font-size: 0.9em;
}
.weather-forecast-icon {
icon-size: 2.18em;
}
.weather-forecast-time {
color: darken($fg_color,40%);
font-size: 0.8em;
}
.calendar-month-label {
color: darken($fg_color,5%);
font-weight: bold;
@ -1042,6 +1031,11 @@ StScrollBar {
-st-icon-style: symbolic;
}
.message-icon-bin > .fallback-window-icon {
width: 1.09em;
height: 1.09em;
}
.message-secondary-bin {
padding: 0 0.82em;;
}
@ -1084,18 +1078,14 @@ StScrollBar {
background-color: $bg_color;
border: 2px solid $bg_color;
border-radius: 2px;
icon-size: 16px;
padding: 8px; }
icon-size: 32px !important;
padding: 6px; }
}
// a little unstructured mess:
.system-switch-user-submenu-icon.user-icon {
icon-size: 20px;
padding: 0 2px;
}
.system-switch-user-submenu-icon.default-icon {
.system-switch-user-submenu-icon {
icon-size: 16px;
padding: 0 4px;
}
@ -1107,6 +1097,11 @@ StScrollBar {
.label-shadow { color: transparent; }
}
.app-menu,
.app-well-menu {
max-width: 27.25em;
}
.aggregate-menu {
min-width: 21em;
.popup-menu-icon { padding: 0 4px; }
@ -1147,8 +1142,14 @@ StScrollBar {
.ripple-box:rtl { border-radius: 0 0 0 52px; } // just a simple change to the border radius position
// Rubberband for select-area screenshots
.select-area-rubberband {
background-color: transparentize($selected_bg_color,0.7);
border: 1px solid $selected_bg_color;
}
// not really top bar only
.popup-menu-arrow { width: 16px; height: 16px; }
.popup-menu-arrow { icon-size: 1.09em; }
.popup-menu-icon { icon-size: 1.09em; }
//close buttons
@ -1294,6 +1295,8 @@ StScrollBar {
.search-section-separator { height: 2px; background-color: rgba(255, 255, 255, 0.2); }
.search-section:last-child .search-section-separator { background-color: transparent; }
.list-search-result-content { spacing: 30px; }
.list-search-result-title { color: darken($osd_fg_color,5%); spacing: 12px; }
.list-search-result-description { color: transparentize(darken($osd_fg_color,15%), 0.5); }
@ -1456,13 +1459,13 @@ StScrollBar {
height: 12px;
background-color: transparent;
border: 2px solid rgba(255, 255, 255, 0.4);
border-radius:12px;
border-radius: 12px;
}
&:hover .page-indicator-icon { border-color: white; }
&:active .page-indicator-icon { border: none; margin: 2px; background-color:#fff; }
&:active .page-indicator-icon { border: none; margin: 2px; background-color: white; }
&:checked .page-indicator-icon,
&:checked:active { background-color: #fff;}
&:checked:active .page-indicator-icon { background-color: white;}
}
.no-frequent-applications-label { @extend %status_text; }
@ -1646,6 +1649,15 @@ StScrollBar {
#keyboard {
background-color: transparentize($osd_bg_color, 0.3);
.page-indicator {
padding: 4px 4px;
.page-indicator-icon {
width: 6px;
height: 6px
}
}
}
.key-container {
@ -1655,8 +1667,8 @@ StScrollBar {
.keyboard-key {
background-color: #393f3f;
min-height: 2em;
min-width: 2em;
min-height: 1.2em;
min-width: 1.2em;
font-size: 16pt;
border-radius: 3px;
border: 1px solid #464d4d;
@ -1707,6 +1719,20 @@ StScrollBar {
-boxpointer-gap: 5px;
}
.emoji-page {
.keyboard-key {
background-color: transparent;
border: none;
}
}
.emoji-panel {
.keyboard-key:latched {
border-color: #005684;
background-color: #006098;
}
}
// IBus Candidate Popup
.candidate-popup-content {
@ -1741,13 +1767,11 @@ StScrollBar {
/* Auth Dialogs & Screen Shield */
.framed-user-icon {
.user-icon {
background-size: contain;
border: 2px solid $osd_fg_color;
color: $osd_fg_color;
border-radius: 3px;
border-radius: 99px;
&:hover {
border-color: lighten($osd_fg_color,30%);
color: lighten($osd_fg_color,30%);
}
}

View File

@ -111,7 +111,7 @@
}
}
@mixin button($t, $c:$osd_bg_color, $tc:$fg_color, $edge: $borders_edge) {
@mixin button($t, $c:opacify(lighten($osd_bg_color, 5%),1.0), $tc:$fg_color, $edge: $borders_edge) {
//
// Button drawing function
//
@ -136,8 +136,7 @@
//
// normal button
//
$_bg: if($c!=$osd_bg_color, transparentize($c, 0.5),
$osd_bg_color);
$_bg: $c;
color: $osd_fg_color;
background-color: $_bg;
@ -150,8 +149,7 @@
//
// focused button
//
$_bg: if($c!=$osd_bg_color, transparentize($c, 0.3),
lighten($osd_bg_color,3%));
$_bg: lighten($c,3%);
color: $osd_fg_color;
text-shadow: 0 1px black;
@ -163,8 +161,7 @@
//
// active osd button
//
$_bg: if($c!=$osd_bg_color, transparentize($c, 0.3),
lighten($osd_bg_color,3%));
$_bg: lighten($c,3%);
color: white;
border-color: $osd_borders_color;

View File

@ -40,6 +40,7 @@ do
done
cat >>$TMP_GRESOURCE_FILE <<EOF
<file>emoji.json</file>
</gresource>
</gresources>
EOF

View File

@ -1,12 +1,5 @@
const Lang = imports.lang;
const Gettext = imports.gettext;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Gio = imports.gi.Gio;
const Gtk = imports.gi.Gtk;
const Gdk = imports.gi.Gdk;
const Pango = imports.gi.Pango;
const { Gdk, GLib, Gio, GObject, Gtk, Pango } = imports.gi;
const Format = imports.format;
const _ = Gettext.gettext;
@ -24,9 +17,8 @@ function stripPrefix(string, prefix) {
return string;
}
var Application = new Lang.Class({
Name: 'Application',
_init() {
var Application = class {
constructor() {
GLib.set_prgname('gnome-shell-extension-prefs');
this.application = new Gtk.Application({
application_id: 'org.gnome.shell.ExtensionPrefs',
@ -42,7 +34,7 @@ var Application = new Lang.Class({
this._startupUuid = null;
this._loaded = false;
this._skipMainWindow = false;
},
}
_extensionAvailable(uuid) {
let extension = ExtensionUtils.extensions[uuid];
@ -54,7 +46,7 @@ var Application = new Lang.Class({
return false;
return true;
},
}
_getExtensionPrefsModule(extension) {
let uuid = extension.metadata.uuid;
@ -69,7 +61,7 @@ var Application = new Lang.Class({
this._extensionPrefsModules[uuid] = prefsModule;
return prefsModule;
},
}
_selectExtension(uuid) {
if (!this._extensionAvailable(uuid))
@ -104,33 +96,115 @@ var Application = new Lang.Class({
dialog.set_default_size(600, 400);
dialog.add(widget);
dialog.show();
},
}
_buildErrorUI(extension, exc) {
let box = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL });
let scroll = new Gtk.ScrolledWindow({
hscrollbar_policy: Gtk.PolicyType.NEVER,
propagate_natural_height: true
});
let box = new Gtk.Box({
orientation: Gtk.Orientation.VERTICAL,
spacing: 12,
margin: 100,
margin_bottom: 60
});
scroll.add(box);
let label = new Gtk.Label({
label: _("There was an error loading the preferences dialog for %s:").format(extension.metadata.name)
label: '<span size="x-large">%s</span>'.format(_("Somethings gone wrong")),
use_markup: true
});
label.get_style_context().add_class(Gtk.STYLE_CLASS_DIM_LABEL);
box.add(label);
label = new Gtk.Label({
label: _("Were very sorry, but theres been a problem: the settings for this extension cant be displayed. We recommend that you report the issue to the extension authors."),
justify: Gtk.Justification.CENTER,
wrap: true
});
box.add(label);
let errortext = '';
errortext += exc;
errortext += '\n\n';
errortext += 'Stack trace:\n';
let expander = new Expander({
label: _("Technical Details"),
margin_top: 12
});
box.add(expander);
// Indent stack trace.
errortext += exc.stack.split('\n').map(line => ' ' + line).join('\n');
let errortext = `${exc}\n\nStack trace:\n${
// Indent stack trace.
exc.stack.split('\n').map(line => ` ${line}`).join('\n')
}`;
let scroll = new Gtk.ScrolledWindow({ vexpand: true });
let buffer = new Gtk.TextBuffer({ text: errortext });
let textview = new Gtk.TextView({ buffer: buffer });
textview.override_font(Pango.font_description_from_string('monospace'));
scroll.add(textview);
box.add(scroll);
let textview = new Gtk.TextView({
buffer: buffer,
wrap_mode: Gtk.WrapMode.WORD,
monospace: true,
editable: false,
top_margin: 12,
bottom_margin: 12,
left_margin: 12,
right_margin: 12
});
box.show_all();
return box;
},
let toolbar = new Gtk.Toolbar();
let provider = new Gtk.CssProvider();
provider.load_from_data(`* {
border: 0 solid @borders;
border-top-width: 1px;
}`);
toolbar.get_style_context().add_provider(
provider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
);
let copyButton = new Gtk.ToolButton({
icon_name: 'edit-copy-symbolic',
tooltip_text: _("Copy Error")
});
toolbar.add(copyButton);
copyButton.connect('clicked', w => {
let clipboard = Gtk.Clipboard.get_default(w.get_display());
let backticks = '```';
clipboard.set_text(
// markdown for pasting in gitlab issues
`The settings of extension ${extension.uuid} had an error:\n${
backticks}\n${exc}\n${backticks}\n\nStack trace:\n${
backticks}\n${exc.stack}${backticks}\n`, -1
);
});
let spacing = new Gtk.SeparatorToolItem({ draw: false });
toolbar.add(spacing);
toolbar.child_set_property(spacing, "expand", true);
let urlButton = new Gtk.ToolButton({
label: _("Homepage"),
tooltip_text: _("Visit extension homepage"),
no_show_all: true,
visible: extension.metadata.url != null
});
toolbar.add(urlButton);
urlButton.connect('clicked', w => {
let context = w.get_display().get_app_launch_context();
Gio.AppInfo.launch_default_for_uri(extension.metadata.url, context);
});
let expandedBox = new Gtk.Box({
orientation: Gtk.Orientation.VERTICAL
});
expandedBox.add(textview);
expandedBox.add(toolbar);
expander.add(expandedBox);
scroll.show_all();
return scroll;
}
_buildUI(app) {
this._window = new Gtk.ApplicationWindow({ application: app,
@ -150,8 +224,12 @@ var Application = new Lang.Class({
Gio.SettingsBindFlags.DEFAULT |
Gio.SettingsBindFlags.INVERT_BOOLEAN);
this._mainStack = new Gtk.Stack({
transition_type: Gtk.StackTransitionType.CROSSFADE
});
this._window.add(this._mainStack);
let scroll = new Gtk.ScrolledWindow({ hscrollbar_policy: Gtk.PolicyType.NEVER });
this._window.add(scroll);
this._extensionSelector = new Gtk.ListBox({ selection_mode: Gtk.SelectionMode.NONE });
this._extensionSelector.set_sort_func(this._sortList.bind(this));
@ -159,6 +237,8 @@ var Application = new Lang.Class({
scroll.add(this._extensionSelector);
this._mainStack.add_named(scroll, 'listing');
this._mainStack.add_named(new EmptyPlaceholder(), 'placeholder');
this._shellProxy = new GnomeShellProxy(Gio.DBus.session, 'org.gnome.Shell', '/org/gnome/Shell');
this._shellProxy.connectSignal('ExtensionStatusChanged', (proxy, senderName, [uuid, state, error]) => {
@ -167,13 +247,13 @@ var Application = new Lang.Class({
});
this._window.show_all();
},
}
_sortList(row1, row2) {
let name1 = ExtensionUtils.extensions[row1.uuid].metadata.name;
let name2 = ExtensionUtils.extensions[row2.uuid].metadata.name;
return name1.localeCompare(name2);
},
}
_updateHeader(row, before) {
if (!before || row.get_header())
@ -181,14 +261,14 @@ var Application = new Lang.Class({
let sep = new Gtk.Separator({ orientation: Gtk.Orientation.HORIZONTAL });
row.set_header(sep);
},
}
_scanExtensions() {
let finder = new ExtensionUtils.ExtensionFinder();
finder.connect('extension-found', this._extensionFound.bind(this));
finder.scanExtensions();
this._extensionsLoaded();
},
}
_extensionFound(finder, extension) {
let row = new ExtensionRow(extension.uuid);
@ -200,24 +280,29 @@ var Application = new Lang.Class({
row.show_all();
this._extensionSelector.add(row);
},
}
_extensionsLoaded() {
if (this._extensionSelector.get_children().length > 0)
this._mainStack.visible_child_name = 'listing';
else
this._mainStack.visible_child_name = 'placeholder';
if (this._startupUuid && this._extensionAvailable(this._startupUuid))
this._selectExtension(this._startupUuid);
this._startupUuid = null;
this._skipMainWindow = false;
this._loaded = true;
},
}
_onActivate() {
this._window.present();
},
}
_onStartup(app) {
this._buildUI(app);
this._scanExtensions();
},
}
_onCommandLine(app, commandLine) {
app.activate();
@ -240,26 +325,187 @@ var Application = new Lang.Class({
}
return 0;
}
});
};
var DescriptionLabel = new Lang.Class({
Name: 'DescriptionLabel',
Extends: Gtk.Label,
var Expander = GObject.registerClass({
Properties: {
'label': GObject.ParamSpec.string(
'label', 'label', 'label',
GObject.ParamFlags.READWRITE,
null
)
}
}, class Expander extends Gtk.Box {
_init(params = {}) {
this._labelText = null;
vfunc_get_preferred_height_for_width(width) {
// Hack: Request the maximum height allowed by the line limit
if (this.lines > 0)
return this.parent(0);
return this.parent(width);
super._init(Object.assign(params, {
orientation: Gtk.Orientation.VERTICAL,
spacing: 0
}));
this._frame = new Gtk.Frame({
shadow_type: Gtk.ShadowType.IN,
hexpand: true
});
let eventBox = new Gtk.EventBox();
this._frame.add(eventBox);
let hbox = new Gtk.Box({
spacing: 6,
margin: 12
});
eventBox.add(hbox);
this._arrow = new Gtk.Image({
icon_name: 'pan-end-symbolic'
});
hbox.add(this._arrow);
this._label = new Gtk.Label({ label: this._labelText });
hbox.add(this._label);
this._revealer = new Gtk.Revealer();
this._childBin = new Gtk.Frame({
shadow_type: Gtk.ShadowType.IN
});
this._revealer.add(this._childBin);
// Directly chain up to parent for internal children
super.add(this._frame);
super.add(this._revealer);
let provider = new Gtk.CssProvider();
provider.load_from_data('* { border-top-width: 0; }');
this._childBin.get_style_context().add_provider(
provider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
);
this._gesture = new Gtk.GestureMultiPress({
widget: this._frame,
button: 0,
exclusive: true
});
this._gesture.connect('released', (gesture, nPress) => {
if (nPress == 1)
this._revealer.reveal_child = !this._revealer.reveal_child;
});
this._revealer.connect('notify::reveal-child', () => {
if (this._revealer.reveal_child)
this._arrow.icon_name = 'pan-down-symbolic';
else
this._arrow.icon_name = 'pan-end-symbolic';
});
}
get label() {
return this._labelText;
}
set label(text) {
if (this._labelText == text)
return;
if (this._label)
this._label.label = text;
this._labelText = text;
this.notify('label');
}
add(child) {
// set expanded child
this._childBin.get_children().forEach(c => {
this._childBin.remove(c);
});
if (child)
this._childBin.add(child);
}
});
var ExtensionRow = new Lang.Class({
Name: 'ExtensionRow',
Extends: Gtk.ListBoxRow,
var EmptyPlaceholder = GObject.registerClass(
class EmptyPlaceholder extends Gtk.Box {
_init() {
super._init({
orientation: Gtk.Orientation.VERTICAL,
spacing: 6,
margin: 32
});
let image = new Gtk.Image({
icon_name: 'application-x-addon-symbolic',
pixel_size: 96,
visible: true,
vexpand: true,
valign: Gtk.Align.END
});
image.get_style_context().add_class(Gtk.STYLE_CLASS_DIM_LABEL);
this.add(image);
let label = new Gtk.Label({
label: `<b><span size="x-large">${_("No Extensions Installed" )}</span></b>`,
use_markup: true,
visible: true
});
label.get_style_context().add_class(Gtk.STYLE_CLASS_DIM_LABEL);
this.add(label);
let appInfo = Gio.DesktopAppInfo.new('org.gnome.Software.desktop');
let desc = new Gtk.Label({
label: _("Extensions can be installed through Software or <a href=\"https://extensions.gnome.org\">extensions.gnome.org</a>."),
use_markup: true,
wrap: true,
justify: Gtk.Justification.CENTER,
visible: true,
max_width_chars: 50,
hexpand: true,
vexpand: (appInfo == null),
halign: Gtk.Align.CENTER,
valign: Gtk.Align.START
});
this.add(desc);
if (appInfo) {
let button = new Gtk.Button({
label: _("Browse in Software"),
image: new Gtk.Image({
icon_name: "org.gnome.Software-symbolic"
}),
always_show_image: true,
margin_top: 12,
visible: true,
halign: Gtk.Align.CENTER,
valign: Gtk.Align.START,
vexpand: true
});
this.add(button);
button.connect('clicked', w => {
let context = w.get_display().get_app_launch_context();
appInfo.launch([], context);
});
}
}
});
var DescriptionLabel = GObject.registerClass(
class DescriptionLabel extends Gtk.Label {
vfunc_get_preferred_height_for_width(width) {
// Hack: Request the maximum height allowed by the line limit
if (this.lines > 0)
return super.vfunc_get_preferred_height_for_width(0);
return super.vfunc_get_preferred_height_for_width(width);
}
});
var ExtensionRow = GObject.registerClass(
class ExtensionRow extends Gtk.ListBoxRow {
_init(uuid) {
this.parent();
super._init();
this.uuid = uuid;
@ -277,7 +523,7 @@ var ExtensionRow = new Lang.Class({
});
this._buildUI();
},
}
_buildUI() {
let extension = ExtensionUtils.extensions[this.uuid];
@ -305,9 +551,9 @@ var ExtensionRow = new Lang.Class({
let button = new Gtk.Button({ valign: Gtk.Align.CENTER,
no_show_all: true });
button.add(new Gtk.Image({ icon_name: 'emblem-system-symbolic',
icon_size: Gtk.IconSize.BUTTON,
visible: true }));
button.set_image(new Gtk.Image({ icon_name: 'emblem-system-symbolic',
icon_size: Gtk.IconSize.BUTTON,
visible: true }));
button.get_style_context().add_class('circular');
hbox.add(button);
@ -324,7 +570,7 @@ var ExtensionRow = new Lang.Class({
});
this._switch.connect('state-set', () => true);
hbox.add(this._switch);
},
}
_canEnable() {
let extension = ExtensionUtils.extensions[this.uuid];
@ -332,12 +578,12 @@ var ExtensionRow = new Lang.Class({
return !this._settings.get_boolean('disable-user-extensions') &&
!(checkVersion && ExtensionUtils.isOutOfDate(extension));
},
}
_isEnabled() {
let extensions = this._settings.get_strv('enabled-extensions');
return extensions.indexOf(this.uuid) != -1;
},
}
_enable() {
let extensions = this._settings.get_strv('enabled-extensions');
@ -346,7 +592,7 @@ var ExtensionRow = new Lang.Class({
extensions.push(this.uuid);
this._settings.set_strv('enabled-extensions', extensions);
},
}
_disable() {
let extensions = this._settings.get_strv('enabled-extensions');

View File

@ -1,11 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const Pango = imports.gi.Pango;
const { Clutter, Pango, Shell, St } = imports.gi;
const Signals = imports.signals;
const St = imports.gi.St;
const Animation = imports.ui.animation;
const Batch = imports.gdm.batch;
@ -38,10 +34,8 @@ var BeginRequestType = {
DONT_PROVIDE_USERNAME: 1
};
var AuthPrompt = new Lang.Class({
Name: 'AuthPrompt',
_init(gdmClient, mode) {
var AuthPrompt = class {
constructor(gdmClient, mode) {
this.verificationStatus = AuthPromptStatus.NOT_VERIFYING;
this._gdmClient = gdmClient;
@ -99,7 +93,7 @@ var AuthPrompt = new Lang.Class({
x_align: St.Align.START });
this._entry = new St.Entry({ style_class: 'login-dialog-prompt-entry',
can_focus: true });
ShellEntry.addContextMenu(this._entry, { isPassword: true });
ShellEntry.addContextMenu(this._entry, { isPassword: true, actionMode: Shell.ActionMode.NONE });
this.actor.add(this._entry,
{ expand: true,
@ -127,17 +121,16 @@ var AuthPrompt = new Lang.Class({
this._initButtons();
let spinnerIcon = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/process-working.svg');
this._spinner = new Animation.AnimatedIcon(spinnerIcon, DEFAULT_BUTTON_WELL_ICON_SIZE);
this._spinner = new Animation.Spinner(DEFAULT_BUTTON_WELL_ICON_SIZE);
this._spinner.actor.opacity = 0;
this._spinner.actor.show();
this._defaultButtonWell.add_child(this._spinner.actor);
},
}
_onDestroy() {
this._userVerifier.destroy();
this._userVerifier = null;
},
}
_initButtons() {
this.cancelButton = new St.Button({ style_class: 'modal-dialog-button button',
@ -185,7 +178,7 @@ var AuthPrompt = new Lang.Class({
if (this.nextButton.reactive)
this.emit('next');
});
},
}
_onAskQuestion(verifier, serviceName, question, passwordChar) {
if (this._queryingService)
@ -211,12 +204,12 @@ var AuthPrompt = new Lang.Class({
this.updateSensitivity(true);
this.emit('prompted');
},
}
_onOVirtUserAuthenticated() {
if (this.verificationStatus != AuthPromptStatus.VERIFICATION_SUCCEEDED)
this.reset();
},
}
_onSmartcardStatusChanged() {
this.smartcardDetected = this._userVerifier.smartcardDetected;
@ -235,12 +228,12 @@ var AuthPrompt = new Lang.Class({
if (this.verificationStatus != AuthPromptStatus.VERIFICATION_SUCCEEDED)
this.reset();
},
}
_onShowMessage(userVerifier, message, type) {
this.setMessage(message, type);
this.emit('prompted');
},
}
_onVerificationFailed(userVerifier, canRetry) {
this._queryingService = null;
@ -249,22 +242,22 @@ var AuthPrompt = new Lang.Class({
this.updateSensitivity(canRetry);
this.setActorInDefaultButtonWell(null);
this.verificationStatus = AuthPromptStatus.VERIFICATION_FAILED;
},
}
_onVerificationComplete() {
this.setActorInDefaultButtonWell(null);
this.verificationStatus = AuthPromptStatus.VERIFICATION_SUCCEEDED;
this.cancelButton.reactive = false;
},
}
_onReset() {
this.verificationStatus = AuthPromptStatus.NOT_VERIFYING;
this.reset();
},
}
addActorToDefaultButtonWell(actor) {
this._defaultButtonWell.add_child(actor);
},
}
setActorInDefaultButtonWell(actor, animate) {
if (!this._defaultButtonWellActor &&
@ -328,25 +321,25 @@ var AuthPrompt = new Lang.Class({
}
this._defaultButtonWellActor = actor;
},
}
startSpinning() {
this.setActorInDefaultButtonWell(this._spinner.actor, true);
},
}
stopSpinning() {
this.setActorInDefaultButtonWell(null, false);
},
}
clear() {
this._entry.text = '';
this.stopSpinning();
},
}
setPasswordChar(passwordChar) {
this._entry.clutter_text.set_password_char(passwordChar);
this._entry.menu.isPassword = passwordChar != '';
},
}
setQuestion(question) {
this._label.set_text(question);
@ -355,7 +348,7 @@ var AuthPrompt = new Lang.Class({
this._entry.show();
this._entry.grab_key_focus();
},
}
getAnswer() {
let text;
@ -368,7 +361,7 @@ var AuthPrompt = new Lang.Class({
}
return text;
},
}
_fadeOutMessage() {
if (this._message.opacity == 0)
@ -379,7 +372,7 @@ var AuthPrompt = new Lang.Class({
time: MESSAGE_FADE_OUT_ANIMATION_TIME,
transition: 'easeOutQuad'
});
},
}
setMessage(message, type) {
if (type == GdmUtil.MessageType.ERROR)
@ -399,18 +392,18 @@ var AuthPrompt = new Lang.Class({
} else {
this._message.opacity = 0;
}
},
}
_updateNextButtonSensitivity(sensitive) {
this.nextButton.reactive = sensitive;
this.nextButton.can_focus = sensitive;
},
}
updateSensitivity(sensitive) {
this._updateNextButtonSensitivity(sensitive && (this._entry.text.length > 0 || this.verificationStatus == AuthPromptStatus.VERIFYING));
this._entry.reactive = sensitive;
this._entry.clutter_text.editable = sensitive;
},
}
hide() {
this.setActorInDefaultButtonWell(null, true);
@ -421,7 +414,7 @@ var AuthPrompt = new Lang.Class({
this.updateSensitivity(true);
this._entry.set_text('');
},
}
setUser(user) {
let oldChild = this._userWell.get_child();
@ -432,7 +425,7 @@ var AuthPrompt = new Lang.Class({
let userWidget = new UserWidget.UserWidget(user);
this._userWell.set_child(userWidget.actor);
}
},
}
reset() {
let oldStatus = this.verificationStatus;
@ -470,7 +463,7 @@ var AuthPrompt = new Lang.Class({
}
this.emit('reset', beginRequestType);
},
}
addCharacter(unichar) {
if (!this._entry.visible)
@ -478,7 +471,7 @@ var AuthPrompt = new Lang.Class({
this._entry.grab_key_focus();
this._entry.clutter_text.insert_unichar(unichar);
},
}
begin(params) {
params = Params.parse(params, { userName: null,
@ -492,7 +485,7 @@ var AuthPrompt = new Lang.Class({
this._userVerifier.begin(params.userName, hold);
this.verificationStatus = AuthPromptStatus.VERIFYING;
},
}
finish(onComplete) {
if (!this._userVerifier.hasPendingMessages) {
@ -506,7 +499,7 @@ var AuthPrompt = new Lang.Class({
this._userVerifier.clear();
onComplete();
});
},
}
cancel() {
if (this.verificationStatus == AuthPromptStatus.VERIFICATION_SUCCEEDED) {
@ -515,5 +508,5 @@ var AuthPrompt = new Lang.Class({
this.reset();
this.emit('cancelled');
}
});
};
Signals.addSignalMethods(AuthPrompt.prototype);

View File

@ -44,45 +44,39 @@
* replaced by something else.
*/
const Lang = imports.lang;
const Signals = imports.signals;
var Task = new Lang.Class({
Name: 'Task',
_init(scope, handler) {
var Task = class {
constructor(scope, handler) {
if (scope)
this.scope = scope;
else
this.scope = this;
this.handler = handler;
},
}
run() {
if (this.handler)
return this.handler.call(this.scope);
return null;
},
});
}
};
Signals.addSignalMethods(Task.prototype);
var Hold = new Lang.Class({
Name: 'Hold',
Extends: Task,
_init() {
this.parent(this, () => this);
var Hold = class extends Task {
constructor() {
super(null, () => this);
this._acquisitions = 1;
},
}
acquire() {
if (this._acquisitions <= 0)
throw new Error("Cannot acquire hold after it's been released");
this._acquisitions++;
},
}
acquireUntilAfter(hold) {
if (!hold.isAcquired())
@ -93,27 +87,24 @@ var Hold = new Lang.Class({
hold.disconnect(signalId);
this.release();
});
},
}
release() {
this._acquisitions--;
if (this._acquisitions == 0)
this.emit('release');
},
}
isAcquired() {
return this._acquisitions > 0;
}
});
};
Signals.addSignalMethods(Hold.prototype);
var Batch = new Lang.Class({
Name: 'Batch',
Extends: Task,
_init(scope, tasks) {
this.parent();
var Batch = class extends Task {
constructor(scope, tasks) {
super();
this.tasks = [];
@ -130,11 +121,11 @@ var Batch = new Lang.Class({
this.tasks.push(task);
}
},
}
process() {
throw new Error('Not implemented');
},
}
runTask() {
if (!(this._currentTaskIndex in this.tasks)) {
@ -142,11 +133,11 @@ var Batch = new Lang.Class({
}
return this.tasks[this._currentTaskIndex].run();
},
}
_finish() {
this.hold.release();
},
}
nextTask() {
this._currentTaskIndex++;
@ -159,7 +150,7 @@ var Batch = new Lang.Class({
}
this.process();
},
}
_start() {
// acquire a hold to get released when the entire
@ -167,7 +158,7 @@ var Batch = new Lang.Class({
this.hold = new Hold();
this._currentTaskIndex = 0;
this.process();
},
}
run() {
this._start();
@ -175,18 +166,15 @@ var Batch = new Lang.Class({
// hold may be destroyed at this point
// if we're already done running
return this.hold;
},
}
cancel() {
this.tasks = this.tasks.splice(0, this._currentTaskIndex + 1);
}
});
};
Signals.addSignalMethods(Batch.prototype);
var ConcurrentBatch = new Lang.Class({
Name: 'ConcurrentBatch',
Extends: Batch,
var ConcurrentBatch = class extends Batch {
process() {
let hold = this.runTask();
@ -199,13 +187,10 @@ var ConcurrentBatch = new Lang.Class({
// concurrently.
this.nextTask();
}
});
};
Signals.addSignalMethods(ConcurrentBatch.prototype);
var ConsecutiveBatch = new Lang.Class({
Name: 'ConsecutiveBatch',
Extends: Batch,
var ConsecutiveBatch = class extends Batch {
process() {
let hold = this.runTask();
@ -222,5 +207,5 @@ var ConsecutiveBatch = new Lang.Class({
this.nextTask();
}
}
});
};
Signals.addSignalMethods(ConsecutiveBatch.prototype);

View File

@ -1,9 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const FprintManagerIface = `
<node>

View File

@ -16,20 +16,9 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
const AccountsService = imports.gi.AccountsService;
const Atk = imports.gi.Atk;
const Clutter = imports.gi.Clutter;
const Gdm = imports.gi.Gdm;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
const Meta = imports.gi.Meta;
const Pango = imports.gi.Pango;
const Shell = imports.gi.Shell;
const { AccountsService, Atk, Clutter, Gdm, Gio,
GLib, GObject, Meta, Pango, Shell, St } = imports.gi;
const Signals = imports.signals;
const St = imports.gi.St;
const AuthPrompt = imports.gdm.authPrompt;
const Batch = imports.gdm.batch;
@ -50,10 +39,8 @@ const _TIMED_LOGIN_IDLE_THRESHOLD = 5.0;
const _LOGO_ICON_HEIGHT = 48;
const _MAX_BOTTOM_MENU_ITEMS = 5;
var UserListItem = new Lang.Class({
Name: 'UserListItem',
_init(user) {
var UserListItem = class {
constructor(user) {
this.user = user;
this._userChangedId = this.user.connect('changed',
this._onUserChanged.bind(this));
@ -91,26 +78,26 @@ var UserListItem = new Lang.Class({
this.actor.connect('clicked', this._onClicked.bind(this));
this._onUserChanged();
},
}
_onUserChanged() {
this._updateLoggedIn();
},
}
_updateLoggedIn() {
if (this.user.is_logged_in())
this.actor.add_style_pseudo_class('logged-in');
else
this.actor.remove_style_pseudo_class('logged-in');
},
}
_onDestroy() {
this.user.disconnect(this._userChangedId);
},
}
_onClicked() {
this.emit('activate');
},
}
_setSelected(selected) {
if (selected) {
@ -119,7 +106,7 @@ var UserListItem = new Lang.Class({
} else {
this.actor.remove_style_pseudo_class('selected');
}
},
}
showTimedLoginIndicator(time) {
let hold = new Batch.Hold();
@ -147,7 +134,7 @@ var UserListItem = new Lang.Class({
GLib.Source.set_name_by_id(this._timedLoginTimeoutId, '[gnome-shell] this._timedLoginTimeoutId');
return hold;
},
}
hideTimedLoginIndicator() {
if (this._timedLoginTimeoutId) {
@ -158,16 +145,14 @@ var UserListItem = new Lang.Class({
this._timedLoginIndicator.visible = false;
this._timedLoginIndicator.scale_x = 0.;
}
});
};
Signals.addSignalMethods(UserListItem.prototype);
var UserList = new Lang.Class({
Name: 'UserList',
_init() {
var UserList = class {
constructor() {
this.actor = new St.ScrollView({ style_class: 'login-dialog-user-list-view'});
this.actor.set_policy(Gtk.PolicyType.NEVER,
Gtk.PolicyType.AUTOMATIC);
this.actor.set_policy(St.PolicyType.NEVER,
St.PolicyType.AUTOMATIC);
this._box = new St.BoxLayout({ vertical: true,
style_class: 'login-dialog-user-list',
@ -177,7 +162,7 @@ var UserList = new Lang.Class({
this._items = {};
this.actor.connect('key-focus-in', this._moveFocusToItems.bind(this));
},
}
_moveFocusToItems() {
let hasItems = Object.keys(this._items).length > 0;
@ -188,18 +173,18 @@ var UserList = new Lang.Class({
if (global.stage.get_key_focus() != this.actor)
return;
let focusSet = this.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
let focusSet = this.actor.navigate_focus(null, St.DirectionType.TAB_FORWARD, false);
if (!focusSet) {
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
this._moveFocusToItems();
return false;
});
}
},
}
_onItemActivated(activatedItem) {
this.emit('activate', activatedItem);
},
}
updateStyle(isExpanded) {
let tasks = [];
@ -213,7 +198,7 @@ var UserList = new Lang.Class({
let item = this._items[userName];
item.actor.sync_hover();
}
},
}
scrollToItem(item) {
let box = item.actor.get_allocation_box();
@ -226,7 +211,7 @@ var UserList = new Lang.Class({
{ value: value,
time: _SCROLL_ANIMATION_TIME,
transition: 'easeOutQuad' });
},
}
jumpToItem(item) {
let box = item.actor.get_allocation_box();
@ -236,7 +221,7 @@ var UserList = new Lang.Class({
let value = (box.y1 + adjustment.step_increment / 2.0) - (adjustment.page_size / 2.0);
adjustment.set_value(value);
},
}
getItemFromUserName(userName) {
let item = this._items[userName];
@ -245,11 +230,11 @@ var UserList = new Lang.Class({
return null;
return item;
},
}
containsUser(user) {
return this._items[user.get_user_name()] != null;
},
}
addUser(user) {
if (!user.is_loaded)
@ -281,7 +266,7 @@ var UserList = new Lang.Class({
this._moveFocusToItems();
this.emit('item-added', item);
},
}
removeUser(user) {
if (!user.is_loaded)
@ -299,18 +284,16 @@ var UserList = new Lang.Class({
item.actor.destroy();
delete this._items[userName];
},
}
numItems() {
return Object.keys(this._items).length;
}
});
};
Signals.addSignalMethods(UserList.prototype);
var SessionMenuButton = new Lang.Class({
Name: 'SessionMenuButton',
_init() {
var SessionMenuButton = class {
constructor() {
let gearIcon = new St.Icon({ icon_name: 'emblem-system-symbolic' });
this._button = new St.Button({ style_class: 'login-dialog-session-list-button',
reactive: true,
@ -342,7 +325,8 @@ var SessionMenuButton = new Lang.Class({
this._button.remove_style_pseudo_class('active');
});
this._manager = new PopupMenu.PopupMenuManager({ actor: this._button });
this._manager = new PopupMenu.PopupMenuManager({ actor: this._button },
{ actionMode: Shell.ActionMode.NONE });
this._manager.addMenu(this._menu);
this._button.connect('clicked', () => { this._menu.toggle(); });
@ -350,13 +334,13 @@ var SessionMenuButton = new Lang.Class({
this._items = {};
this._activeSessionId = null;
this._populate();
},
}
updateSensitivity(sensitive) {
this._button.reactive = sensitive;
this._button.can_focus = sensitive;
this._menu.close(BoxPointer.PopupAnimation.NONE);
},
}
_updateOrnament() {
let itemIds = Object.keys(this._items);
@ -366,7 +350,7 @@ var SessionMenuButton = new Lang.Class({
else
this._items[itemIds[i]].setOrnament(PopupMenu.Ornament.NONE);
}
},
}
setActiveSession(sessionId) {
if (sessionId == this._activeSessionId)
@ -374,11 +358,11 @@ var SessionMenuButton = new Lang.Class({
this._activeSessionId = sessionId;
this._updateOrnament();
},
}
close() {
this._menu.close();
},
}
_populate() {
let ids = Gdm.get_session_ids();
@ -403,16 +387,14 @@ var SessionMenuButton = new Lang.Class({
});
}
}
});
};
Signals.addSignalMethods(SessionMenuButton.prototype);
var LoginDialog = new Lang.Class({
Name: 'LoginDialog',
Extends: St.Widget,
var LoginDialog = GObject.registerClass({
Signals: { 'failed': {} },
}, class LoginDialog extends St.Widget {
_init(parentActor) {
this.parent({ style_class: 'login-dialog',
super._init({ style_class: 'login-dialog',
visible: false });
this.get_accessible().set_role(Atk.Role.WINDOW);
@ -482,8 +464,8 @@ var LoginDialog = new Lang.Class({
this._bannerView = new St.ScrollView({ style_class: 'login-dialog-banner-view',
opacity: 0,
vscrollbar_policy: Gtk.PolicyType.AUTOMATIC,
hscrollbar_policy: Gtk.PolicyType.NEVER });
vscrollbar_policy: St.PolicyType.AUTOMATIC,
hscrollbar_policy: St.PolicyType.NEVER });
this.add_child(this._bannerView);
let bannerBox = new St.BoxLayout({ vertical: true });
@ -499,6 +481,9 @@ 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._logoBin.connect('resource-scale-changed', () => {
this._updateLogoTexture(this._textureCache, this._logoFile);
});
this.add_child(this._logoBin);
this._updateLogo();
@ -530,7 +515,7 @@ var LoginDialog = new Lang.Class({
// focus later
this._startupCompleteId = Main.layoutManager.connect('startup-complete',
this._updateDisableUserList.bind(this));
},
}
_getBannerAllocation(dialogBox) {
let actorBox = new Clutter.ActorBox();
@ -544,7 +529,7 @@ var LoginDialog = new Lang.Class({
actorBox.y2 = actorBox.y1 + natHeight;
return actorBox;
},
}
_getLogoBinAllocation(dialogBox) {
let actorBox = new Clutter.ActorBox();
@ -558,7 +543,7 @@ var LoginDialog = new Lang.Class({
actorBox.y2 = actorBox.y1 + natHeight;
return actorBox;
},
}
_getCenterActorAllocation(dialogBox, actor) {
let actorBox = new Clutter.ActorBox();
@ -576,7 +561,7 @@ var LoginDialog = new Lang.Class({
actorBox.y2 = actorBox.y1 + natHeight;
return actorBox;
},
}
vfunc_allocate(dialogBox, flags) {
this.set_allocation(dialogBox, flags);
@ -719,7 +704,7 @@ var LoginDialog = new Lang.Class({
if (logoAllocation)
this._logoBin.allocate(logoAllocation, flags);
},
}
_ensureUserListLoaded() {
if (!this._userManager.is_loaded) {
@ -735,7 +720,7 @@ var LoginDialog = new Lang.Class({
let id = GLib.idle_add(GLib.PRIORITY_DEFAULT, this._loadUserList.bind(this));
GLib.Source.set_name_by_id(id, '[gnome-shell] _loadUserList');
}
},
}
_updateDisableUserList() {
let disableUserList = this._settings.get_boolean(GdmUtil.DISABLE_USER_LIST_KEY);
@ -750,7 +735,7 @@ var LoginDialog = new Lang.Class({
if (this._authPrompt.verificationStatus == AuthPrompt.AuthPromptStatus.NOT_VERIFYING)
this._authPrompt.reset();
}
},
}
_updateCancelButton() {
let cancelVisible;
@ -763,7 +748,7 @@ var LoginDialog = new Lang.Class({
cancelVisible = true;
this._authPrompt.cancelButton.visible = cancelVisible;
},
}
_updateBanner() {
let enabled = this._settings.get_boolean(GdmUtil.BANNER_MESSAGE_KEY);
@ -775,7 +760,7 @@ var LoginDialog = new Lang.Class({
} else {
this._bannerLabel.hide();
}
},
}
_fadeInBannerView() {
this._bannerView.show();
@ -783,33 +768,34 @@ var LoginDialog = new Lang.Class({
{ opacity: 255,
time: _FADE_ANIMATION_TIME,
transition: 'easeOutQuad' });
},
}
_hideBannerView() {
Tweener.removeTweens(this._bannerView);
this._bannerView.opacity = 0;
this._bannerView.hide();
},
}
_updateLogoTexture(cache, file) {
if (this._logoFile && !this._logoFile.equal(file))
return;
this._logoBin.destroy_all_children();
if (this._logoFile) {
if (this._logoFile && this._logoBin.resource_scale > 0) {
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
this._logoBin.add_child(this._textureCache.load_file_async(this._logoFile,
-1, _LOGO_ICON_HEIGHT,
scaleFactor));
scaleFactor,
this._logoBin.resource_scale));
}
},
}
_updateLogo() {
let path = this._settings.get_string(GdmUtil.LOGO_KEY);
this._logoFile = path ? Gio.file_new_for_path(path) : null;
this._updateLogoTexture(this._textureCache, this._logoFile);
},
}
_onPrompted() {
if (this._shouldShowSessionMenuButton()) {
@ -819,7 +805,7 @@ var LoginDialog = new Lang.Class({
this._sessionMenuButton.updateSensitivity(false);
}
this._showPrompt();
},
}
_resetGreeterProxy() {
if (GLib.getenv('GDM_GREETER_TEST') != '1') {
@ -835,7 +821,7 @@ var LoginDialog = new Lang.Class({
this._timedLoginRequestedId = this._greeter.connect('timed-login-requested',
this._onTimedLoginRequested.bind(this));
}
},
}
_onReset(authPrompt, beginRequest) {
this._resetGreeterProxy();
@ -856,11 +842,11 @@ var LoginDialog = new Lang.Class({
} else {
this._hideUserListAndBeginVerification();
}
},
}
_onDefaultSessionChanged(client, sessionId) {
this._sessionMenuButton.setActiveSession(sessionId);
},
}
_shouldShowSessionMenuButton() {
if (this._authPrompt.verificationStatus != AuthPrompt.AuthPromptStatus.VERIFYING &&
@ -871,7 +857,7 @@ var LoginDialog = new Lang.Class({
return false;
return true;
},
}
_showPrompt() {
if (this._authPrompt.actor.visible)
@ -883,7 +869,7 @@ var LoginDialog = new Lang.Class({
time: _FADE_ANIMATION_TIME,
transition: 'easeOutQuad' });
this._fadeInBannerView();
},
}
_showRealmLoginHint(realmManager, hint) {
if (!hint)
@ -896,7 +882,7 @@ var LoginDialog = new Lang.Class({
// Translators: this message is shown below the username entry field
// to clue the user in on how to login to the local network realm
this._authPrompt.setMessage(_("(e.g., user or %s)").format(hint), GdmUtil.MessageType.HINT);
},
}
_askForUsernameAndBeginVerification() {
this._authPrompt.setPasswordChar('');
@ -923,7 +909,7 @@ var LoginDialog = new Lang.Class({
this._sessionMenuButton.updateSensitivity(false);
this._authPrompt.updateSensitivity(true);
this._showPrompt();
},
}
_loginScreenSessionActivated() {
if (this.opacity == 255 && this._authPrompt.verificationStatus == AuthPrompt.AuthPromptStatus.NOT_VERIFYING)
@ -947,7 +933,7 @@ var LoginDialog = new Lang.Class({
this._authPrompt.reset();
},
onCompleteScope: this });
},
}
_gotGreeterSessionProxy(proxy) {
this._greeterSessionProxy = proxy;
@ -956,7 +942,7 @@ var LoginDialog = new Lang.Class({
if (proxy.Active)
this._loginScreenSessionActivated();
});
},
}
_startSession(serviceName) {
Tweener.addTween(this,
@ -976,11 +962,11 @@ var LoginDialog = new Lang.Class({
this._greeter.call_start_session_when_ready_sync(serviceName, true, null);
},
onCompleteScope: this });
},
}
_onSessionOpened(client, serviceName) {
this._authPrompt.finish(() => { this._startSession(serviceName); });
},
}
_waitForItemForUser(userName) {
let item = this._userList.getItemFromUserName(userName);
@ -1000,7 +986,7 @@ var LoginDialog = new Lang.Class({
hold.connect('release', () => { this._userList.disconnect(signalId); });
return hold;
},
}
_blockTimedLoginUntilIdle() {
let hold = new Batch.Hold();
@ -1013,7 +999,7 @@ var LoginDialog = new Lang.Class({
});
GLib.Source.set_name_by_id(this._timedLoginIdleTimeOutId, '[gnome-shell] this._timedLoginIdleTimeOutId');
return hold;
},
}
_startTimedLogin(userName, delay) {
let firstRun = true;
@ -1086,7 +1072,7 @@ var LoginDialog = new Lang.Class({
this._timedLoginBatch = new Batch.ConsecutiveBatch(this, tasks);
return this._timedLoginBatch.run();
},
}
_onTimedLoginRequested(client, userName, seconds) {
if (this._timedLoginBatch)
@ -1103,28 +1089,28 @@ var LoginDialog = new Lang.Class({
return Clutter.EVENT_PROPAGATE;
});
},
}
_setUserListExpanded(expanded) {
this._userList.updateStyle(expanded);
this._userSelectionBox.visible = expanded;
},
}
_hideUserList() {
this._setUserListExpanded(false);
if (this._userSelectionBox.visible)
GdmUtil.cloneAndFadeOutActor(this._userSelectionBox);
},
}
_hideUserListAskForUsernameAndBeginVerification() {
this._hideUserList();
this._askForUsernameAndBeginVerification();
},
}
_hideUserListAndBeginVerification() {
this._hideUserList();
this._authPrompt.begin();
},
}
_showUserList() {
this._ensureUserListLoaded();
@ -1134,7 +1120,7 @@ var LoginDialog = new Lang.Class({
this._setUserListExpanded(true);
this._notListedButton.show();
this._userList.actor.grab_key_focus();
},
}
_beginVerificationForItem(item) {
this._authPrompt.setUser(item.user);
@ -1145,7 +1131,7 @@ var LoginDialog = new Lang.Class({
this._authPrompt.begin({ userName: userName,
hold: hold });
return hold;
},
}
_onUserListActivated(activatedItem) {
this._user = activatedItem.user;
@ -1155,7 +1141,7 @@ var LoginDialog = new Lang.Class({
let batch = new Batch.ConcurrentBatch(this, [GdmUtil.cloneAndFadeOutActor(this._userSelectionBox),
this._beginVerificationForItem(activatedItem)]);
batch.run();
},
}
_onDestroy() {
if (this._userManagerLoadedId) {
@ -1196,7 +1182,7 @@ var LoginDialog = new Lang.Class({
this._realmManager.release();
this._realmManager = null;
}
},
}
_loadUserList() {
if (this._userListLoaded)
@ -1234,7 +1220,7 @@ var LoginDialog = new Lang.Class({
});
return GLib.SOURCE_REMOVE;
},
}
open() {
Main.ctrlAltTabManager.addGroup(this,
@ -1253,22 +1239,22 @@ var LoginDialog = new Lang.Class({
transition: 'easeInQuad' });
return true;
},
}
close() {
Main.popModal(this);
Main.ctrlAltTabManager.removeGroup(this);
},
}
cancel() {
this._authPrompt.cancel();
},
}
addCharacter(unichar) {
// Don't allow type ahead at the login screen
},
}
finish(onComplete) {
this._authPrompt.finish(onComplete);
},
}
});

View File

@ -1,7 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const Signals = imports.signals;
const OVirtCredentialsIface = `
@ -28,33 +27,32 @@ function OVirtCredentials() {
return self;
}
var OVirtCredentialsManager = new Lang.Class({
Name: 'OVirtCredentialsManager',
_init() {
var OVirtCredentialsManager = class {
constructor() {
this._token = null;
this._credentials = new OVirtCredentials();
this._credentials.connectSignal('UserAuthenticated',
this._onUserAuthenticated.bind(this));
},
}
_onUserAuthenticated(proxy, sender, [token]) {
this._token = token;
this.emit('user-authenticated', token);
},
}
hasToken() {
return this._token != null;
},
}
getToken() {
return this._token;
},
}
resetToken() {
this._token = null;
}
});
};
Signals.addSignalMethods(OVirtCredentialsManager.prototype);
function getOVirtCredentialsManager() {

View File

@ -1,8 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const { loadInterfaceXML } = imports.misc.fileUtils;
@ -16,10 +14,8 @@ const Service = Gio.DBusProxy.makeProxyWrapper(ServiceIface);
const RealmIface = loadInterfaceXML("org.freedesktop.realmd.Realm");
const Realm = Gio.DBusProxy.makeProxyWrapper(RealmIface);
var Manager = new Lang.Class({
Name: 'Manager',
_init(parentActor) {
var Manager = class {
constructor(parentActor) {
this._aggregateProvider = Provider(Gio.DBus.system,
'org.freedesktop.realmd',
'/org/freedesktop/realmd',
@ -31,7 +27,7 @@ var Manager = new Lang.Class({
if ('Realms' in properties.deep_unpack())
this._reloadRealms();
});
},
}
_reloadRealms() {
let realmPaths = this._aggregateProvider.Realms;
@ -45,7 +41,7 @@ var Manager = new Lang.Class({
realmPaths[i],
this._onRealmLoaded.bind(this));
}
},
}
_reloadRealm(realm) {
if (!realm.Configured) {
@ -58,7 +54,7 @@ var Manager = new Lang.Class({
this._realms[realm.get_object_path()] = realm;
this._updateLoginFormat();
},
}
_onRealmLoaded(realm, error) {
if (error)
@ -70,7 +66,7 @@ var Manager = new Lang.Class({
if ('Configured' in properties.deep_unpack())
this._reloadRealm(realm);
});
},
}
_updateLoginFormat() {
let newLoginFormat;
@ -87,7 +83,7 @@ var Manager = new Lang.Class({
this._loginFormat = newLoginFormat;
this.emit('login-format-changed', newLoginFormat);
}
},
}
get loginFormat() {
if (this._loginFormat !== undefined)
@ -96,7 +92,7 @@ var Manager = new Lang.Class({
this._updateLoginFormat();
return this._loginFormat;
},
}
release() {
Service(Gio.DBus.system,
@ -107,5 +103,5 @@ var Manager = new Lang.Class({
this._realms = { };
this._updateLoginFormat();
}
});
};
Signals.addSignalMethods(Manager.prototype)

View File

@ -1,19 +1,13 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const { Clutter, Gio, GLib } = imports.gi;
const Signals = imports.signals;
const St = imports.gi.St;
const Batch = imports.gdm.batch;
const Fprint = imports.gdm.fingerprint;
const OVirt = imports.gdm.oVirt;
const Main = imports.ui.main;
const Params = imports.misc.params;
const ShellEntry = imports.ui.shellEntry;
const SmartcardManager = imports.misc.smartcardManager;
const Tweener = imports.ui.tweener;
@ -119,10 +113,8 @@ function cloneAndFadeOutActor(actor) {
return hold;
}
var ShellUserVerifier = new Lang.Class({
Name: 'ShellUserVerifier',
_init(client, params) {
var ShellUserVerifier = class {
constructor(client, params) {
params = Params.parse(params, { reauthenticationOnly: false });
this._reauthOnly = params.reauthenticationOnly;
@ -165,7 +157,7 @@ var ShellUserVerifier = new Lang.Class({
this._oVirtUserAuthenticatedId = this._oVirtCredentialsManager.connect('user-authenticated',
this._oVirtUserAuthenticated.bind(this));
},
}
begin(userName, hold) {
this._cancellable = new Gio.Cancellable();
@ -183,7 +175,7 @@ var ShellUserVerifier = new Lang.Class({
} else {
this._client.get_user_verifier(this._cancellable, this._userVerifierGot.bind(this));
}
},
}
cancel() {
if (this._cancellable)
@ -193,14 +185,14 @@ var ShellUserVerifier = new Lang.Class({
this._userVerifier.call_cancel_sync(null);
this.clear();
}
},
}
_clearUserVerifier() {
if (this._userVerifier) {
this._userVerifier.run_dispose();
this._userVerifier = null;
}
},
}
clear() {
if (this._cancellable) {
@ -210,7 +202,7 @@ var ShellUserVerifier = new Lang.Class({
this._clearUserVerifier();
this._clearMessageQueue();
},
}
destroy() {
this.clear();
@ -224,7 +216,7 @@ var ShellUserVerifier = new Lang.Class({
this._oVirtCredentialsManager.disconnect(this._oVirtUserAuthenticatedId);
this._oVirtCredentialsManager = null;
},
}
answerQuery(serviceName, answer) {
if (!this.hasPendingMessages) {
@ -235,12 +227,12 @@ var ShellUserVerifier = new Lang.Class({
this._userVerifier.call_answer_query(serviceName, answer, this._cancellable, null);
});
}
},
}
_getIntervalForMessage(message) {
// We probably could be smarter here
return message.length * USER_READ_TIME;
},
}
finishMessageQueue() {
if (!this.hasPendingMessages)
@ -250,7 +242,7 @@ var ShellUserVerifier = new Lang.Class({
this.hasPendingMessages = false;
this.emit('no-more-messages');
},
}
_queueMessageTimeout() {
if (this._messageQueue.length == 0) {
@ -273,7 +265,7 @@ var ShellUserVerifier = new Lang.Class({
return GLib.SOURCE_REMOVE;
});
GLib.Source.set_name_by_id(this._messageQueueTimeoutId, '[gnome-shell] this._queueMessageTimeout');
},
}
_queueMessage(message, messageType) {
let interval = this._getIntervalForMessage(message);
@ -281,7 +273,7 @@ var ShellUserVerifier = new Lang.Class({
this.hasPendingMessages = true;
this._messageQueue.push({ text: message, type: messageType, interval: interval });
this._queueMessageTimeout();
},
}
_clearMessageQueue() {
this.finishMessageQueue();
@ -291,7 +283,7 @@ var ShellUserVerifier = new Lang.Class({
this._messageQueueTimeoutId = 0;
}
this.emit('show-message', null, MessageType.NONE);
},
}
_checkForFingerprintReader() {
this._haveFingerprintReader = false;
@ -309,12 +301,12 @@ var ShellUserVerifier = new Lang.Class({
this._updateDefaultService();
}
});
},
}
_oVirtUserAuthenticated(token) {
this._preemptingService = OVIRT_SERVICE_NAME;
this.emit('ovirt-user-authenticated');
},
}
_checkForSmartcard() {
let smartcardDetected;
@ -336,7 +328,7 @@ var ShellUserVerifier = new Lang.Class({
this.emit('smartcard-status-changed');
}
},
}
_reportInitError(where, error) {
logError(error, where);
@ -344,7 +336,7 @@ var ShellUserVerifier = new Lang.Class({
this._queueMessage(_("Authentication error"), MessageType.ERROR);
this._verificationFailed(false);
},
}
_reauthenticationChannelOpened(client, result) {
try {
@ -371,7 +363,7 @@ var ShellUserVerifier = new Lang.Class({
this._connectSignals();
this._beginVerification();
this._hold.release();
},
}
_userVerifierGot(client, result) {
try {
@ -387,7 +379,7 @@ var ShellUserVerifier = new Lang.Class({
this._connectSignals();
this._beginVerification();
this._hold.release();
},
}
_connectSignals() {
this._userVerifier.connect('info', this._onInfo.bind(this));
@ -397,22 +389,22 @@ var ShellUserVerifier = new Lang.Class({
this._userVerifier.connect('conversation-stopped', this._onConversationStopped.bind(this));
this._userVerifier.connect('reset', this._onReset.bind(this));
this._userVerifier.connect('verification-complete', this._onVerificationComplete.bind(this));
},
}
_getForegroundService() {
if (this._preemptingService)
return this._preemptingService;
return this._defaultService;
},
}
serviceIsForeground(serviceName) {
return serviceName == this._getForegroundService();
},
}
serviceIsDefault(serviceName) {
return serviceName == this._defaultService;
},
}
_updateDefaultService() {
if (this._settings.get_boolean(PASSWORD_AUTHENTICATION_KEY))
@ -426,7 +418,7 @@ var ShellUserVerifier = new Lang.Class({
log("no authentication service is enabled, using password authentication");
this._defaultService = PASSWORD_SERVICE_NAME;
}
},
}
_startService(serviceName) {
this._hold.acquire();
@ -462,14 +454,14 @@ var ShellUserVerifier = new Lang.Class({
this._hold.release();
});
}
},
}
_beginVerification() {
this._startService(this._getForegroundService());
if (this._userName && this._haveFingerprintReader && !this.serviceIsForeground(FINGERPRINT_SERVICE_NAME))
this._startService(FINGERPRINT_SERVICE_NAME);
},
}
_onInfo(client, serviceName, info) {
if (this.serviceIsForeground(serviceName)) {
@ -484,21 +476,21 @@ var ShellUserVerifier = new Lang.Class({
// to indicate the user can swipe their finger instead
this._queueMessage(_("(or swipe finger)"), MessageType.HINT);
}
},
}
_onProblem(client, serviceName, problem) {
if (!this.serviceIsForeground(serviceName))
return;
this._queueMessage(problem, MessageType.ERROR);
},
}
_onInfoQuery(client, serviceName, question) {
if (!this.serviceIsForeground(serviceName))
return;
this.emit('ask-question', serviceName, question, '');
},
}
_onSecretInfoQuery(client, serviceName, secretQuestion) {
if (!this.serviceIsForeground(serviceName))
@ -511,7 +503,7 @@ var ShellUserVerifier = new Lang.Class({
}
this.emit('ask-question', serviceName, secretQuestion, '\u25cf');
},
}
_onReset() {
// Clear previous attempts to authenticate
@ -519,20 +511,20 @@ var ShellUserVerifier = new Lang.Class({
this._updateDefaultService();
this.emit('reset');
},
}
_onVerificationComplete() {
this.emit('verification-complete');
},
}
_cancelAndReset() {
this.cancel();
this._onReset();
},
}
_retry() {
this.begin(this._userName, new Batch.Hold());
},
}
_verificationFailed(retry) {
// For Not Listed / enterprise logins, immediately reset
@ -567,7 +559,7 @@ var ShellUserVerifier = new Lang.Class({
}
this.emit('verification-failed', canRetry);
},
}
_onConversationStopped(client, serviceName) {
// If the login failed with the preauthenticated oVirt credentials
@ -586,6 +578,6 @@ var ShellUserVerifier = new Lang.Class({
if (this.serviceIsForeground(serviceName)) {
this._verificationFailed(true);
}
},
});
}
};
Signals.addSignalMethods(ShellUserVerifier.prototype);

View File

@ -78,11 +78,11 @@
<file>ui/overview.js</file>
<file>ui/overviewControls.js</file>
<file>ui/padOsd.js</file>
<file>ui/pageIndicators.js</file>
<file>ui/panel.js</file>
<file>ui/panelMenu.js</file>
<file>ui/pointerWatcher.js</file>
<file>ui/popupMenu.js</file>
<file>ui/remoteMenu.js</file>
<file>ui/remoteSearch.js</file>
<file>ui/runDialog.js</file>
<file>ui/screenShield.js</file>

View File

@ -3,7 +3,7 @@
// Common utils for the extension system and the extension
// preferences tool
const Lang = imports.lang;
const Gettext = imports.gettext;
const Signals = imports.signals;
const Gio = imports.gi.Gio;
@ -64,6 +64,66 @@ function getCurrentExtension() {
return null;
}
/**
* initTranslations:
* @domain: (optional): the gettext domain to use
*
* Initialize Gettext to load translations from extensionsdir/locale.
* If @domain is not provided, it will be taken from metadata['gettext-domain']
*/
function initTranslations(domain) {
let extension = getCurrentExtension();
if (!extension)
throw new Error('initTranslations() can only be called from extensions');
domain = domain || extension.metadata['gettext-domain'];
// Expect USER extensions to have a locale/ subfolder, otherwise assume a
// SYSTEM extension that has been installed in the same prefix as the shell
let localeDir = extension.dir.get_child('locale');
if (localeDir.query_exists(null))
Gettext.bindtextdomain(domain, localeDir.get_path());
else
Gettext.bindtextdomain(domain, Config.LOCALEDIR);
}
/**
* getSettings:
* @schema: (optional): the GSettings schema id
*
* Builds and returns a GSettings schema for @schema, using schema files
* in extensionsdir/schemas. If @schema is omitted, it is taken from
* metadata['settings-schema'].
*/
function getSettings(schema) {
let extension = getCurrentExtension();
if (!extension)
throw new Error('getSettings() can only be called from extensions');
schema = schema || extension.metadata['settings-schema'];
const GioSSS = Gio.SettingsSchemaSource;
// Expect USER extensions to have a schemas/ subfolder, otherwise assume a
// SYSTEM extension that has been installed in the same prefix as the shell
let schemaDir = extension.dir.get_child('schemas');
let schemaSource;
if (schemaDir.query_exists(null))
schemaSource = GioSSS.new_from_directory(schemaDir.get_path(),
GioSSS.get_default(),
false);
else
schemaSource = GioSSS.get_default();
let schemaObj = schemaSource.lookup(schema, true);
if (!schemaObj)
throw new Error(`Schema ${schema} could not be found for extension ${extension.metadata.uuid}. Please check your installation`);
return new Gio.Settings({ settings_schema: schemaObj });
}
/**
* versionCheck:
* @required: an array of versions we're compatible with
@ -160,9 +220,7 @@ function installImporter(extension) {
imports.searchPath = oldSearchPath;
}
var ExtensionFinder = new Lang.Class({
Name: 'ExtensionFinder',
var ExtensionFinder = class {
_loadExtension(extensionDir, info, perUserDir) {
let fileType = info.get_file_type();
if (fileType != Gio.FileType.DIRECTORY)
@ -184,7 +242,7 @@ var ExtensionFinder = new Lang.Class({
return;
}
this.emit('extension-found', extension);
},
}
scanExtensions() {
let perUserDir = Gio.File.new_for_path(global.userdatadir);
@ -192,5 +250,5 @@ var ExtensionFinder = new Lang.Class({
this._loadExtension(dir, info, perUserDir);
});
}
});
};
Signals.addSignalMethods(ExtensionFinder.prototype);

View File

@ -1,10 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
const { Gio, GLib } = imports.gi;
const Config = imports.misc.config;
const Params = imports.misc.params;
function collectFromDatadirs(subdir, includeUserDir, processFile) {
let dataDirs = GLib.get_system_data_dirs();

View File

@ -1,8 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const Signals = imports.signals;
const { loadInterfaceXML } = imports.misc.fileUtils;

View File

@ -1,16 +1,13 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Lang = imports.lang;
const Signals = imports.signals;
const Clutter = imports.gi.Clutter;
const Params = imports.misc.params;
var DEFAULT_LIMIT = 512;
var HistoryManager = new Lang.Class({
Name: 'HistoryManager',
_init(params) {
var HistoryManager = class {
constructor(params) {
params = Params.parse(params, { gsettingsKey: null,
limit: DEFAULT_LIMIT,
entry: null });
@ -34,12 +31,12 @@ var HistoryManager = new Lang.Class({
this._entry.connect('key-press-event',
this._onEntryKeyPress.bind(this));
}
},
}
_historyChanged() {
this._history = global.settings.get_strv(this._key);
this._historyIndex = this._history.length;
},
}
_setPrevItem(text) {
if (this._historyIndex <= 0)
@ -50,7 +47,7 @@ var HistoryManager = new Lang.Class({
this._historyIndex--;
this._indexChanged();
return true;
},
}
_setNextItem(text) {
if (this._historyIndex >= this._history.length)
@ -61,7 +58,7 @@ var HistoryManager = new Lang.Class({
this._historyIndex++;
this._indexChanged();
return true;
},
}
lastItem() {
if (this._historyIndex != this._history.length) {
@ -70,7 +67,7 @@ var HistoryManager = new Lang.Class({
}
return this._historyIndex ? this._history[this._historyIndex -1] : null;
},
}
addItem(input) {
if (this._history.length == 0 ||
@ -81,7 +78,7 @@ var HistoryManager = new Lang.Class({
this._save();
}
this._historyIndex = this._history.length;
},
}
_onEntryKeyPress(entry, event) {
let symbol = event.get_key_symbol();
@ -91,7 +88,7 @@ var HistoryManager = new Lang.Class({
return this._setNextItem(entry.get_text());
}
return Clutter.EVENT_PROPAGATE;
},
}
_indexChanged() {
let current = this._history[this._historyIndex] || '';
@ -99,7 +96,7 @@ var HistoryManager = new Lang.Class({
if (this._entry)
this._entry.set_text(current);
},
}
_save() {
if (this._history.length > this._limit)
@ -108,5 +105,5 @@ var HistoryManager = new Lang.Class({
if (this._key)
global.settings.set_strv(this._key, this._history);
}
});
};
Signals.addSignalMethods(HistoryManager.prototype);

View File

@ -1,12 +1,9 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
const { Gio, GLib, IBus } = imports.gi;
const Mainloop = imports.mainloop;
const Signals = imports.signals;
const IBus = imports.gi.IBus;
const IBusCandidatePopup = imports.ui.ibusCandidatePopup;
// Ensure runtime version matches
@ -32,17 +29,16 @@ function getIBusManager() {
return _ibusManager;
}
var IBusManager = new Lang.Class({
Name: 'IBusManager',
// This is the longest we'll keep the keyboard frozen until an input
// source is active.
_MAX_INPUT_SOURCE_ACTIVATION_TIME: 4000, // ms
_PRELOAD_ENGINES_DELAY_TIME: 30, // sec
_init() {
var IBusManager = class {
constructor() {
IBus.init();
// This is the longest we'll keep the keyboard frozen until an input
// source is active.
this._MAX_INPUT_SOURCE_ACTIVATION_TIME = 4000; // ms
this._PRELOAD_ENGINES_DELAY_TIME = 30; // sec
this._candidatePopup = new IBusCandidatePopup.CandidatePopup();
this._panelService = null;
@ -60,7 +56,7 @@ var IBusManager = new Lang.Class({
this._ibus.connect('global-engine-changed', this._engineChanged.bind(this));
this._spawn();
},
}
_spawn() {
try {
@ -69,7 +65,7 @@ var IBusManager = new Lang.Class({
} catch(e) {
log('Failed to launch ibus-daemon: ' + e.message);
}
},
}
_clear() {
if (this._panelService)
@ -85,7 +81,7 @@ var IBusManager = new Lang.Class({
this.emit('ready', false);
this._spawn();
},
}
_onConnected() {
this._ibus.list_engines_async(-1, null, this._initEngines.bind(this));
@ -93,7 +89,7 @@ var IBusManager = new Lang.Class({
IBus.BusNameFlag.REPLACE_EXISTING,
-1, null,
this._initPanelService.bind(this));
},
}
_initEngines(ibus, result) {
let enginesList = this._ibus.list_engines_async_finish(result);
@ -106,7 +102,7 @@ var IBusManager = new Lang.Class({
} else {
this._clear();
}
},
}
_initPanelService(ibus, result) {
let success = this._ibus.request_name_async_finish(result);
@ -151,13 +147,13 @@ var IBusManager = new Lang.Class({
} else {
this._clear();
}
},
}
_updateReadiness() {
this._ready = (Object.keys(this._engines).length > 0 &&
this._panelService != null);
this.emit('ready', this._ready);
},
}
_engineChanged(bus, engineName) {
if (!this._ready)
@ -178,26 +174,26 @@ var IBusManager = new Lang.Class({
this.emit('properties-registered', this._currentEngineName, props);
});
},
}
_updateProperty(panel, prop) {
this.emit('property-updated', this._currentEngineName, prop);
},
}
_setContentType(panel, purpose, hints) {
this.emit('set-content-type', purpose, hints);
},
}
activateProperty(key, state) {
this._panelService.property_activate(key, state);
},
}
getEngineDesc(id) {
if (!this._ready || !this._engines.hasOwnProperty(id))
return null;
return this._engines[id];
},
}
setEngine(id, callback) {
// Send id even if id == this._currentEngineName
@ -211,7 +207,7 @@ var IBusManager = new Lang.Class({
this._ibus.set_global_engine_async(id, this._MAX_INPUT_SOURCE_ACTIVATION_TIME,
null, callback || null);
},
}
preloadEngines(ids) {
if (!this._ibus || ids.length == 0)
@ -233,6 +229,6 @@ var IBusManager = new Lang.Class({
this._preloadEnginesId = 0;
return GLib.SOURCE_REMOVE;
});
},
});
}
};
Signals.addSignalMethods(IBusManager.prototype);

View File

@ -1,23 +1,21 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const IBus = imports.gi.IBus;
const { Clutter, GLib, GObject, IBus } = imports.gi;
const Keyboard = imports.ui.status.keyboard;
const Lang = imports.lang;
const Signals = imports.signals;
var InputMethod = new Lang.Class({
Name: 'InputMethod',
Extends: Clutter.InputMethod,
var HIDE_PANEL_TIME = 50;
var InputMethod = GObject.registerClass(
class InputMethod extends Clutter.InputMethod {
_init() {
this.parent();
super._init();
this._hints = 0;
this._purpose = 0;
this._enabled = true;
this._currentFocus = null;
this._preeditStr = '';
this._preeditPos = 0;
this._preeditVisible = false;
this._hidePanelId = 0;
this._ibus = IBus.Bus.new_async();
this._ibus.connect('connected', this._onConnected.bind(this));
this._ibus.connect('disconnected', this._clear.bind(this));
@ -30,11 +28,11 @@ var InputMethod = new Lang.Class({
if (this._ibus.is_connected())
this._onConnected();
},
}
get currentFocus() {
return this._currentFocus;
},
}
_updateCapabilities() {
let caps = 0;
@ -49,21 +47,19 @@ var InputMethod = new Lang.Class({
if (this._context)
this._context.set_capabilities(caps);
},
}
_onSourceChanged() {
this._currentSource = this._inputSourceManager.currentSource;
},
}
_onConnected() {
this._ibus.create_input_context_async ('gnome-shell', -1, null,
this._setContext.bind(this));
},
}
_setContext(bus, res) {
this._context = this._ibus.create_input_context_async_finish(res);
this._context.connect('enabled', () => { this._enabled = true });
this._context.connect('disabled', () => { this._enabled = false });
this._context.connect('commit-text', this._onCommitText.bind(this));
this._context.connect('delete-surrounding-text', this._onDeleteSurroundingText.bind(this));
this._context.connect('update-preedit-text', this._onUpdatePreeditText.bind(this));
@ -72,30 +68,29 @@ var InputMethod = new Lang.Class({
this._context.connect('forward-key-event', this._onForwardKeyEvent.bind(this));
this._updateCapabilities();
},
}
_clear() {
this._context = null;
this._hints = 0;
this._purpose = 0;
this._enabled = false;
this._preeditStr = ''
this._preeditPos = 0;
this._preeditVisible = false;
},
}
_emitRequestSurrounding() {
if (this._context.needs_surrounding_text())
this.emit('request-surrounding');
},
}
_onCommitText(context, text) {
this.commit(text.get_text());
},
}
_onDeleteSurroundingText(context) {
this.delete_surrounding();
},
}
_onUpdatePreeditText(context, text, pos, visible) {
if (text == null)
@ -111,17 +106,17 @@ var InputMethod = new Lang.Class({
this._preeditStr = preedit;
this._preeditPos = pos;
this._preeditVisible = visible;
},
}
_onShowPreeditText(context) {
this._preeditVisible = true;
this.set_preedit_text(this._preeditStr, this._preeditPos);
},
}
_onHidePreeditText(context) {
this.set_preedit_text(null, this._preeditPos);
this._preeditVisible = false;
},
}
_onForwardKeyEvent(context, keyval, keycode, state) {
let press = (state & IBus.ModifierType.RELEASE_MASK) == 0;
@ -135,7 +130,7 @@ var InputMethod = new Lang.Class({
time = global.display.get_current_time_roundtrip();
this.forward_key(keyval, keycode + 8, state & Clutter.ModifierType.MODIFIER_MASK, time, press);
},
}
vfunc_focus_in(focus) {
this._currentFocus = focus;
@ -144,7 +139,12 @@ var InputMethod = new Lang.Class({
this._updateCapabilities();
this._emitRequestSurrounding();
}
},
if (this._hidePanelId) {
GLib.source_remove(this._hidePanelId);
this._hidePanelId = 0;
}
}
vfunc_focus_out() {
this._currentFocus = null;
@ -158,7 +158,13 @@ var InputMethod = new Lang.Class({
this.set_preedit_text(null, 0);
this._preeditStr = null;
}
},
this._hidePanelId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, HIDE_PANEL_TIME, () => {
this.set_input_panel_state(Clutter.InputPanelState.OFF);
this._hidePanelId = 0;
return GLib.SOURCE_REMOVE;
});
}
vfunc_reset() {
if (this._context) {
@ -171,7 +177,7 @@ var InputMethod = new Lang.Class({
this.set_preedit_text(null, 0);
this._preeditStr = null;
}
},
}
vfunc_set_cursor_location(rect) {
if (this._context) {
@ -179,7 +185,7 @@ var InputMethod = new Lang.Class({
rect.get_width(), rect.get_height());
this._emitRequestSurrounding();
}
},
}
vfunc_set_surrounding(text, cursor, anchor) {
if (!this._context || !text)
@ -187,7 +193,7 @@ var InputMethod = new Lang.Class({
let ibusText = IBus.Text.new_from_string(text);
this._context.set_surrounding_text(ibusText, cursor, anchor);
},
}
vfunc_update_content_hints(hints) {
let ibusHints = 0;
@ -207,7 +213,7 @@ var InputMethod = new Lang.Class({
this._hints = ibusHints;
if (this._context)
this._context.set_content_type(this._purpose, this._hints);
},
}
vfunc_update_content_purpose(purpose) {
let ibusPurpose = 0;
@ -233,10 +239,10 @@ var InputMethod = new Lang.Class({
this._purpose = ibusPurpose;
if (this._context)
this._context.set_content_type(this._purpose, this._hints);
},
}
vfunc_filter_key_event(event) {
if (!this._context || !this._enabled)
if (!this._context)
return false;
if (!this._currentSource)
return false;
@ -260,5 +266,5 @@ var InputMethod = new Lang.Class({
}
});
return true;
},
}
});

View File

@ -1,8 +1,4 @@
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const { Gio, GLib, Meta, Shell } = imports.gi;
const INTROSPECT_SCHEMA = 'org.gnome.shell';
const INTROSPECT_KEY = 'introspect';
@ -12,10 +8,8 @@ const { loadInterfaceXML } = imports.misc.fileUtils;
const IntrospectDBusIface = loadInterfaceXML('org.gnome.Shell.Introspect');
var IntrospectService = new Lang.Class({
Name: 'IntrospectService',
_init() {
var IntrospectService = class {
constructor() {
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(IntrospectDBusIface,
this);
this._dbusImpl.export(Gio.DBus.session, '/org/gnome/Shell/Introspect');
@ -45,21 +39,21 @@ var IntrospectService = new Lang.Class({
});
this._syncRunningApplications();
},
}
_isStandaloneApp(app) {
let windows = app.get_windows();
return app.get_windows().some(w => w.transient_for == null);
},
}
_isIntrospectEnabled() {
return this._settings.get_boolean(INTROSPECT_KEY);
},
}
_isSenderWhitelisted(sender) {
return APP_WHITELIST.includes(sender);
},
}
_syncRunningApplications() {
let tracker = Shell.WindowTracker.get_default();
@ -95,7 +89,7 @@ var IntrospectService = new Lang.Class({
}
this._runningApplicationsDirty = false;
this._activeApplicationDirty = false;
},
}
_isEligibleWindow(window) {
if (window.is_override_redirect())
@ -106,7 +100,7 @@ var IntrospectService = new Lang.Class({
type == Meta.WindowType.DIALOG ||
type == Meta.WindowType.MODAL_DIALOG ||
type == Meta.WindowType.UTILITY);
},
}
GetRunningApplicationsAsync(params, invocation) {
if (!this._isIntrospectEnabled() &&
@ -118,7 +112,7 @@ var IntrospectService = new Lang.Class({
}
invocation.return_value(new GLib.Variant('(a{sa{sv}})', [this._runningApplications]));
},
}
GetWindowsAsync(params, invocation) {
let focusWindow = global.display.get_focus_window();
@ -163,4 +157,4 @@ var IntrospectService = new Lang.Class({
}
invocation.return_value(new GLib.Variant('(a{ta{sv}})', [windowsList]));
}
});
};

View File

@ -1,9 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const GLib = imports.gi.GLib;
const GnomeDesktop = imports.gi.GnomeDesktop;
const Lang = imports.lang;
const Meta = imports.gi.Meta;
const { GLib, GnomeDesktop, Meta } = imports.gi;
const Main = imports.ui.main;
@ -38,22 +35,20 @@ function holdKeyboard() {
global.display.freeze_keyboard(global.get_current_time());
}
var KeyboardManager = new Lang.Class({
Name: 'KeyboardManager',
var KeyboardManager = class {
constructor() {
// The XKB protocol doesn't allow for more that 4 layouts in a
// keymap. Wayland doesn't impose this limit and libxkbcommon can
// handle up to 32 layouts but since we need to support X clients
// even as a Wayland compositor, we can't bump this.
this.MAX_LAYOUTS_PER_GROUP = 4;
// The XKB protocol doesn't allow for more that 4 layouts in a
// keymap. Wayland doesn't impose this limit and libxkbcommon can
// handle up to 32 layouts but since we need to support X clients
// even as a Wayland compositor, we can't bump this.
MAX_LAYOUTS_PER_GROUP: 4,
_init() {
this._xkbInfo = getXkbInfo();
this._current = null;
this._localeLayoutInfo = this._getLocaleLayout();
this._layoutInfos = {};
this._currentKeymap = null;
},
}
_applyLayoutGroup(group) {
let options = this._buildOptionsString();
@ -67,11 +62,11 @@ var KeyboardManager = new Lang.Class({
this._currentKeymap = {layouts, variants, options};
Meta.get_backend().set_keymap(layouts, variants, options);
},
}
_applyLayoutGroupIndex(idx) {
Meta.get_backend().lock_layout_group(idx);
},
}
apply(id) {
let info = this._layoutInfos[id];
@ -87,7 +82,7 @@ var KeyboardManager = new Lang.Class({
}
this._current = info;
},
}
reapply() {
if (!this._current)
@ -95,7 +90,7 @@ var KeyboardManager = new Lang.Class({
this._applyLayoutGroup(this._current.group);
this._applyLayoutGroupIndex(this._current.groupIndex);
},
}
setUserLayouts(ids) {
this._current = null;
@ -126,7 +121,7 @@ var KeyboardManager = new Lang.Class({
i += 1;
}
},
}
_getLocaleLayout() {
let locale = GLib.get_language_names()[0];
@ -143,21 +138,21 @@ var KeyboardManager = new Lang.Class({
return { layout: _layout, variant: _variant };
else
return { layout: DEFAULT_LAYOUT, variant: DEFAULT_VARIANT };
},
}
_buildGroupStrings(_group) {
let group = _group.concat(this._localeLayoutInfo);
let layouts = group.map(g => g.layout).join(',');
let variants = group.map(g => g.variant).join(',');
return [layouts, variants];
},
}
setKeyboardOptions(options) {
this._xkbOptions = options;
},
}
_buildOptionsString() {
let options = this._xkbOptions.join(',');
return options;
}
});
};

View File

@ -1,10 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Shell = imports.gi.Shell;
const { GLib, Gio } = imports.gi;
const Signals = imports.signals;
const { loadInterfaceXML } = imports.misc.fileUtils;
@ -70,10 +66,8 @@ function getLoginManager() {
return _loginManager;
}
var LoginManagerSystemd = new Lang.Class({
Name: 'LoginManagerSystemd',
_init() {
var LoginManagerSystemd = class {
constructor() {
this._proxy = new SystemdLoginManager(Gio.DBus.system,
'org.freedesktop.login1',
'/org/freedesktop/login1');
@ -82,7 +76,7 @@ var LoginManagerSystemd = new Lang.Class({
'/org/freedesktop/login1/user/self');
this._proxy.connectSignal('PrepareForSleep',
this._prepareForSleep.bind(this));
},
}
getCurrentSessionProxy(callback) {
if (this._currentSession) {
@ -129,7 +123,7 @@ var LoginManagerSystemd = new Lang.Class({
callback(this._currentSession);
}
});
},
}
canSuspend(asyncCallback) {
this._proxy.CanSuspendRemote((result, error) => {
@ -141,7 +135,7 @@ var LoginManagerSystemd = new Lang.Class({
asyncCallback(canSuspend, needsAuth);
}
});
},
}
listSessions(asyncCallback) {
this._proxy.ListSessionsRemote((result, error) => {
@ -150,11 +144,11 @@ var LoginManagerSystemd = new Lang.Class({
else
asyncCallback(result[0]);
});
},
}
suspend() {
this._proxy.SuspendRemote(true);
},
}
inhibit(reason, callback) {
let inVariant = GLib.Variant.new('(ssss)',
@ -174,38 +168,36 @@ var LoginManagerSystemd = new Lang.Class({
callback(null);
}
});
},
}
_prepareForSleep(proxy, sender, [aboutToSuspend]) {
this.emit('prepare-for-sleep', aboutToSuspend);
}
});
};
Signals.addSignalMethods(LoginManagerSystemd.prototype);
var LoginManagerDummy = new Lang.Class({
Name: 'LoginManagerDummy',
var LoginManagerDummy = class {
getCurrentSessionProxy(callback) {
// we could return a DummySession object that fakes whatever callers
// expect (at the time of writing: connect() and connectSignal()
// methods), but just never calling the callback should be safer
},
}
canSuspend(asyncCallback) {
asyncCallback(false, false);
},
}
listSessions(asyncCallback) {
asyncCallback([]);
},
}
suspend() {
this.emit('prepare-for-sleep', true);
this.emit('prepare-for-sleep', false);
},
}
inhibit(reason, callback) {
callback(null);
}
});
};
Signals.addSignalMethods(LoginManagerDummy.prototype);

View File

@ -1,8 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const NMA = imports.gi.NMA;
const { Gio, NMA } = imports.gi;
const Signals = imports.signals;
const { loadInterfaceXML } = imports.misc.fileUtils;
@ -100,10 +98,8 @@ const ModemGsmNetworkProxy = Gio.DBusProxy.makeProxyWrapper(ModemGsmNetworkInter
const ModemCdmaInterface = loadInterfaceXML('org.freedesktop.ModemManager.Modem.Cdma');
const ModemCdmaProxy = Gio.DBusProxy.makeProxyWrapper(ModemCdmaInterface);
var ModemGsm = new Lang.Class({
Name: 'ModemGsm',
_init(path) {
var ModemGsm = class {
constructor(path) {
this._proxy = new ModemGsmNetworkProxy(Gio.DBus.system, 'org.freedesktop.ModemManager', path);
this.signal_quality = 0;
@ -139,13 +135,11 @@ var ModemGsm = new Lang.Class({
this.emit('notify::signal-quality');
});
}
});
};
Signals.addSignalMethods(ModemGsm.prototype);
var ModemCdma = new Lang.Class({
Name: 'ModemCdma',
_init(path) {
var ModemCdma = class {
constructor(path) {
this._proxy = new ModemCdmaProxy(Gio.DBus.system, 'org.freedesktop.ModemManager', path);
this.signal_quality = 0;
@ -169,7 +163,7 @@ var ModemCdma = new Lang.Class({
}
this.emit('notify::signal-quality');
});
},
}
_refreshServingSystem() {
this._proxy.GetServingSystemRemote(([result], err) => {
@ -184,7 +178,7 @@ var ModemCdma = new Lang.Class({
this.emit('notify::operator-name');
});
}
});
};
Signals.addSignalMethods(ModemCdma.prototype);
@ -201,10 +195,8 @@ const BroadbandModem3gppProxy = Gio.DBusProxy.makeProxyWrapper(BroadbandModem3gp
const BroadbandModemCdmaInterface = loadInterfaceXML('org.freedesktop.ModemManager1.Modem.ModemCdma');
const BroadbandModemCdmaProxy = Gio.DBusProxy.makeProxyWrapper(BroadbandModemCdmaInterface);
var BroadbandModem = new Lang.Class({
Name: 'BroadbandModem',
_init(path, capabilities) {
var BroadbandModem = class {
constructor(path, capabilities) {
this._proxy = new BroadbandModemProxy(Gio.DBus.system, 'org.freedesktop.ModemManager1', path);
this._proxy_3gpp = new BroadbandModem3gppProxy(Gio.DBus.system, 'org.freedesktop.ModemManager1', path);
this._proxy_cdma = new BroadbandModemCdmaProxy(Gio.DBus.system, 'org.freedesktop.ModemManager1', path);
@ -229,13 +221,13 @@ var BroadbandModem = new Lang.Class({
this._reloadCdmaOperatorName();
});
this._reloadCdmaOperatorName();
},
}
_reloadSignalQuality() {
let [quality, recent] = this._proxy.SignalQuality;
this.signal_quality = quality;
this.emit('notify::signal-quality');
},
}
_reloadOperatorName() {
let new_name = "";
@ -250,19 +242,19 @@ var BroadbandModem = new Lang.Class({
this.operator_name = new_name;
this.emit('notify::operator-name');
},
}
_reload3gppOperatorName() {
let name = this._proxy_3gpp.OperatorName;
let code = this._proxy_3gpp.OperatorCode;
this.operator_name_3gpp = _findProviderForMccMnc(name, code);
this._reloadOperatorName();
},
}
_reloadCdmaOperatorName() {
let sid = this._proxy_cdma.Sid;
this.operator_name_cdma = _findProviderForSid(sid);
this._reloadOperatorName();
}
});
};
Signals.addSignalMethods(BroadbandModem.prototype);

View File

@ -1,8 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
const { Gio, GLib } = imports.gi;
const Params = imports.misc.params;
const Signals = imports.signals;
@ -27,9 +25,8 @@ const ObjectManagerIface = `
const ObjectManagerInfo = Gio.DBusInterfaceInfo.new_for_xml(ObjectManagerIface);
var ObjectManager = new Lang.Class({
Name: 'ObjectManager',
_init(params) {
var ObjectManager = class {
constructor(params) {
params = Params.parse(params, { connection: null,
name: null,
objectPath: null,
@ -63,7 +60,7 @@ var ObjectManager = new Lang.Class({
this._managerProxy.init_async(GLib.PRIORITY_DEFAULT,
this._cancellable,
this._onManagerProxyLoaded.bind(this));
},
}
_tryToCompleteLoad() {
if (this._numLoadInhibitors == 0)
@ -74,7 +71,7 @@ var ObjectManager = new Lang.Class({
if (this._onLoaded)
this._onLoaded();
}
},
}
_addInterface(objectPath, interfaceName, onFinished) {
let info = this._interfaceInfos[interfaceName];
@ -129,7 +126,7 @@ var ObjectManager = new Lang.Class({
if (onFinished)
onFinished();
});
},
}
_removeInterface(objectPath, interfaceName) {
if (!this._objects[objectPath])
@ -155,14 +152,14 @@ var ObjectManager = new Lang.Class({
delete this._objects[objectPath];
this.emit('object-removed', objectPath);
}
},
}
_onManagerProxyLoaded(initable, result) {
let error = null;
try {
initable.init_finish(result);
} catch(e) {
logError(e, 'could not initialize object manager for object ' + params.name);
logError(e, 'could not initialize object manager for object ' + this._serviceName);
this._tryToCompleteLoad();
return;
@ -194,7 +191,7 @@ var ObjectManager = new Lang.Class({
if (this._managerProxy.g_name_owner)
this._onNameAppeared();
},
}
_onNameAppeared() {
this._managerProxy.GetManagedObjectsRemote((result, error) => {
@ -232,7 +229,7 @@ var ObjectManager = new Lang.Class({
}
this._tryToCompleteLoad();
});
},
}
_onNameVanished() {
let objectPaths = Object.keys(this._objects);
@ -248,14 +245,14 @@ var ObjectManager = new Lang.Class({
this._removeInterface(objectPath, interfaceName);
}
}
},
}
_registerInterfaces(interfaces) {
for (let i = 0; i < interfaces.length; i++) {
let info = Gio.DBusInterfaceInfo.new_for_xml(interfaces[i]);
this._interfaceInfos[info.name] = info;
}
},
}
getProxy(objectPath, interfaceName) {
let object = this._objects[objectPath];
@ -264,7 +261,7 @@ var ObjectManager = new Lang.Class({
return null;
return object[interfaceName];
},
}
getProxiesForInterface(interfaceName) {
let proxyList = this._interfaces[interfaceName];
@ -273,7 +270,7 @@ var ObjectManager = new Lang.Class({
return [];
return proxyList;
},
}
getAllProxies() {
let proxies = [];
@ -283,8 +280,8 @@ var ObjectManager = new Lang.Class({
let object = this._objects[objectPaths];
let interfaceNames = Object.keys(object);
for (let j = 0; i < interfaceNames.length; i++) {
let interfaceName = interfaceNames[i];
for (let j = 0; j < interfaceNames.length; j++) {
let interfaceName = interfaceNames[j];
if (object[interfaceName])
proxies.push(object(interfaceName));
}
@ -292,5 +289,5 @@ var ObjectManager = new Lang.Class({
return proxies;
}
});
};
Signals.addSignalMethods(ObjectManager.prototype);

View File

@ -1,8 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const ObjectManager = imports.misc.objectManager;
@ -26,9 +24,8 @@ function getSmartcardManager() {
return _smartcardManager;
}
var SmartcardManager = new Lang.Class({
Name: 'SmartcardManager',
_init() {
var SmartcardManager = class {
constructor() {
this._objectManager = new ObjectManager.ObjectManager({ connection: Gio.DBus.session,
name: "org.gnome.SettingsDaemon.Smartcard",
objectPath: '/org/gnome/SettingsDaemon/Smartcard',
@ -36,7 +33,7 @@ var SmartcardManager = new Lang.Class({
onLoaded: this._onLoaded.bind(this) });
this._insertedTokens = {};
this._loginToken = null;
},
}
_onLoaded() {
let tokens = this._objectManager.getProxiesForInterface('org.gnome.SettingsDaemon.Smartcard.Token');
@ -53,7 +50,7 @@ var SmartcardManager = new Lang.Class({
if (interfaceName == 'org.gnome.SettingsDaemon.Smartcard.Token')
this._removeToken(proxy);
});
},
}
_updateToken(token) {
let objectPath = token.get_object_path();
@ -65,7 +62,7 @@ var SmartcardManager = new Lang.Class({
if (token.UsedToLogin)
this._loginToken = token;
},
}
_addToken(token) {
this._updateToken(token);
@ -85,7 +82,7 @@ var SmartcardManager = new Lang.Class({
// Emit a smartcard-inserted at startup if it's already plugged in
if (token.IsInserted)
this.emit('smartcard-inserted', token);
},
}
_removeToken(token) {
let objectPath = token.get_object_path();
@ -99,11 +96,11 @@ var SmartcardManager = new Lang.Class({
this._loginToken = null;
token.disconnectAll();
},
}
hasInsertedTokens() {
return Object.keys(this._insertedTokens).length > 0;
},
}
hasInsertedLoginToken() {
if (!this._loginToken)
@ -115,5 +112,5 @@ var SmartcardManager = new Lang.Class({
return true;
}
});
};
Signals.addSignalMethods(SmartcardManager.prototype);

View File

@ -1,11 +1,4 @@
const AccountsService = imports.gi.AccountsService;
const Clutter = imports.gi.Clutter;
const Gdm = imports.gi.Gdm;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
const Meta = imports.gi.Meta;
const GObject = imports.gi.GObject;
const { AccountsService, Clutter, Gdm, Gio, GLib, GObject, Meta } = imports.gi;
const GnomeSession = imports.misc.gnomeSession;
const LoginManager = imports.misc.loginManager;
@ -44,9 +37,7 @@ function getDefault() {
return _singleton;
}
const SystemActions = new Lang.Class({
Name: 'SystemActions',
Extends: GObject.Object,
const SystemActions = GObject.registerClass({
Properties: {
'can-power-off': GObject.ParamSpec.boolean('can-power-off',
'can-power-off',
@ -83,10 +74,10 @@ const SystemActions = new Lang.Class({
'orientation-lock-icon',
GObject.ParamFlags.READWRITE,
null)
},
}
}, class SystemActions extends GObject.Object {
_init() {
this.parent();
super._init();
this._canHavePowerOff = true;
this._canHaveSuspend = true;
@ -186,35 +177,35 @@ const SystemActions = new Lang.Class({
Main.sessionMode.connect('updated', () => { this._sessionUpdated(); });
this._sessionUpdated();
},
}
get can_power_off() {
return this._actions.get(POWER_OFF_ACTION_ID).available;
},
}
get can_suspend() {
return this._actions.get(SUSPEND_ACTION_ID).available;
},
}
get can_lock_screen() {
return this._actions.get(LOCK_SCREEN_ACTION_ID).available;
},
}
get can_switch_user() {
return this._actions.get(SWITCH_USER_ACTION_ID).available;
},
}
get can_logout() {
return this._actions.get(LOGOUT_ACTION_ID).available;
},
}
get can_lock_orientation() {
return this._actions.get(LOCK_ORIENTATION_ACTION_ID).available;
},
}
get orientation_lock_icon() {
return this._actions.get(LOCK_ORIENTATION_ACTION_ID).iconName;
},
}
_sensorProxyAppeared() {
this._sensorProxy = new SensorProxy(Gio.DBus.system, SENSOR_BUS_NAME, SENSOR_OBJECT_PATH,
@ -227,7 +218,7 @@ const SystemActions = new Lang.Class({
() => { this._updateOrientationLock(); });
this._updateOrientationLock();
});
},
}
_updateOrientationLock() {
let available = false;
@ -238,7 +229,7 @@ const SystemActions = new Lang.Class({
this._actions.get(LOCK_ORIENTATION_ACTION_ID).available = available;
this.notify('can-lock-orientation');
},
}
_updateOrientationLockIcon() {
let locked = this._orientationSettings.get_boolean('orientation-lock');
@ -247,14 +238,14 @@ const SystemActions = new Lang.Class({
this._actions.get(LOCK_ORIENTATION_ACTION_ID).iconName = iconName;
this.notify('orientation-lock-icon');
},
}
_sessionUpdated() {
this._updateLockScreen();
this._updatePowerOff();
this._updateSuspend();
this._updateMultiUser();
},
}
forceUpdate() {
// Whether those actions are available or not depends on both lockdown
@ -262,7 +253,7 @@ const SystemActions = new Lang.Class({
// latter, so their value may be outdated; force an update now
this._updateHaveShutdown();
this._updateHaveSuspend();
},
}
getMatchingActions(terms) {
// terms is a list of strings
@ -275,15 +266,15 @@ const SystemActions = new Lang.Class({
results.push(key);
return results;
},
}
getName(id) {
return this._actions.get(id).name;
},
}
getIconName(id) {
return this._actions.get(id).iconName;
},
}
activateAction(id) {
switch (id) {
@ -306,14 +297,14 @@ const SystemActions = new Lang.Class({
this.activateLockOrientation();
break;
}
},
}
_updateLockScreen() {
let showLock = !Main.sessionMode.isLocked && !Main.sessionMode.isGreeter;
let allowLockScreen = !this._lockdownSettings.get_boolean(DISABLE_LOCK_SCREEN_KEY);
this._actions.get(LOCK_SCREEN_ACTION_ID).available = showLock && allowLockScreen && LoginManager.canLock();
this.notify('can-lock-screen');
},
}
_updateHaveShutdown() {
this._session.CanShutdownRemote((result, error) => {
@ -323,7 +314,7 @@ const SystemActions = new Lang.Class({
this._canHavePowerOff = result[0];
this._updatePowerOff();
});
},
}
_updatePowerOff() {
let disabled = Main.sessionMode.isLocked ||
@ -331,7 +322,7 @@ const SystemActions = new Lang.Class({
this._loginScreenSettings.get_boolean(DISABLE_RESTART_KEY));
this._actions.get(POWER_OFF_ACTION_ID).available = this._canHavePowerOff && !disabled;
this.notify('can-power-off');
},
}
_updateHaveSuspend() {
this._loginManager.canSuspend(
@ -340,7 +331,7 @@ const SystemActions = new Lang.Class({
this._suspendNeedsAuth = needsAuth;
this._updateSuspend();
});
},
}
_updateSuspend() {
let disabled = (Main.sessionMode.isLocked &&
@ -349,12 +340,12 @@ const SystemActions = new Lang.Class({
this._loginScreenSettings.get_boolean(DISABLE_RESTART_KEY));
this._actions.get(SUSPEND_ACTION_ID).available = this._canHaveSuspend && !disabled;
this.notify('can-suspend');
},
}
_updateMultiUser() {
this._updateLogout();
this._updateSwitchUser();
},
}
_updateSwitchUser() {
let allowSwitch = !this._lockdownSettings.get_boolean(DISABLE_USER_SWITCH_KEY);
@ -366,7 +357,7 @@ const SystemActions = new Lang.Class({
this.notify('can-switch-user');
return visible;
},
}
_updateLogout() {
let user = this._userManager.get_user(GLib.get_user_name());
@ -384,7 +375,7 @@ const SystemActions = new Lang.Class({
this.notify('can-logout');
return visible;
},
}
activateLockOrientation() {
if (!this._actions.get(LOCK_ORIENTATION_ACTION_ID).available)
@ -392,14 +383,14 @@ const SystemActions = new Lang.Class({
let locked = this._orientationSettings.get_boolean('orientation-lock');
this._orientationSettings.set_boolean('orientation-lock', !locked);
},
}
activateLockScreen() {
if (!this._actions.get(LOCK_SCREEN_ACTION_ID).available)
throw new Error('The lock-screen action is not available!');
Main.screenShield.lock(true);
},
}
activateSwitchUser() {
if (!this._actions.get(SWITCH_USER_ACTION_ID).available)
@ -412,7 +403,7 @@ const SystemActions = new Lang.Class({
Gdm.goto_login_session_sync(null);
return false;
});
},
}
activateLogout() {
if (!this._actions.get(LOGOUT_ACTION_ID).available)
@ -420,14 +411,14 @@ const SystemActions = new Lang.Class({
Main.overview.hide();
this._session.LogoutRemote(0);
},
}
activatePowerOff() {
if (!this._actions.get(POWER_OFF_ACTION_ID).available)
throw new Error('The power-off action is not available!');
this._session.ShutdownRemote(0);
},
}
activateSuspend() {
if (!this._actions.get(SUSPEND_ACTION_ID).available)

View File

@ -1,14 +1,9 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const { Clutter, Gio, GLib, GObject, Shell, St } = imports.gi;
const Gettext = imports.gettext;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Signals = imports.signals;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
@ -348,12 +343,10 @@ function insertSorted(array, val, cmp) {
return pos;
}
var CloseButton = new Lang.Class({
Name: 'CloseButton',
Extends: St.Button,
var CloseButton = GObject.registerClass(
class CloseButton extends St.Button {
_init(boxpointer) {
this.parent({ style_class: 'notification-close'});
super._init({ style_class: 'notification-close'});
// This is a bit tricky. St.Bin has its own x-align/y-align properties
// that compete with Clutter's properties. This should be fixed for
@ -370,7 +363,7 @@ var CloseButton = new Lang.Class({
this._boxPointer = boxpointer;
if (boxpointer)
this._boxPointer.connect('arrow-side-changed', this._sync.bind(this));
},
}
_computeBoxPointerOffset() {
if (!this._boxPointer || !this._boxPointer.actor.get_stage())
@ -381,7 +374,7 @@ var CloseButton = new Lang.Class({
return this._boxPointer.getArrowHeight();
else
return 0;
},
}
_sync() {
let themeNode = this.get_theme_node();
@ -389,12 +382,12 @@ var CloseButton = new Lang.Class({
let offY = this._computeBoxPointerOffset();
this.translation_x = themeNode.get_length('-shell-close-overlap-x')
this.translation_y = themeNode.get_length('-shell-close-overlap-y') + offY;
},
}
vfunc_style_changed() {
this._sync();
this.parent();
},
super.vfunc_style_changed();
}
});
function makeCloseButton(boxpointer) {
@ -437,10 +430,8 @@ function ensureActorVisibleInScrollView(scrollView, actor) {
transition: 'easeOutQuad' });
}
var AppSettingsMonitor = new Lang.Class({
Name: 'AppSettingsMonitor',
_init(appId, schemaId) {
var AppSettingsMonitor = class {
constructor(appId, schemaId) {
this._appId = appId;
this._schemaId = schemaId;
@ -454,23 +445,23 @@ var AppSettingsMonitor = new Lang.Class({
this._appSystem.connect('installed-changed',
this._onInstalledChanged.bind(this));
this._onInstalledChanged();
},
}
get available() {
return this._app != null && this._settings != null;
},
}
activateApp() {
if (this._app)
this._app.activate();
},
}
watchSetting(key, callback) {
let handler = { id: 0, key: key, callback: callback };
this._handlers.push(handler);
this._connectHandler(handler);
},
}
_connectHandler(handler) {
if (!this._settings || handler.id > 0)
@ -479,13 +470,13 @@ var AppSettingsMonitor = new Lang.Class({
handler.id = this._settings.connect('changed::' + handler.key,
handler.callback);
handler.callback(this._settings, handler.key);
},
}
_disconnectHandler(handler) {
if (this._settings && handler.id > 0)
this._settings.disconnect(handler.id);
handler.id = 0;
},
}
_onInstalledChanged() {
let hadApp = (this._app != null);
@ -499,7 +490,7 @@ var AppSettingsMonitor = new Lang.Class({
this._checkSettings();
else
this._setSettings(null);
},
}
_setSettings(settings) {
this._handlers.forEach((handler) => { this._disconnectHandler(handler); });
@ -512,7 +503,7 @@ var AppSettingsMonitor = new Lang.Class({
if (hadSettings != haveSettings)
this.emit('available-changed');
},
}
_checkSettings() {
let schema = this._schemaSource.lookup(this._schemaId, true);
@ -525,5 +516,5 @@ var AppSettingsMonitor = new Lang.Class({
});
}
}
});
};
Signals.addSignalMethods(AppSettingsMonitor.prototype);

View File

@ -1,10 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Geoclue = imports.gi.Geoclue;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GWeather = imports.gi.GWeather;
const Lang = imports.lang;
const { Geoclue, Gio, GLib, GWeather } = imports.gi;
const Signals = imports.signals;
const PermissionStore = imports.misc.permissionStore;
@ -13,10 +9,8 @@ const Util = imports.misc.util;
// Minimum time between updates to show loading indication
var UPDATE_THRESHOLD = 10 * GLib.TIME_SPAN_MINUTE;
var WeatherClient = new Lang.Class({
Name: 'WeatherClient',
_init() {
var WeatherClient = class {
constructor() {
this._loading = false;
this._locationValid = false;
this._lastUpdate = GLib.DateTime.new_from_unix_local(0);
@ -36,6 +30,14 @@ var WeatherClient = new Lang.Class({
return;
}
if (this._permStore.g_name_owner == null) {
// Failed to auto-start, likely because xdg-desktop-portal
// isn't installed; don't restrict access to location service
this._weatherAuthorized = true;
this._updateAutoLocation();
return;
}
this._permStore.LookupRemote('gnome', 'geolocation', (res, error) => {
if (error)
log('Error looking up permission: ' + error.message);
@ -64,34 +66,34 @@ var WeatherClient = new Lang.Class({
this.emit('changed');
});
this._weatherAppMon = new Util.AppSettingsMonitor('org.gnome.Weather.Application.desktop',
'org.gnome.Weather.Application');
this._weatherAppMon = new Util.AppSettingsMonitor('org.gnome.Weather.desktop',
'org.gnome.Weather');
this._weatherAppMon.connect('available-changed', () => { this.emit('changed'); });
this._weatherAppMon.watchSetting('automatic-location',
this._onAutomaticLocationChanged.bind(this));
this._weatherAppMon.watchSetting('locations',
this._onLocationsChanged.bind(this));
},
}
get available() {
return this._weatherAppMon.available;
},
}
get loading() {
return this._loading;
},
}
get hasLocation() {
return this._locationValid;
},
}
get info() {
return this._weatherInfo;
},
}
activateApp() {
this._weatherAppMon.activateApp();
},
}
update() {
if (!this._locationValid)
@ -104,13 +106,13 @@ var WeatherClient = new Lang.Class({
this._weatherInfo.update();
else
this._loadInfo();
},
}
get _useAutoLocation() {
return this._autoLocationRequested &&
this._locationSettings.get_boolean('enabled') &&
this._weatherAuthorized;
},
}
_loadInfo() {
let id = this._weatherInfo.connect('updated', () => {
@ -122,7 +124,7 @@ var WeatherClient = new Lang.Class({
this.emit('changed');
this._weatherInfo.update();
},
}
_locationsEqual(loc1, loc2) {
if (loc1 == loc2)
@ -132,7 +134,7 @@ var WeatherClient = new Lang.Class({
return false;
return loc1.equal(loc2);
},
}
_setLocation(location) {
if (this._locationsEqual(this._weatherInfo.location, location))
@ -148,7 +150,7 @@ var WeatherClient = new Lang.Class({
this._loadInfo();
else
this.emit('changed');
},
}
_updateLocationMonitoring() {
if (this._useAutoLocation) {
@ -164,7 +166,7 @@ var WeatherClient = new Lang.Class({
this._gclueService.disconnect(this._gclueLocationChangedId);
this._gclueLocationChangedId = 0;
}
},
}
_startGClueService() {
if (this._gclueStarting)
@ -185,7 +187,7 @@ var WeatherClient = new Lang.Class({
this._gclueService.get_client().distance_threshold = 100;
this._updateLocationMonitoring();
});
},
}
_onGClueLocationChanged() {
let geoLocation = this._gclueService.location;
@ -194,7 +196,7 @@ var WeatherClient = new Lang.Class({
geoLocation.latitude,
geoLocation.longitude);
this._setLocation(location);
},
}
_onAutomaticLocationChanged(settings, key) {
let useAutoLocation = settings.get_boolean(key);
@ -204,7 +206,7 @@ var WeatherClient = new Lang.Class({
this._autoLocationRequested = useAutoLocation;
this._updateAutoLocation();
},
}
_updateAutoLocation() {
this._updateLocationMonitoring();
@ -213,7 +215,7 @@ var WeatherClient = new Lang.Class({
this._startGClueService();
else
this._setLocation(this._mostRecentLocation);
},
}
_onLocationsChanged(settings, key) {
let serialized = settings.get_value(key).deep_unpack().shift();
@ -229,7 +231,7 @@ var WeatherClient = new Lang.Class({
if (!this._useAutoLocation || !this._gclueStarted)
this._setLocation(this._mostRecentLocation);
},
}
_onPermStoreChanged(proxy, sender, params) {
let [table, id, deleted, data, perms] = params;
@ -237,11 +239,11 @@ var WeatherClient = new Lang.Class({
if (table != 'gnome' || id != 'geolocation')
return;
let permission = perms['org.gnome.Weather.Application'] || ['NONE'];
let permission = perms['org.gnome.Weather'] || ['NONE'];
let [accuracy] = permission;
this._weatherAuthorized = accuracy != 'NONE';
this._updateAutoLocation();
}
});
};
Signals.addSignalMethods(WeatherClient.prototype);

View File

@ -10,7 +10,7 @@ const Scripting = imports.ui.scripting;
// someone should be able to get an idea of how well the shell is performing
// on a particular system.
let METRICS = {
var METRICS = {
overviewLatencyFirst:
{ description: "Time to first frame after triggering overview, first time",
units: "us" },
@ -65,7 +65,7 @@ let WINDOW_CONFIGS = [
{ width: 640, height: 480, alpha: true, maximized: false, count: 10, metric: 'overviewFps10Alpha' }
];
function run() {
function *run() {
Scripting.defineScriptEvent("overviewShowStart", "Starting to show the overview");
Scripting.defineScriptEvent("overviewShowDone", "Overview finished showing");
Scripting.defineScriptEvent("afterShowHide", "After a show/hide cycle for the overview");

View File

@ -1,12 +1,8 @@
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const Gtk = imports.gi.Gtk;
const Meta = imports.gi.Meta;
const { Clutter, Gio, Shell } = imports.gi;
const Main = imports.ui.main;
const Scripting = imports.ui.scripting;
const Shell = imports.gi.Shell;
let METRICS = {
var METRICS = {
timeToDesktop:
{ description: "Time from starting graphical.target to desktop showing",
units: "us" },
@ -89,7 +85,7 @@ function extractBootTimestamp() {
return result;
}
function run() {
function *run() {
Scripting.defineScriptEvent("desktopShown", "Finished initial animation");
Scripting.defineScriptEvent("overviewShowStart", "Starting to show the overview");
Scripting.defineScriptEvent("overviewShowDone", "Overview finished showing");
@ -108,7 +104,10 @@ function run() {
yield Scripting.waitLeisure();
Scripting.scriptEvent('desktopShown');
Gtk.Settings.get_default().gtk_enable_animations = false;
let interfaceSettings = new Gio.Settings({
schema_id: 'org.gnome.desktop.interface'
});
interfaceSettings.set_boolean('enable-animations', false);
Scripting.scriptEvent('overviewShowStart');
Main.overview.show();
@ -204,7 +203,7 @@ function run() {
yield Scripting.sleep(1000);
Gtk.Settings.get_default().gtk_enable_animations = true;
interfaceSettings.set_boolean('enable-animations', true);
}
let overviewShowStart;

View File

@ -1,13 +1,6 @@
const Format = imports.format;
const Gettext = imports.gettext;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Gio = imports.gi.Gio;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
const Pango = imports.gi.Pango;
const Soup = imports.gi.Soup;
const WebKit = imports.gi.WebKit2;
const { Gio, GLib, GObject, Gtk, Pango, Soup, WebKit2: WebKit } = imports.gi;
const _ = Gettext.gettext;
@ -33,12 +26,10 @@ const CONNECTIVITY_RECHECK_RATELIMIT_TIMEOUT = 30 * GLib.USEC_PER_SEC;
const HelperDBusInterface = loadInterfaceXML('org.gnome.Shell.PortalHelper');
var PortalHeaderBar = new Lang.Class({
Name: 'PortalHeaderBar',
Extends: Gtk.HeaderBar,
var PortalHeaderBar = GObject.registerClass(
class PortalHeaderBar extends Gtk.HeaderBar {
_init() {
this.parent({ show_close_button: true });
super._init({ show_close_button: true });
// See ephy-title-box.c in epiphany for the layout
let vbox = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL,
@ -73,11 +64,11 @@ var PortalHeaderBar = new Lang.Class({
hbox.add(this.subtitleLabel);
vbox.show_all();
},
}
setSubtitle(label) {
this.subtitleLabel.set_text(label);
},
}
setSecurityIcon(securityLevel) {
switch (securityLevel) {
@ -95,15 +86,13 @@ var PortalHeaderBar = new Lang.Class({
this._lockImage.set_tooltip_text(_('Your connection to this hotspot login is not secure. Passwords or other information you enter on this page can be viewed by people nearby.'));
break;
}
},
}
});
var PortalWindow = new Lang.Class({
Name: 'PortalWindow',
Extends: Gtk.ApplicationWindow,
var PortalWindow = GObject.registerClass(
class PortalWindow extends Gtk.ApplicationWindow {
_init(application, url, timestamp, doneCallback) {
this.parent({ application: application });
super._init({ application: application });
this.connect('delete-event', this.destroyWindow.bind(this));
this._headerBar = new PortalHeaderBar();
@ -144,11 +133,11 @@ var PortalWindow = new Lang.Class({
this.present_with_time(timestamp);
this.application.set_accels_for_action('app.quit', ['<Primary>q', '<Primary>w']);
},
}
destroyWindow() {
this.destroy();
},
}
_syncUri() {
let uri = this._webView.uri;
@ -156,12 +145,12 @@ var PortalWindow = new Lang.Class({
this._headerBar.setSubtitle(GLib.uri_unescape_string(uri, null));
else
this._headerBar.setSubtitle('');
},
}
refresh() {
this._everSeenRedirect = false;
this._webView.load_uri(this._originalUrl);
},
}
vfunc_delete_event(event) {
if (this._recheckAtExit)
@ -169,7 +158,7 @@ var PortalWindow = new Lang.Class({
else
this._doneCallback(PortalHelperResult.CANCELLED);
return false;
},
}
_onLoadChanged(view, loadEvent) {
if (loadEvent == WebKit.LoadEvent.STARTED) {
@ -183,11 +172,11 @@ var PortalWindow = new Lang.Class({
else
this._headerBar.setSecurityIcon(PortalHelperSecurityLevel.INSECURE);
}
},
}
_onInsecureContentDetected() {
this._headerBar.setSecurityIcon(PortalHelperSecurityLevel.INSECURE);
},
}
_onLoadFailedWithTlsErrors(view, failingURI, certificate, errors) {
this._headerBar.setSecurityIcon(PortalHelperSecurityLevel.INSECURE);
@ -195,7 +184,7 @@ var PortalWindow = new Lang.Class({
this._webContext.allow_tls_certificate_for_host(certificate, uri.get_host());
this._webView.load_uri(failingURI);
return true;
},
}
_onDecidePolicy(view, decision, type) {
if (type == WebKit.PolicyDecisionType.NEW_WINDOW_ACTION) {
@ -262,15 +251,13 @@ var PortalWindow = new Lang.Class({
decision.use();
return true;
},
}
});
var WebPortalHelper = new Lang.Class({
Name: 'WebPortalHelper',
Extends: Gtk.Application,
var WebPortalHelper = GObject.registerClass(
class WebPortalHelper extends Gtk.Application {
_init() {
this.parent({ application_id: 'org.gnome.Shell.PortalHelper',
super._init({ application_id: 'org.gnome.Shell.PortalHelper',
flags: Gio.ApplicationFlags.IS_SERVICE,
inactivity_timeout: 30000 });
@ -280,30 +267,30 @@ var WebPortalHelper = new Lang.Class({
let action = new Gio.SimpleAction({ name: 'quit' });
action.connect('activate', () => { this.active_window.destroyWindow(); });
this.add_action(action);
},
}
vfunc_dbus_register(connection, path) {
this._dbusImpl.export(connection, path);
this.parent(connection, path);
super.vfunc_dbus_register(connection, path);
return true;
},
}
vfunc_dbus_unregister(connection, path) {
this._dbusImpl.unexport_from_connection(connection);
this.parent(connection, path);
},
super.vfunc_dbus_unregister(connection, path);
}
vfunc_activate() {
// If launched manually (for example for testing), force a dummy authentication
// session with the default url
this.Authenticate('/org/gnome/dummy', '', 0);
},
}
Authenticate(connection, url, timestamp) {
this._queue.push({ connection: connection, url: url, timestamp: timestamp });
this._processQueue();
},
}
Close(connection) {
for (let i = 0; i < this._queue.length; i++) {
@ -318,7 +305,7 @@ var WebPortalHelper = new Lang.Class({
}
this._processQueue();
},
}
Refresh(connection) {
for (let i = 0; i < this._queue.length; i++) {
@ -330,7 +317,7 @@ var WebPortalHelper = new Lang.Class({
break;
}
}
},
}
_processQueue() {
if (this._queue.length == 0)
@ -343,7 +330,7 @@ var WebPortalHelper = new Lang.Class({
top.window = new PortalWindow(this, top.url, top.timestamp, result => {
this._dbusImpl.emit_signal('Done', new GLib.Variant('(ou)', [top.connection, result]));
});
},
}
});
function initEnvironment() {

View File

@ -1,10 +1,4 @@
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
const Pango = imports.gi.Pango;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const { Clutter, Gio, GLib, Shell } = imports.gi;
const CheckBox = imports.ui.checkBox;
const Dialog = imports.ui.dialog;
@ -21,12 +15,9 @@ var DialogResponse = {
CLOSED: 2
};
var AccessDialog = new Lang.Class({
Name: 'AccessDialog',
Extends: ModalDialog.ModalDialog,
_init(invocation, handle, title, subtitle, body, options) {
this.parent({ styleClass: 'access-dialog' });
var AccessDialog = class extends ModalDialog.ModalDialog {
constructor(invocation, handle, title, subtitle, body, options) {
super({ styleClass: 'access-dialog' });
this._invocation = invocation;
this._handle = handle;
@ -38,7 +29,7 @@ var AccessDialog = new Lang.Class({
options[option] = options[option].deep_unpack();
this._buildLayout(title, subtitle, body, options);
},
}
_buildLayout(title, subtitle, body, options) {
// No support for non-modal system dialogs, so ignore the option
@ -78,14 +69,14 @@ var AccessDialog = new Lang.Class({
action: () => {
this._sendResponse(DialogResponse.OK);
}});
},
}
open() {
this.parent();
super.open();
let connection = this._invocation.get_connection();
this._requestExported = this._request.export(connection, this._handle);
},
}
CloseAsync(invocation, params) {
if (this._invocation.get_sender() != invocation.get_sender()) {
@ -96,7 +87,7 @@ var AccessDialog = new Lang.Class({
}
this._sendResponse(DialogResponse.CLOSED);
},
}
_sendResponse(response) {
if (this._requestExported)
@ -118,12 +109,10 @@ var AccessDialog = new Lang.Class({
});
this.close();
}
});
};
var AccessDialogDBus = new Lang.Class({
Name: 'AccessDialogDBus',
_init() {
var AccessDialogDBus = class {
constructor() {
this._accessDialog = null;
this._windowTracker = Shell.WindowTracker.get_default();
@ -132,7 +121,7 @@ var AccessDialogDBus = new Lang.Class({
this._dbusImpl.export(Gio.DBus.session, '/org/freedesktop/portal/desktop');
Gio.DBus.session.own_name('org.freedesktop.impl.portal.desktop.gnome', Gio.BusNameOwnerFlags.REPLACE, null, null);
},
}
AccessDialogAsync(params, invocation) {
if (this._accessDialog) {
@ -160,4 +149,4 @@ var AccessDialogDBus = new Lang.Class({
this._accessDialog = dialog;
}
});
};

View File

@ -1,15 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
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 { Atk, Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const Atk = imports.gi.Atk;
const Main = imports.ui.main;
const SwitcherPopup = imports.ui.switcherPopup;
@ -59,12 +51,10 @@ function getWindows(workspace) {
}).filter((w, i, a) => !w.skip_taskbar && a.indexOf(w) == i);
}
var AppSwitcherPopup = new Lang.Class({
Name: 'AppSwitcherPopup',
Extends: SwitcherPopup.SwitcherPopup,
var AppSwitcherPopup = GObject.registerClass(
class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
_init() {
this.parent();
super._init();
this._thumbnails = null;
this._thumbnailTimeoutId = 0;
@ -79,10 +69,10 @@ var AppSwitcherPopup = new Lang.Class({
this._switcherList = new AppSwitcher(apps, this);
this._items = this._switcherList.icons;
},
}
vfunc_allocate(box, flags) {
this.parent(box, flags);
super.vfunc_allocate(box, flags);
// Allocate the thumbnails
// We try to avoid overflowing the screen so we base the resulting size on
@ -117,7 +107,7 @@ var AppSwitcherPopup = new Lang.Class({
childBox.y2 = childBox.y1 + childNaturalHeight;
this._thumbnails.allocate(childBox, flags);
}
},
}
_initialSelection(backward, binding) {
if (binding == 'switch-group') {
@ -140,7 +130,7 @@ var AppSwitcherPopup = new Lang.Class({
} else {
this._select(1);
}
},
}
_nextWindow() {
// We actually want the second window if we're in the unset state
@ -148,14 +138,15 @@ var AppSwitcherPopup = new Lang.Class({
this._currentWindow = 0;
return SwitcherPopup.mod(this._currentWindow + 1,
this._items[this._selectedIndex].cachedWindows.length);
},
}
_previousWindow() {
// Also assume second window here
if (this._currentWindow == -1)
this._currentWindow = 1;
return SwitcherPopup.mod(this._currentWindow - 1,
this._items[this._selectedIndex].cachedWindows.length);
},
}
_closeAppWindow(appIndex, windowIndex) {
let appIcon = this._items[appIndex];
@ -167,7 +158,7 @@ var AppSwitcherPopup = new Lang.Class({
return;
window.delete(global.get_current_time());
},
}
_quitApplication(appIndex) {
let appIcon = this._items[appIndex];
@ -175,7 +166,7 @@ var AppSwitcherPopup = new Lang.Class({
return;
appIcon.app.request_quit();
},
}
_keyPressHandler(keysym, action) {
if (action == Meta.KeyBindingAction.SWITCH_GROUP) {
@ -214,7 +205,7 @@ var AppSwitcherPopup = new Lang.Class({
}
return Clutter.EVENT_STOP;
},
}
_scrollHandler(direction) {
if (direction == Clutter.ScrollDirection.UP) {
@ -244,7 +235,7 @@ var AppSwitcherPopup = new Lang.Class({
this._select(this._next());
}
}
},
}
_itemActivatedHandler(n) {
// If the user clicks on the selected app, activate the
@ -254,24 +245,24 @@ var AppSwitcherPopup = new Lang.Class({
this._select(n, this._currentWindow);
else
this._select(n);
},
}
_itemEnteredHandler(n) {
this._select(n);
},
}
_windowActivated(thumbnailList, n) {
let appIcon = this._items[this._selectedIndex];
Main.activateWindow(appIcon.cachedWindows[n]);
this.fadeAndDestroy();
},
}
_windowEntered(thumbnailList, n) {
if (!this.mouseActive)
return;
this._select(this._selectedIndex, n);
},
}
_windowRemoved(thumbnailList, n) {
let appIcon = this._items[this._selectedIndex];
@ -282,7 +273,7 @@ var AppSwitcherPopup = new Lang.Class({
let newIndex = Math.min(n, appIcon.cachedWindows.length - 1);
this._select(this._selectedIndex, newIndex);
}
},
}
_finish(timestamp) {
let appIcon = this._items[this._selectedIndex];
@ -291,17 +282,17 @@ var AppSwitcherPopup = new Lang.Class({
else if (appIcon.cachedWindows[this._currentWindow])
Main.activateWindow(appIcon.cachedWindows[this._currentWindow], timestamp);
this.parent();
},
super._finish(timestamp);
}
_onDestroy() {
this.parent();
super._onDestroy();
if (this._thumbnails)
this._destroyThumbnails();
if (this._thumbnailTimeoutId != 0)
Mainloop.source_remove(this._thumbnailTimeoutId);
},
}
/**
* _select:
@ -357,7 +348,7 @@ var AppSwitcherPopup = new Lang.Class({
this._timeoutPopupThumbnails.bind(this));
GLib.Source.set_name_by_id(this._thumbnailTimeoutId, '[gnome-shell] this._timeoutPopupThumbnails');
}
},
}
_timeoutPopupThumbnails() {
if (!this._thumbnails)
@ -365,7 +356,7 @@ var AppSwitcherPopup = new Lang.Class({
this._thumbnailTimeoutId = 0;
this._thumbnailsFocused = false;
return GLib.SOURCE_REMOVE;
},
}
_destroyThumbnails() {
let thumbnailsActor = this._thumbnails;
@ -379,9 +370,9 @@ var AppSwitcherPopup = new Lang.Class({
}
});
this._thumbnails = null;
if (this._switcherList._items[this._selectedIndex])
if (this._switcherList._items[this._selectedIndex])
this._switcherList._items[this._selectedIndex].remove_accessible_state (Atk.StateType.EXPANDED);
},
}
_createThumbnails() {
this._thumbnails = new ThumbnailList (this._items[this._selectedIndex].cachedWindows);
@ -411,10 +402,8 @@ var AppSwitcherPopup = new Lang.Class({
}
});
var CyclerHighlight = new Lang.Class({
Name: 'CyclerHighlight',
_init() {
class CyclerHighlight {
constructor() {
this._window = null;
this.actor = new St.Widget({ layout_manager: new Clutter.BinLayout() });
@ -434,7 +423,7 @@ var CyclerHighlight = new Lang.Class({
this.actor.connect('notify::allocation',
this._onAllocationChanged.bind(this));
this.actor.connect('destroy', this._onDestroy.bind(this));
},
}
set window(w) {
if (this._window == w)
@ -452,7 +441,7 @@ var CyclerHighlight = new Lang.Class({
windowActor.hide();
this._clone.source = windowActor;
},
}
_onAllocationChanged() {
if (!this._window) {
@ -465,35 +454,33 @@ var CyclerHighlight = new Lang.Class({
this._highlight.set_position(rect.x - x, rect.y - y);
this._highlight.show();
}
},
}
_onDestroy() {
this.window = null;
}
});
};
// 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,
var CyclerList = GObject.registerClass({
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] } },
}, class CyclerList extends St.Widget {
highlight(index, justOutline) {
this.emit('item-highlighted', index);
}
});
var CyclerPopup = new Lang.Class({
Name: 'CyclerPopup',
Extends: SwitcherPopup.SwitcherPopup,
Abstract: true,
var CyclerPopup = GObject.registerClass(
class CyclerPopup extends SwitcherPopup.SwitcherPopup {
_init() {
this.parent();
if (new.target === CyclerPopup)
throw new TypeError('Cannot instantiate abstract class ' + new.target.name);
super._init();
this._items = this._getWindows();
@ -507,12 +494,12 @@ var CyclerPopup = new Lang.Class({
this._switcherList.connect('item-highlighted', (list, index) => {
this._highlightItem(index);
});
},
}
_highlightItem(index, justOutline) {
this._highlight.window = this._items[index];
global.window_group.set_child_above_sibling(this._highlight.actor, null);
},
}
_finish() {
let window = this._items[this._selectedIndex];
@ -537,25 +524,23 @@ var CyclerPopup = new Lang.Class({
Main.wm.actionMoveWindow(window, ws);
}
this.parent();
},
super._finish();
}
_onDestroy() {
this._highlight.actor.destroy();
this.parent();
super._onDestroy();
}
});
var GroupCyclerPopup = new Lang.Class({
Name: 'GroupCyclerPopup',
Extends: CyclerPopup,
var GroupCyclerPopup = GObject.registerClass(
class GroupCyclerPopup extends CyclerPopup {
_getWindows() {
let app = Shell.WindowTracker.get_default().focus_app;
return app ? app.get_windows() : [];
},
}
_keyPressHandler(keysym, action) {
if (action == Meta.KeyBindingAction.CYCLE_GROUP)
@ -569,12 +554,10 @@ var GroupCyclerPopup = new Lang.Class({
}
});
var WindowSwitcherPopup = new Lang.Class({
Name: 'WindowSwitcherPopup',
Extends: SwitcherPopup.SwitcherPopup,
var WindowSwitcherPopup = GObject.registerClass(
class WindowSwitcherPopup extends SwitcherPopup.SwitcherPopup {
_init() {
this.parent();
super._init();
this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell.window-switcher' });
let windows = this._getWindowList();
@ -585,7 +568,7 @@ var WindowSwitcherPopup = new Lang.Class({
let mode = this._settings.get_enum('app-icon-mode');
this._switcherList = new WindowList(windows, mode);
this._items = this._switcherList.icons;
},
}
_getWindowList() {
let workspace = null;
@ -597,7 +580,7 @@ var WindowSwitcherPopup = new Lang.Class({
}
return getWindows(workspace);
},
}
_closeWindow(windowIndex) {
let windowIcon = this._items[windowIndex];
@ -605,7 +588,7 @@ var WindowSwitcherPopup = new Lang.Class({
return;
windowIcon.window.delete(global.get_current_time());
},
}
_keyPressHandler(keysym, action) {
if (action == Meta.KeyBindingAction.SWITCH_WINDOWS) {
@ -624,23 +607,21 @@ var WindowSwitcherPopup = new Lang.Class({
}
return Clutter.EVENT_STOP;
},
}
_finish() {
Main.activateWindow(this._items[this._selectedIndex].window);
this.parent();
super._finish();
}
});
var WindowCyclerPopup = new Lang.Class({
Name: 'WindowCyclerPopup',
Extends: CyclerPopup,
var WindowCyclerPopup = GObject.registerClass(
class WindowCyclerPopup extends CyclerPopup {
_init() {
this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell.window-switcher' });
this.parent();
},
super._init();
}
_getWindows() {
let workspace = null;
@ -652,7 +633,7 @@ var WindowCyclerPopup = new Lang.Class({
}
return getWindows(workspace);
},
}
_keyPressHandler(keysym, action) {
if (action == Meta.KeyBindingAction.CYCLE_WINDOWS)
@ -666,12 +647,10 @@ var WindowCyclerPopup = new Lang.Class({
}
});
var AppIcon = new Lang.Class({
Name: 'AppIcon',
Extends: St.BoxLayout,
var AppIcon = GObject.registerClass(
class AppIcon extends St.BoxLayout {
_init(app) {
this.parent({ style_class: 'alt-tab-app',
super._init({ style_class: 'alt-tab-app',
vertical: true });
this.app = app;
@ -681,28 +660,26 @@ var AppIcon = new Lang.Class({
this.add(this._iconBin, { x_fill: false, y_fill: false } );
this.label = new St.Label({ text: this.app.get_name() });
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);
let [minWidth, ] = super.vfunc_get_preferred_width(forHeight);
minWidth = Math.max(minWidth, forHeight);
return [minWidth, minWidth];
}
});
var AppSwitcher = new Lang.Class({
Name: 'AppSwitcher',
Extends: SwitcherPopup.SwitcherList,
var AppSwitcher = GObject.registerClass(
class AppSwitcher extends SwitcherPopup.SwitcherList {
_init(apps, altTabPopup) {
this.parent(true);
super._init(true);
this.icons = [];
this._arrows = [];
@ -736,7 +713,7 @@ var AppSwitcher = new Lang.Class({
this._mouseTimeOutId = 0;
this.connect('destroy', this._onDestroy.bind(this));
},
}
_onDestroy() {
if (this._mouseTimeOutId != 0)
@ -745,7 +722,7 @@ var AppSwitcher = new Lang.Class({
this.icons.forEach(icon => {
icon.app.disconnect(icon._stateChangedId);
});
},
}
_setIconSize() {
let j = 0;
@ -786,16 +763,16 @@ var AppSwitcher = new Lang.Class({
break;
this.icons[i].set_size(iconSize);
}
},
}
vfunc_get_preferred_height(forWidth) {
this._setIconSize();
return this.parent(forWidth);
},
return super.vfunc_get_preferred_height(forWidth);
}
vfunc_allocate(box, flags) {
// Allocate the main list items
this.parent(box, flags);
super.vfunc_allocate(box, flags);
let contentBox = this.get_theme_node().get_content_box(box);
@ -812,7 +789,7 @@ var AppSwitcher = new Lang.Class({
childBox.y2 = childBox.y1 + arrowHeight;
this._arrows[i].allocate(childBox, flags);
}
},
}
// We override SwitcherList's _onItemEnter method to delay
// activation when the thumbnail list is open
@ -829,14 +806,14 @@ var AppSwitcher = new Lang.Class({
GLib.Source.set_name_by_id(this._mouseTimeOutId, '[gnome-shell] this._enterItem');
} else
this._itemEntered(index);
},
}
_enterItem(index) {
let [x, y, mask] = global.get_pointer();
let pickedActor = global.stage.get_actor_at_pos(Clutter.PickMode.ALL, x, y);
if (this._items[index].contains(pickedActor))
this._itemEntered(index);
},
}
// We override SwitcherList's highlight() method to also deal with
// the AppSwitcher->ThumbnailList arrows. Apps with only 1 window
@ -853,7 +830,7 @@ var AppSwitcher = new Lang.Class({
this._arrows[this._curApp].remove_style_pseudo_class('highlighted');
}
this.parent(n, justOutline);
super.highlight(n, justOutline);
this._curApp = n;
if (this._curApp != -1) {
@ -862,7 +839,7 @@ var AppSwitcher = new Lang.Class({
else
this._arrows[this._curApp].add_style_pseudo_class('highlighted');
}
},
}
_addIcon(appIcon) {
this.icons.push(appIcon);
@ -883,7 +860,7 @@ var AppSwitcher = new Lang.Class({
arrow.hide();
else
item.add_accessible_state (Atk.StateType.EXPANDABLE);
},
}
_removeIcon(app) {
let index = this.icons.findIndex(icon => {
@ -894,15 +871,13 @@ var AppSwitcher = new Lang.Class({
this.icons.splice(index, 1);
this.removeItem(index);
},
}
});
var ThumbnailList = new Lang.Class({
Name: 'ThumbnailList',
Extends: SwitcherPopup.SwitcherList,
var ThumbnailList = GObject.registerClass(
class ThumbnailList extends SwitcherPopup.SwitcherList {
_init(windows) {
this.parent(false);
super._init(false);
this._labels = new Array();
this._thumbnailBins = new Array();
@ -935,7 +910,7 @@ var ThumbnailList = new Lang.Class({
}
this.connect('destroy', this._onDestroy.bind(this));
},
}
addClones(availHeight) {
if (!this._thumbnailBins.length)
@ -968,7 +943,7 @@ var ThumbnailList = new Lang.Class({
// Make sure we only do this once
this._thumbnailBins = new Array();
},
}
_removeThumbnail(source, clone) {
let index = this._clones.indexOf(clone);
@ -984,23 +959,20 @@ var ThumbnailList = new Lang.Class({
this.highlight(SwitcherPopup.mod(index, this._clones.length));
else
this.destroy();
},
}
_onDestroy() {
this._clones.forEach(clone => {
if (clone.source)
clone.source.disconnect(clone._destroyId);
});
},
}
});
var WindowIcon = new Lang.Class({
Name: 'WindowIcon',
Extends: St.BoxLayout,
var WindowIcon = GObject.registerClass(
class WindowIcon extends St.BoxLayout {
_init(window, mode) {
this.parent({ style_class: 'alt-tab-app',
super._init({ style_class: 'alt-tab-app',
vertical: true });
this.window = window;
@ -1041,7 +1013,7 @@ var WindowIcon = new Lang.Class({
}
this._icon.set_size(size * scaleFactor, size * scaleFactor);
},
}
_createAppIcon(app, size) {
let appIcon = app ? app.create_icon_texture(size)
@ -1054,12 +1026,10 @@ var WindowIcon = new Lang.Class({
}
});
var WindowList = new Lang.Class({
Name: 'WindowList',
Extends: SwitcherPopup.SwitcherList,
var WindowList = GObject.registerClass(
class WindowList extends SwitcherPopup.SwitcherList {
_init(windows, mode) {
this.parent(true);
super._init(true);
this._label = new St.Label({ x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.CENTER });
@ -1081,16 +1051,16 @@ var WindowList = new Lang.Class({
}
this.connect('destroy', this._onDestroy.bind(this));
},
}
_onDestroy() {
this.icons.forEach(icon => {
icon.window.disconnect(icon._unmanagedSignalId);
});
},
}
vfunc_get_preferred_height(forWidth) {
let [minHeight, natHeight] = this.parent(forWidth);
let [minHeight, natHeight] = super.vfunc_get_preferred_height(forWidth);
let spacing = this.get_theme_node().get_padding(St.Side.BOTTOM);
let [labelMin, labelNat] = this._label.get_preferred_height(-1);
@ -1099,7 +1069,7 @@ var WindowList = new Lang.Class({
natHeight += labelNat + spacing;
return [minHeight, natHeight];
},
}
vfunc_allocate(box, flags) {
let themeNode = this.get_theme_node();
@ -1117,19 +1087,19 @@ var WindowList = new Lang.Class({
childBox.x2 = box.x2;
childBox.y1 = box.y1;
childBox.y2 = box.y2 - totalLabelHeight;
this.parent(childBox, flags);
super.vfunc_allocate(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) {
this.parent(index, justOutline);
super.highlight(index, justOutline);
this._label.set_text(index == -1 ? '' : this.icons[index].label.text);
},
}
_removeWindow(window) {
let index = this.icons.findIndex(icon => {

View File

@ -1,20 +1,27 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const GLib = imports.gi.GLib;
const Lang = imports.lang;
const { GLib, Gio, St } = imports.gi;
const Mainloop = imports.mainloop;
const St = imports.gi.St;
const Signals = imports.signals;
const Atk = imports.gi.Atk;
const Tweener = imports.ui.tweener;
var ANIMATED_ICON_UPDATE_TIMEOUT = 16;
var SPINNER_ANIMATION_TIME = 0.3;
var SPINNER_ANIMATION_DELAY = 1.0;
var Animation = new Lang.Class({
Name: 'Animation',
_init(file, width, height, speed) {
var Animation = class {
constructor(file, width, height, speed) {
this.actor = new St.Bin();
this.actor.set_size(width, height);
this.actor.connect('destroy', this._onDestroy.bind(this));
this.actor.connect('notify::size', this._syncAnimationSize.bind(this));
this.actor.connect('resource-scale-changed',
this._loadFile.bind(this, file, width, height));
let themeContext = St.ThemeContext.get_for_stage(global.stage);
this._scaleChangedId = themeContext.connect('notify::scale-factor',
this._loadFile.bind(this, file, width, height));
this._speed = speed;
this._isLoaded = false;
@ -22,11 +29,8 @@ var Animation = new Lang.Class({
this._timeoutId = 0;
this._frame = 0;
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
this._animations = St.TextureCache.get_default().load_sliced_image (file, width, height, scaleFactor,
this._animationsLoaded.bind(this));
this.actor.set_child(this._animations);
},
this._loadFile(file, width, height);
}
play() {
if (this._isLoaded && this._timeoutId == 0) {
@ -38,7 +42,7 @@ var Animation = new Lang.Class({
}
this._isPlaying = true;
},
}
stop() {
if (this._timeoutId > 0) {
@ -47,7 +51,24 @@ var Animation = new Lang.Class({
}
this._isPlaying = false;
},
}
_loadFile(file, width, height) {
let [validResourceScale, resourceScale] = this.actor.get_resource_scale();
this._isLoaded = false;
this.actor.destroy_all_children();
if (!validResourceScale)
return;
let texture_cache = St.TextureCache.get_default();
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
this._animations = texture_cache.load_sliced_image(file, width, height,
scaleFactor, resourceScale,
this._animationsLoaded.bind(this));
this.actor.set_child(this._animations);
}
_showFrame(frame) {
let oldFrameActor = this._animations.get_child_at_index(this._frame);
@ -59,30 +80,94 @@ var Animation = new Lang.Class({
let newFrameActor = this._animations.get_child_at_index(this._frame);
if (newFrameActor)
newFrameActor.show();
},
}
_update() {
this._showFrame(this._frame + 1);
return GLib.SOURCE_CONTINUE;
},
}
_syncAnimationSize() {
if (!this._isLoaded)
return;
let [width, height] = this.actor.get_size();
for (let i = 0; i < this._animations.get_n_children(); ++i)
this._animations.get_child_at_index(i).set_size(width, height);
}
_animationsLoaded() {
this._isLoaded = this._animations.get_n_children() > 0;
this._syncAnimationSize();
if (this._isPlaying)
this.play();
},
}
_onDestroy() {
this.stop();
}
});
var AnimatedIcon = new Lang.Class({
Name: 'AnimatedIcon',
Extends: Animation,
_init(file, size) {
this.parent(file, size, size, ANIMATED_ICON_UPDATE_TIMEOUT);
let themeContext = St.ThemeContext.get_for_stage(global.stage);
if (this._scaleChangedId)
themeContext.disconnect(this._scaleChangedId);
this._scaleChangedId = 0;
}
});
};
var AnimatedIcon = class extends Animation {
constructor(file, size) {
super(file, size, size, ANIMATED_ICON_UPDATE_TIMEOUT);
}
};
var Spinner = class extends AnimatedIcon {
constructor(size, animate=false) {
let file = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/process-working.svg');
super(file, size);
this.actor.opacity = 0;
this._animate = animate;
}
_onDestroy() {
this._animate = false;
super._onDestroy();
}
play() {
Tweener.removeTweens(this.actor);
if (this._animate) {
super.play();
Tweener.addTween(this.actor, {
opacity: 255,
delay: SPINNER_ANIMATION_DELAY,
time: SPINNER_ANIMATION_TIME,
transition: 'linear'
});
} else {
this.actor.opacity = 255;
super.play();
}
}
stop() {
Tweener.removeTweens(this.actor);
if (this._animate) {
Tweener.addTween(this.actor, {
opacity: 0,
time: SPINNER_ANIMATION_TIME,
transition: 'linear',
onComplete: () => {
this.stop(false);
}
});
} else {
this.actor.opacity = 0;
super.stop();
}
}
};

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Shell = imports.gi.Shell;
const Lang = imports.lang;
const Signals = imports.signals;
const Main = imports.ui.main;
@ -15,53 +14,63 @@ const RENAMED_DESKTOP_IDS = {
'epiphany.desktop': 'org.gnome.Epiphany.desktop',
'evolution.desktop': 'org.gnome.Evolution.desktop',
'file-roller.desktop': 'org.gnome.FileRoller.desktop',
'five-or-more.desktop': 'org.gnome.five-or-more.desktop',
'four-in-a-row.desktop': 'org.gnome.Four-in-a-row.desktop',
'gcalctool.desktop': 'org.gnome.Calculator.desktop',
'geary.desktop': 'org.gnome.Geary.desktop',
'gedit.desktop': 'org.gnome.gedit.desktop',
'glchess.desktop': 'gnome-chess.desktop',
'glines.desktop': 'five-or-more.desktop',
'gnect.desktop': 'four-in-a-row.desktop',
'glchess.desktop': 'org.gnome.Chess.desktop',
'glines.desktop': 'org.gnome.five-or-more.desktop',
'gnect.desktop': 'org.gnome.Four-in-a-row.desktop',
'gnibbles.desktop': 'org.gnome.Nibbles.desktop',
'gnobots2.desktop': 'gnome-robots.desktop',
'gnobots2.desktop': 'org.gnome.Robots.desktop',
'gnome-boxes.desktop': 'org.gnome.Boxes.desktop',
'gnome-calculator.desktop': 'org.gnome.Calculator.desktop',
'gnome-chess.desktop': 'org.gnome.Chess.desktop',
'gnome-clocks.desktop': 'org.gnome.clocks.desktop',
'gnome-contacts.desktop': 'org.gnome.Contacts.desktop',
'gnome-documents.desktop': 'org.gnome.Documents.desktop',
'gnome-font-viewer.desktop': 'org.gnome.font-viewer.desktop',
'gnome-klotski.desktop': 'org.gnome.Klotski.desktop',
'gnome-nibbles.desktop': 'org.gnome.Nibbles.desktop',
'gnome-mahjongg.desktop': 'org.gnome.Mahjongg.desktop',
'gnome-mines.desktop': 'org.gnome.Mines.desktop',
'gnome-music.desktop': 'org.gnome.Music.desktop',
'gnome-photos.desktop': 'org.gnome.Photos.desktop',
'gnome-robots.desktop': 'org.gnome.Robots.desktop',
'gnome-screenshot.desktop': 'org.gnome.Screenshot.desktop',
'gnome-software.desktop': 'org.gnome.Software.desktop',
'gnome-terminal.desktop': 'org.gnome.Terminal.desktop',
'gnome-tetravex.desktop': 'org.gnome.Tetravex.desktop',
'gnome-tweaks.desktop': 'org.gnome.tweaks.desktop',
'gnome-weather.desktop': 'org.gnome.Weather.Application.desktop',
'gnomine.desktop': 'gnome-mines.desktop',
'gnotravex.desktop': 'gnome-tetravex.desktop',
'gnotski.desktop': 'gnome-klotski.desktop',
'gtali.desktop': 'tali.desktop',
'gnome-weather.desktop': 'org.gnome.Weather.desktop',
'gnomine.desktop': 'org.gnome.Mines.desktop',
'gnotravex.desktop': 'org.gnome.Tetravex.desktop',
'gnotski.desktop': 'org.gnome.Klotski.desktop',
'gtali.desktop': 'org.gnome.Tali.desktop',
'iagno.desktop': 'org.gnome.Reversi.desktop',
'nautilus.desktop': 'org.gnome.Nautilus.desktop',
'org.gnome.gnome-2048.desktop': 'org.gnome.TwentyFortyEight.desktop',
'org.gnome.taquin.desktop': 'org.gnome.Taquin.desktop',
'org.gnome.Weather.Application.desktop': 'org.gnome.Weather.desktop',
'polari.desktop': 'org.gnome.Polari.desktop',
'tali.desktop': 'org.gnome.Tali.desktop',
'totem.desktop': 'org.gnome.Totem.desktop',
'evince.desktop': 'org.gnome.Evince.desktop',
};
var AppFavorites = new Lang.Class({
Name: 'AppFavorites',
FAVORITE_APPS_KEY: 'favorite-apps',
_init() {
class AppFavorites {
constructor() {
this.FAVORITE_APPS_KEY = 'favorite-apps';
this._favorites = {};
global.settings.connect('changed::' + this.FAVORITE_APPS_KEY, this._onFavsChanged.bind(this));
this.reload();
},
}
_onFavsChanged() {
this.reload();
this.emit('changed');
},
}
reload() {
let ids = global.settings.get_strv(this.FAVORITE_APPS_KEY);
@ -89,29 +98,29 @@ var AppFavorites = new Lang.Class({
let app = apps[i];
this._favorites[app.get_id()] = app;
}
},
}
_getIds() {
let ret = [];
for (let id in this._favorites)
ret.push(id);
return ret;
},
}
getFavoriteMap() {
return this._favorites;
},
}
getFavorites() {
let ret = [];
for (let id in this._favorites)
ret.push(this._favorites[id]);
return ret;
},
}
isFavorite(appId) {
return appId in this._favorites;
},
}
_addFavorite(appId, pos) {
if (appId in this._favorites)
@ -129,7 +138,7 @@ var AppFavorites = new Lang.Class({
ids.splice(pos, 0, appId);
global.settings.set_strv(this.FAVORITE_APPS_KEY, ids);
return true;
},
}
addFavoriteAtPos(appId, pos) {
if (!this._addFavorite(appId, pos))
@ -143,25 +152,25 @@ var AppFavorites = new Lang.Class({
this._removeFavorite(appId);
}
});
},
}
addFavorite(appId) {
this.addFavoriteAtPos(appId, -1);
},
}
moveFavoriteToPos(appId, pos) {
this._removeFavorite(appId);
this._addFavorite(appId, pos);
},
}
_removeFavorite(appId) {
if (!appId in this._favorites)
if (!(appId in this._favorites))
return false;
let ids = this._getIds().filter(id => id != appId);
global.settings.set_strv(this.FAVORITE_APPS_KEY, ids);
return true;
},
}
removeFavorite(appId) {
let ids = this._getIds();
@ -178,7 +187,7 @@ var AppFavorites = new Lang.Class({
}
});
}
});
};
Signals.addSignalMethods(AppFavorites.prototype);
var appFavoritesInstance = null;

View File

@ -1,10 +1,4 @@
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const { Clutter, Gio, GLib, Meta, Shell, St } = imports.gi;
const Main = imports.ui.main;
const ModalDialog = imports.ui.modalDialog;
@ -19,12 +13,10 @@ var AudioDevice = {
const AudioDeviceSelectionIface = loadInterfaceXML('org.gnome.Shell.AudioDeviceSelection');
var AudioDeviceSelectionDialog = new Lang.Class({
Name: 'AudioDeviceSelectionDialog',
Extends: ModalDialog.ModalDialog,
_init(devices) {
this.parent({ styleClass: 'audio-device-selection-dialog' });
var AudioDeviceSelectionDialog =
class AudioDeviceSelectionDialog extends ModalDialog.ModalDialog {
constructor(devices) {
super({ styleClass: 'audio-device-selection-dialog' });
this._deviceItems = {};
@ -39,11 +31,11 @@ var AudioDeviceSelectionDialog = new Lang.Class({
if (this._selectionBox.get_n_children() < 2)
throw new Error('Too few devices for a selection');
},
}
destroy() {
this.parent();
},
super.destroy();
}
_buildLayout(devices) {
let title = new St.Label({ style_class: 'audio-selection-title',
@ -56,12 +48,13 @@ var AudioDeviceSelectionDialog = new Lang.Class({
this._selectionBox = new St.BoxLayout({ style_class: 'audio-selection-box' });
this.contentLayout.add(this._selectionBox, { expand: true });
this.addButton({ action: this._openSettings.bind(this),
label: _("Sound Settings") });
if (Main.sessionMode.allowSettings)
this.addButton({ action: this._openSettings.bind(this),
label: _("Sound Settings") });
this.addButton({ action: this.close.bind(this),
label: _("Cancel"),
key: Clutter.Escape });
},
}
_getDeviceLabel(device) {
switch(device) {
@ -74,7 +67,7 @@ var AudioDeviceSelectionDialog = new Lang.Class({
default:
return null;
}
},
}
_getDeviceIcon(device) {
switch(device) {
@ -87,7 +80,7 @@ var AudioDeviceSelectionDialog = new Lang.Class({
default:
return null;
}
},
}
_addDevice(device) {
let box = new St.BoxLayout({ style_class: 'audio-selection-device-box',
@ -117,7 +110,7 @@ var AudioDeviceSelectionDialog = new Lang.Class({
this.close();
Main.overview.hide();
});
},
}
_openSettings() {
let desktopFile = 'gnome-sound-panel.desktop'
@ -132,23 +125,21 @@ var AudioDeviceSelectionDialog = new Lang.Class({
Main.overview.hide();
app.activate();
}
});
};
var AudioDeviceSelectionDBus = new Lang.Class({
Name: 'AudioDeviceSelectionDBus',
_init() {
var AudioDeviceSelectionDBus = class AudioDeviceSelectionDBus {
constructor() {
this._audioSelectionDialog = null;
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(AudioDeviceSelectionIface, this);
this._dbusImpl.export(Gio.DBus.session, '/org/gnome/Shell/AudioDeviceSelection');
Gio.DBus.session.own_name('org.gnome.Shell.AudioDeviceSelection', Gio.BusNameOwnerFlags.REPLACE, null, null);
},
}
_onDialogClosed() {
this._audioSelectionDialog = null;
},
}
_onDeviceSelected(dialog, device) {
let connection = this._dbusImpl.get_connection();
@ -161,7 +152,7 @@ var AudioDeviceSelectionDBus = new Lang.Class({
info ? info.name : null,
'DeviceSelected',
GLib.Variant.new('(s)', [deviceName]));
},
}
OpenAsync(params, invocation) {
if (this._audioSelectionDialog) {
@ -189,7 +180,7 @@ var AudioDeviceSelectionDBus = new Lang.Class({
this._audioSelectionDialog = dialog;
invocation.return_value(null);
},
}
CloseAsync(params, invocation) {
if (this._audioSelectionDialog &&
@ -198,4 +189,4 @@ var AudioDeviceSelectionDBus = new Lang.Class({
invocation.return_value(null);
}
});
};

View File

@ -93,13 +93,7 @@
// MetaBackgroundImage MetaBackgroundImage
// MetaBackgroundImage MetaBackgroundImage
const Clutter = imports.gi.Clutter;
const GDesktopEnums = imports.gi.GDesktopEnums;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GnomeDesktop = imports.gi.GnomeDesktop;
const Lang = imports.lang;
const Meta = imports.gi.Meta;
const { Clutter, GDesktopEnums, Gio, GLib, GnomeDesktop, Meta } = imports.gi;
const Signals = imports.signals;
const LoginManager = imports.misc.loginManager;
@ -138,14 +132,12 @@ function _fileEqual0(file1, file2) {
return file1.equal(file2);
}
var BackgroundCache = new Lang.Class({
Name: 'BackgroundCache',
_init() {
var BackgroundCache = class BackgroundCache {
constructor() {
this._fileMonitors = {};
this._backgroundSources = {};
this._animations = {};
},
}
monitorFile(file) {
let key = file.hash();
@ -163,7 +155,7 @@ var BackgroundCache = new Lang.Class({
});
this._fileMonitors[key] = monitor;
},
}
getAnimation(params) {
params = Params.parse(params, { file: null,
@ -195,7 +187,7 @@ var BackgroundCache = new Lang.Class({
GLib.Source.set_name_by_id(id, '[gnome-shell] params.onLoaded');
}
});
},
}
getBackgroundSource(layoutManager, settingsSchema) {
// The layoutManager is always the same one; we pass in it since
@ -209,7 +201,7 @@ var BackgroundCache = new Lang.Class({
}
return this._backgroundSources[settingsSchema];
},
}
releaseBackgroundSource(settingsSchema) {
if (settingsSchema in this._backgroundSources) {
@ -221,7 +213,7 @@ var BackgroundCache = new Lang.Class({
}
}
}
});
};
Signals.addSignalMethods(BackgroundCache.prototype);
function getBackgroundCache() {
@ -230,10 +222,8 @@ function getBackgroundCache() {
return _backgroundCache;
}
var Background = new Lang.Class({
Name: 'Background',
_init(params) {
var Background = class Background {
constructor(params) {
params = Params.parse(params, { monitorIndex: 0,
layoutManager: Main.layoutManager,
settings: null,
@ -272,7 +262,7 @@ var Background = new Lang.Class({
});
this._load();
},
}
destroy() {
this._cancellable.cancel();
@ -298,12 +288,12 @@ var Background = new Lang.Class({
if (this._settingsChangedSignalId != 0)
this._settings.disconnect(this._settingsChangedSignalId);
this._settingsChangedSignalId = 0;
},
}
updateResolution() {
if (this._animation)
this._refreshAnimation();
},
}
_refreshAnimation() {
if (!this._animation)
@ -311,7 +301,7 @@ var Background = new Lang.Class({
this._removeAnimationTimeout();
this._updateAnimation();
},
}
_setLoaded() {
if (this.isLoaded)
@ -324,7 +314,7 @@ var Background = new Lang.Class({
return GLib.SOURCE_REMOVE;
});
GLib.Source.set_name_by_id(id, '[gnome-shell] this.emit');
},
}
_loadPattern() {
let colorString, res, color, secondColor;
@ -340,7 +330,7 @@ var Background = new Lang.Class({
this.background.set_color(color);
else
this.background.set_gradient(shadingType, color, secondColor);
},
}
_watchFile(file) {
let key = file.hash();
@ -357,14 +347,14 @@ var Background = new Lang.Class({
}
});
this._fileWatches[key] = signalId;
},
}
_removeAnimationTimeout() {
if (this._updateAnimationTimeoutId) {
GLib.source_remove(this._updateAnimationTimeoutId);
this._updateAnimationTimeoutId = 0;
}
},
}
_updateAnimation() {
this._updateAnimationTimeoutId = 0;
@ -404,7 +394,7 @@ var Background = new Lang.Class({
});
}
}
},
}
_queueUpdateAnimation() {
if (this._updateAnimationTimeoutId != 0)
@ -433,7 +423,7 @@ var Background = new Lang.Class({
return GLib.SOURCE_REMOVE;
});
GLib.Source.set_name_by_id(this._updateAnimationTimeoutId, '[gnome-shell] this._updateAnimation');
},
}
_loadAnimation(file) {
this._cache.getAnimation({ file: file,
@ -450,7 +440,7 @@ var Background = new Lang.Class({
this._watchFile(file);
}
});
},
}
_loadImage(file) {
this.background.set_file(file, this._style);
@ -466,14 +456,14 @@ var Background = new Lang.Class({
image.disconnect(id);
});
}
},
}
_loadFile(file) {
if (file.get_basename().endsWith('.xml'))
this._loadAnimation(file);
else
this._loadImage(file);
},
}
_load() {
this._cache = getBackgroundCache();
@ -486,16 +476,14 @@ var Background = new Lang.Class({
}
this._loadFile(this._file);
},
});
}
};
Signals.addSignalMethods(Background.prototype);
let _systemBackground;
var SystemBackground = new Lang.Class({
Name: 'SystemBackground',
_init() {
var SystemBackground = class SystemBackground {
constructor() {
let file = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/noise-texture.png');
if (_systemBackground == null) {
@ -524,14 +512,12 @@ var SystemBackground = new Lang.Class({
image = null;
});
}
},
});
}
};
Signals.addSignalMethods(SystemBackground.prototype);
var BackgroundSource = new Lang.Class({
Name: 'BackgroundSource',
_init(layoutManager, settingsSchema) {
var BackgroundSource = class BackgroundSource {
constructor(layoutManager, settingsSchema) {
// Allow override the background image setting for performance testing
this._layoutManager = layoutManager;
this._overrideImage = GLib.getenv('SHELL_BACKGROUND_IMAGE');
@ -542,7 +528,7 @@ var BackgroundSource = new Lang.Class({
this._monitorsChangedId =
monitorManager.connect('monitors-changed',
this._onMonitorsChanged.bind(this));
},
}
_onMonitorsChanged() {
for (let monitorIndex in this._backgrounds) {
@ -556,7 +542,7 @@ var BackgroundSource = new Lang.Class({
delete this._backgrounds[monitorIndex];
}
}
},
}
getBackground(monitorIndex) {
let file = null;
@ -603,7 +589,7 @@ var BackgroundSource = new Lang.Class({
}
return this._backgrounds[monitorIndex];
},
}
destroy() {
let monitorManager = Meta.MonitorManager.get();
@ -617,12 +603,10 @@ var BackgroundSource = new Lang.Class({
this._backgrounds = null;
}
});
};
var Animation = new Lang.Class({
Name: 'Animation',
_init(params) {
var Animation = class Animation {
constructor(params) {
params = Params.parse(params, { file: null });
this.file = params.file;
@ -630,7 +614,7 @@ var Animation = new Lang.Class({
this.transitionProgress = 0.0;
this.transitionDuration = 0.0;
this.loaded = false;
},
}
load(callback) {
this._show = new GnomeDesktop.BGSlideShow({ filename: this.file.get_path() });
@ -640,7 +624,7 @@ var Animation = new Lang.Class({
if (callback)
callback();
});
},
}
update(monitor) {
this.keyFrameFiles = [];
@ -661,14 +645,12 @@ var Animation = new Lang.Class({
if (filename2)
this.keyFrameFiles.push(Gio.File.new_for_path(filename2));
},
});
}
};
Signals.addSignalMethods(Animation.prototype);
var BackgroundManager = new Lang.Class({
Name: 'BackgroundManager',
_init(params) {
var BackgroundManager = class BackgroundManager {
constructor(params) {
params = Params.parse(params, { container: null,
layoutManager: Main.layoutManager,
monitorIndex: null,
@ -688,7 +670,7 @@ var BackgroundManager = new Lang.Class({
this.backgroundActor = this._createBackgroundActor();
this._newBackgroundActor = null;
},
}
destroy() {
let cache = getBackgroundCache();
@ -704,7 +686,7 @@ var BackgroundManager = new Lang.Class({
this.backgroundActor.destroy();
this.backgroundActor = null;
}
},
}
_swapBackgroundActor() {
let oldBackgroundActor = this.backgroundActor;
@ -721,7 +703,7 @@ var BackgroundManager = new Lang.Class({
oldBackgroundActor.destroy();
}
});
},
}
_updateBackgroundActor() {
if (this._newBackgroundActor) {
@ -750,7 +732,7 @@ var BackgroundManager = new Lang.Class({
this._swapBackgroundActor();
});
}
},
}
_createBackgroundActor() {
let background = this._backgroundSource.getBackground(this._monitorIndex);
@ -764,10 +746,8 @@ var BackgroundManager = new Lang.Class({
this._container.add_child(backgroundActor);
let monitor = this._layoutManager.monitors[this._monitorIndex];
backgroundActor.set_size(monitor.width, monitor.height);
if (this._controlPosition) {
let monitor = this._layoutManager.monitors[this._monitorIndex];
backgroundActor.set_position(monitor.x, monitor.y);
backgroundActor.lower_bottom();
}
@ -787,6 +767,6 @@ var BackgroundManager = new Lang.Class({
});
return backgroundActor;
},
});
}
};
Signals.addSignalMethods(BackgroundManager.prototype);

View File

@ -1,20 +1,14 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Lang = imports.lang;
const St = imports.gi.St;
const Shell = imports.gi.Shell;
const { Clutter, St } = imports.gi;
const BoxPointer = imports.ui.boxpointer;
const Main = imports.ui.main;
const PopupMenu = imports.ui.popupMenu;
var BackgroundMenu = new Lang.Class({
Name: 'BackgroundMenu',
Extends: PopupMenu.PopupMenu,
_init(layoutManager) {
this.parent(layoutManager.dummyCursor, 0, St.Side.TOP);
var BackgroundMenu = class BackgroundMenu extends PopupMenu.PopupMenu {
constructor(layoutManager) {
super(layoutManager.dummyCursor, 0, St.Side.TOP);
this.addSettingsAction(_("Change Background…"), 'gnome-background-panel.desktop');
this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
@ -26,7 +20,7 @@ var BackgroundMenu = new Lang.Class({
layoutManager.uiGroup.add_actor(this.actor);
this.actor.hide();
}
});
};
function addBackgroundMenu(actor, layoutManager) {
actor.reactive = true;

View File

@ -1,16 +1,10 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Atk = imports.gi.Atk;
const Cairo = imports.cairo;
const Clutter = imports.gi.Clutter;
const Lang = imports.lang;
const St = imports.gi.St;
const { Atk, Clutter, St } = imports.gi;
const Signals = imports.signals;
var BarLevel = new Lang.Class({
Name: "BarLevel",
_init(value, params) {
var BarLevel = class {
constructor(value, params) {
if (isNaN(value))
// Avoid spreading NaNs around
throw TypeError('The bar level value must be a number');
@ -40,7 +34,7 @@ var BarLevel = new Lang.Class({
this._customAccessible.connect('set-current-value', this._setCurrentValue.bind(this));
this.connect('value-changed', this._valueChanged.bind(this));
},
}
setValue(value) {
if (isNaN(value))
@ -48,7 +42,7 @@ var BarLevel = new Lang.Class({
this._value = Math.max(Math.min(value, this._maxValue), 0);
this.actor.queue_repaint();
},
}
setMaximumValue(value) {
if (isNaN(value))
@ -57,7 +51,7 @@ var BarLevel = new Lang.Class({
this._maxValue = Math.max(value, 1);
this._overdriveStart = Math.min(this._overdriveStart, this._maxValue);
this.actor.queue_repaint();
},
}
setOverdriveStart(value) {
if (isNaN(value))
@ -69,7 +63,7 @@ var BarLevel = new Lang.Class({
this._overdriveStart = value;
this._value = Math.max(Math.min(value, this._maxValue), 0);
this.actor.queue_repaint();
},
}
_barLevelRepaint(area) {
let cr = area.get_context();
@ -176,35 +170,34 @@ var BarLevel = new Lang.Class({
}
cr.$dispose();
},
}
_getCurrentValue(actor) {
return this._value;
},
}
_getOverdriveStart(actor) {
return this._overdriveStart;
},
}
_getMinimumValue(actor) {
return 0;
},
}
_getMaximumValue(actor) {
return this._maxValue;
},
}
_setCurrentValue(actor, value) {
this._value = value;
},
}
_valueChanged(barLevel, value, property) {
this._customAccessible.notify("accessible-value");
},
}
get value() {
return this._value;
}
});
};
Signals.addSignalMethods(BarLevel.prototype);

View File

@ -1,11 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Lang = imports.lang;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const St = imports.gi.St;
const { Clutter, GObject, Meta, Shell, St } = imports.gi;
const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
@ -29,16 +24,14 @@ var POPUP_ANIMATION_TIME = 0.15;
* placed. The arrow position may be controlled via
* setArrowOrigin(). The arrow side might be temporarily flipped
* depending on the box size and source position to keep the box
* totally inside the monitor if possible.
* totally inside the monitor workarea if possible.
*
*/
var BoxPointer = new Lang.Class({
Name: 'BoxPointer',
Extends: St.Widget,
var BoxPointer = GObject.registerClass({
Signals: { 'arrow-side-changed': {} },
}, class BoxPointer extends St.Widget {
_init(arrowSide, binProperties) {
this.parent();
super._init();
this.actor = this;
@ -54,31 +47,27 @@ var BoxPointer = new Lang.Class({
this._border.connect('repaint', this._drawBorder.bind(this));
this.add_actor(this._border);
this.bin.raise(this._border);
this._xOffset = 0;
this._yOffset = 0;
this._xPosition = 0;
this._yPosition = 0;
this._sourceAlignment = 0.5;
this._capturedEventId = 0;
this._muteInput();
},
}
get arrowSide() {
return this._arrowSide;
},
}
_muteInput() {
if (this._capturedEventId == 0)
this._capturedEventId = this.connect('captured-event',
() => Clutter.EVENT_STOP);
},
}
_unmuteInput() {
if (this._capturedEventId != 0) {
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.
@ -94,7 +83,7 @@ var BoxPointer = new Lang.Class({
}
this.visible = true;
},
}
hide(animate, onComplete) {
if (animate !== undefined) {
@ -108,7 +97,7 @@ var BoxPointer = new Lang.Class({
}
this.visible = false;
},
}
open(animate, onComplete) {
let themeNode = this.get_theme_node();
@ -125,23 +114,23 @@ var BoxPointer = new Lang.Class({
if (animate & PopupAnimation.SLIDE) {
switch (this._arrowSide) {
case St.Side.TOP:
this.yOffset = -rise;
this.translation_y = -rise;
break;
case St.Side.BOTTOM:
this.yOffset = rise;
this.translation_y = rise;
break;
case St.Side.LEFT:
this.xOffset = -rise;
this.translation_x = -rise;
break;
case St.Side.RIGHT:
this.xOffset = rise;
this.translation_x = rise;
break;
}
}
Tweener.addTween(this, { opacity: 255,
xOffset: 0,
yOffset: 0,
translation_x: 0,
translation_y: 0,
transition: 'linear',
onComplete: () => {
this._unmuteInput();
@ -149,14 +138,14 @@ var BoxPointer = new Lang.Class({
onComplete();
},
time: animationTime });
},
}
close(animate, onComplete) {
if (!this.visible)
return;
let xOffset = 0;
let yOffset = 0;
let translationX = 0;
let translationY = 0;
let themeNode = this.get_theme_node();
let rise = themeNode.get_length('-arrow-rise');
let fade = (animate & PopupAnimation.FADE);
@ -165,16 +154,16 @@ var BoxPointer = new Lang.Class({
if (animate & PopupAnimation.SLIDE) {
switch (this._arrowSide) {
case St.Side.TOP:
yOffset = rise;
translationY = rise;
break;
case St.Side.BOTTOM:
yOffset = -rise;
translationY = -rise;
break;
case St.Side.LEFT:
xOffset = rise;
translationX = rise;
break;
case St.Side.RIGHT:
xOffset = -rise;
translationX = -rise;
break;
}
}
@ -183,20 +172,20 @@ var BoxPointer = new Lang.Class({
Tweener.removeTweens(this);
Tweener.addTween(this, { opacity: fade ? 0 : 255,
xOffset: xOffset,
yOffset: yOffset,
translation_x: translationX,
translation_y: translationY,
transition: 'linear',
time: animationTime,
onComplete: () => {
this.hide();
this.opacity = 0;
this.xOffset = 0;
this.yOffset = 0;
this.translation_x = 0;
this.translation_y = 0;
if (onComplete)
onComplete();
}
});
},
}
_adjustAllocationForArrow(isWidth, minSize, natSize) {
let themeNode = this.get_theme_node();
@ -211,7 +200,7 @@ var BoxPointer = new Lang.Class({
}
return [minSize, natSize];
},
}
vfunc_get_preferred_width(forHeight) {
let themeNode = this.get_theme_node();
@ -221,7 +210,7 @@ var BoxPointer = new Lang.Class({
width = this._adjustAllocationForArrow(true, ...width);
return themeNode.adjust_preferred_width(...width);
},
}
vfunc_get_preferred_height(forWidth) {
let themeNode = this.get_theme_node();
@ -232,7 +221,7 @@ var BoxPointer = new Lang.Class({
height = this._adjustAllocationForArrow(false, ...height);
return themeNode.adjust_preferred_height(...height);
},
}
vfunc_allocate(box, flags) {
this.set_allocation(box, flags);
@ -276,7 +265,7 @@ var BoxPointer = new Lang.Class({
this._reposition();
this._updateFlip();
}
},
}
_drawBorder(area) {
let themeNode = this.get_theme_node();
@ -458,7 +447,7 @@ var BoxPointer = new Lang.Class({
}
cr.$dispose();
},
}
setPosition(sourceActor, alignment) {
// We need to show it now to force an allocation,
@ -470,7 +459,7 @@ var BoxPointer = new Lang.Class({
this._reposition();
this._updateFlip();
},
}
setSourceAlignment(alignment) {
this._sourceAlignment = alignment;
@ -479,16 +468,20 @@ var BoxPointer = new Lang.Class({
return;
this.setPosition(this._sourceActor, this._arrowAlignment);
},
}
_reposition() {
let sourceActor = this._sourceActor;
let alignment = this._arrowAlignment;
let monitorIndex = Main.layoutManager.findIndexForActor(sourceActor);
this._sourceAllocation = Shell.util_get_transformed_allocation(sourceActor);
this._workArea = Main.layoutManager.getWorkAreaForMonitor(monitorIndex);
// Position correctly relative to the sourceActor
let sourceNode = sourceActor.get_theme_node();
let sourceContentBox = sourceNode.get_content_box(sourceActor.get_allocation_box());
let sourceAllocation = Shell.util_get_transformed_allocation(sourceActor);
let sourceAllocation = this._sourceAllocation;
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.get_preferred_size();
@ -496,7 +489,7 @@ var BoxPointer = new Lang.Class({
// 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 workarea = this._workArea;
let themeNode = this.get_theme_node();
let borderWidth = themeNode.get_length('-arrow-border-width');
let arrowBase = themeNode.get_length('-arrow-base');
@ -546,8 +539,8 @@ var BoxPointer = new Lang.Class({
case St.Side.BOTTOM:
resX = sourceCenterX - (halfMargin + (natWidth - margin) * alignment);
resX = Math.max(resX, monitor.x + padding);
resX = Math.min(resX, monitor.x + monitor.width - (padding + natWidth));
resX = Math.max(resX, workarea.x + padding);
resX = Math.min(resX, workarea.x + workarea.width - (padding + natWidth));
arrowOrigin = sourceCenterX - resX;
if (arrowOrigin <= (x1 + (borderRadius + halfBase))) {
@ -565,8 +558,8 @@ var BoxPointer = new Lang.Class({
case St.Side.RIGHT:
resY = sourceCenterY - (halfMargin + (natHeight - margin) * alignment);
resY = Math.max(resY, monitor.y + padding);
resY = Math.min(resY, monitor.y + monitor.height - (padding + natHeight));
resY = Math.max(resY, workarea.y + padding);
resY = Math.min(resY, workarea.y + workarea.height - (padding + natHeight));
arrowOrigin = sourceCenterY - resY;
if (arrowOrigin <= (y1 + (borderRadius + halfBase))) {
@ -590,10 +583,10 @@ var BoxPointer = new Lang.Class({
parent = parent.get_parent();
}
this._xPosition = Math.floor(x);
this._yPosition = Math.floor(y);
this._shiftActor();
},
// Actually set the position
this.x = Math.floor(x);
this.y = Math.floor(y);
}
// @origin: Coordinate specifying middle of the arrow, along
// the Y axis for St.Side.LEFT, St.Side.RIGHT from the top and X axis from
@ -603,7 +596,7 @@ var BoxPointer = new Lang.Class({
this._arrowOrigin = origin;
this._border.queue_repaint();
}
},
}
// @actor: an actor relative to which the arrow is positioned.
// Differently from setPosition, this will not move the boxpointer itself,
@ -613,52 +606,38 @@ var BoxPointer = new Lang.Class({
this._arrowActor = actor;
this._border.queue_repaint();
}
},
_shiftActor() {
// Since the position of the BoxPointer depends on the allocated size
// of the BoxPointer and the position of the source actor, trying
// to position the BoxPointer via the x/y properties will result in
// allocation loops and warnings. Instead we do the positioning via
// the anchor point, which is independent of allocation, and leave
// x == y == 0.
this.set_anchor_point(-(this._xPosition + this._xOffset),
-(this._yPosition + this._yOffset));
},
}
_calculateArrowSide(arrowSide) {
let sourceAllocation = Shell.util_get_transformed_allocation(this._sourceActor);
let sourceAllocation = this._sourceAllocation;
let [minWidth, minHeight, boxWidth, boxHeight] = this.get_preferred_size();
let monitorActor = this.sourceActor;
if (!monitorActor)
monitorActor = this;
let monitor = Main.layoutManager.findMonitorForActor(monitorActor);
let workarea = this._workArea;
switch (arrowSide) {
case St.Side.TOP:
if (sourceAllocation.y2 + boxHeight > monitor.y + monitor.height &&
boxHeight < sourceAllocation.y1 - monitor.y)
if (sourceAllocation.y2 + boxHeight > workarea.y + workarea.height &&
boxHeight < sourceAllocation.y1 - workarea.y)
return St.Side.BOTTOM;
break;
case St.Side.BOTTOM:
if (sourceAllocation.y1 - boxHeight < monitor.y &&
boxHeight < monitor.y + monitor.height - sourceAllocation.y2)
if (sourceAllocation.y1 - boxHeight < workarea.y &&
boxHeight < workarea.y + workarea.height - sourceAllocation.y2)
return St.Side.TOP;
break;
case St.Side.LEFT:
if (sourceAllocation.x2 + boxWidth > monitor.x + monitor.width &&
boxWidth < sourceAllocation.x1 - monitor.x)
if (sourceAllocation.x2 + boxWidth > workarea.x + workarea.width &&
boxWidth < sourceAllocation.x1 - workarea.x)
return St.Side.RIGHT;
break;
case St.Side.RIGHT:
if (sourceAllocation.x1 - boxWidth < monitor.x &&
boxWidth < monitor.x + monitor.width - sourceAllocation.x2)
if (sourceAllocation.x1 - boxWidth < workarea.x &&
boxWidth < workarea.x + workarea.width - sourceAllocation.x2)
return St.Side.LEFT;
break;
}
return arrowSide;
},
}
_updateFlip() {
let arrowSide = this._calculateArrowSide(this._userArrowSide);
@ -672,36 +651,18 @@ var BoxPointer = new Lang.Class({
this.emit('arrow-side-changed');
}
},
set xOffset(offset) {
this._xOffset = offset;
this._shiftActor();
},
get xOffset() {
return this._xOffset;
},
set yOffset(offset) {
this._yOffset = offset;
this._shiftActor();
},
get yOffset() {
return this._yOffset;
},
}
updateArrowSide(side) {
this._arrowSide = side;
this._border.queue_repaint();
this.emit('arrow-side-changed');
},
}
getPadding(side) {
return this.bin.get_theme_node().get_padding(side);
},
}
getArrowHeight() {
return this.get_theme_node().get_length('-arrow-rise');

View File

@ -1,13 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
const St = imports.gi.St;
const { Clutter, Gio, GLib, Shell, St } = imports.gi;
const Signals = imports.signals;
const Shell = imports.gi.Shell;
const Main = imports.ui.main;
const MessageList = imports.ui.messageList;
@ -15,6 +9,8 @@ const MessageTray = imports.ui.messageTray;
const Mpris = imports.ui.mpris;
const Util = imports.misc.util;
const { loadInterfaceXML } = imports.misc.fileUtils;
var MSECS_IN_DAY = 24 * 60 * 60 * 1000;
var SHOW_WEEKDATE_KEY = 'show-weekdate';
var ELLIPSIS_CHAR = '\u2026';
@ -89,64 +85,45 @@ function _getCalendarDayAbbreviation(dayNumber) {
// Abstraction for an appointment/event in a calendar
var CalendarEvent = new Lang.Class({
Name: 'CalendarEvent',
_init(id, date, end, summary, allDay) {
var CalendarEvent = class CalendarEvent {
constructor(id, date, end, summary, allDay) {
this.id = id;
this.date = date;
this.end = end;
this.summary = summary;
this.allDay = allDay;
}
});
};
// Interface for appointments/events - e.g. the contents of a calendar
//
// First, an implementation with no events
var EmptyEventSource = new Lang.Class({
Name: 'EmptyEventSource',
_init() {
var EmptyEventSource = class EmptyEventSource {
constructor() {
this.isLoading = false;
this.isDummy = true;
this.hasCalendars = false;
},
}
destroy() {
},
ignoreEvent(event) {
},
}
requestRange(begin, end) {
},
}
getEvents(begin, end) {
let result = [];
return result;
},
}
hasEvents(day) {
return false;
}
});
};
Signals.addSignalMethods(EmptyEventSource.prototype);
const CalendarServerIface = `
<node>
<interface name="org.gnome.Shell.CalendarServer">
<method name="GetEvents">
<arg type="x" direction="in" />
<arg type="x" direction="in" />
<arg type="b" direction="in" />
<arg type="a(sssbxxa{sv})" direction="out" />
</method>
<property name="HasCalendars" type="b" access="read" />
<signal name="Changed" />
</interface>
</node>`;
const CalendarServerIface = loadInterfaceXML('org.gnome.Shell.CalendarServer');
const CalendarServerInfo = Gio.DBusInterfaceInfo.new_for_xml(CalendarServerIface);
@ -177,22 +154,12 @@ function _dateIntervalsOverlap(a0, a1, b0, b1)
}
// an implementation that reads data from a session bus service
var DBusEventSource = new Lang.Class({
Name: 'DBusEventSource',
_init() {
var DBusEventSource = class DBusEventSource {
constructor() {
this._resetCache();
this.isLoading = false;
this.isDummy = false;
this._ignoredEvents = new Map();
let savedState = global.get_persistent_state('as', 'ignored_events');
if (savedState)
savedState.deep_unpack().forEach(eventId => {
this._ignoredEvents.set(eventId, true);
});
this._initialized = false;
this._dbusProxy = new CalendarServer();
this._dbusProxy.init_async(GLib.PRIORITY_DEFAULT, null, (object, result) => {
@ -235,39 +202,39 @@ var DBusEventSource = new Lang.Class({
this._onNameAppeared();
}
});
},
}
destroy() {
this._dbusProxy.run_dispose();
},
}
get hasCalendars() {
if (this._initialized)
return this._dbusProxy.HasCalendars;
else
return false;
},
}
_resetCache() {
this._events = [];
this._lastRequestBegin = null;
this._lastRequestEnd = null;
},
}
_onNameAppeared(owner) {
this._initialized = true;
this._resetCache();
this._loadEvents(true);
},
}
_onNameVanished(oldOwner) {
this._resetCache();
this.emit('changed');
},
}
_onChanged() {
this._loadEvents(false);
},
}
_onEventsReceived(results, error) {
let newEvents = [];
@ -289,7 +256,7 @@ var DBusEventSource = new Lang.Class({
this._events = newEvents;
this.isLoading = false;
this.emit('changed');
},
}
_loadEvents(forceReload) {
// Ignore while loading
@ -303,17 +270,7 @@ var DBusEventSource = new Lang.Class({
this._onEventsReceived.bind(this),
Gio.DBusCallFlags.NONE);
}
},
ignoreEvent(event) {
if (this._ignoredEvents.get(event.id))
return;
this._ignoredEvents.set(event.id, true);
let savedState = new GLib.Variant('as', [...this._ignoredEvents.keys()]);
global.set_persistent_state('ignored_events', savedState);
this.emit('changed');
},
}
requestRange(begin, end) {
if (!(_datesEqual(begin, this._lastRequestBegin) && _datesEqual(end, this._lastRequestEnd))) {
@ -324,16 +281,13 @@ var DBusEventSource = new Lang.Class({
this._curRequestEnd = end;
this._loadEvents(false);
}
},
}
getEvents(begin, end) {
let result = [];
for(let n = 0; n < this._events.length; n++) {
let event = this._events[n];
if (this._ignoredEvents.has(event.id))
continue;
if (_dateIntervalsOverlap (event.date, event.end, begin, end)) {
result.push(event);
}
@ -345,7 +299,7 @@ var DBusEventSource = new Lang.Class({
return d1.getTime() - d2.getTime();
});
return result;
},
}
hasEvents(day) {
let dayBegin = _getBeginningOfDay(day);
@ -358,13 +312,11 @@ var DBusEventSource = new Lang.Class({
return true;
}
});
};
Signals.addSignalMethods(DBusEventSource.prototype);
var Calendar = new Lang.Class({
Name: 'Calendar',
_init() {
var Calendar = class Calendar {
constructor() {
this._weekStart = Shell.util_get_week_start();
this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.calendar' });
@ -402,7 +354,7 @@ var Calendar = new Lang.Class({
this._onScroll.bind(this));
this._buildHeader ();
},
}
// @eventSource: is an object implementing the EventSource API, e.g. the
// requestRange(), getEvents(), hasEvents() methods and the ::changed signal.
@ -414,7 +366,7 @@ var Calendar = new Lang.Class({
});
this._rebuildCalendar();
this._update();
},
}
// Sets the calendar to show a specific date
setDate(date) {
@ -424,14 +376,14 @@ var Calendar = new Lang.Class({
this._selectedDate = date;
this._update();
this.emit('selected-date-changed', new Date(this._selectedDate));
},
}
updateTimeZone() {
// The calendar need to be rebuilt after a time zone update because
// the date might have changed.
this._rebuildCalendar();
this._update();
},
}
_buildHeader() {
let layout = this.actor.layout_manager;
@ -488,7 +440,7 @@ var Calendar = new Lang.Class({
// All the children after this are days, and get removed when we update the calendar
this._firstDayIndex = this.actor.get_n_children();
},
}
_onScroll(actor, event) {
switch (event.get_scroll_direction()) {
@ -502,7 +454,7 @@ var Calendar = new Lang.Class({
break;
}
return Clutter.EVENT_PROPAGATE;
},
}
_onPrevMonthButtonClicked() {
let newDate = new Date(this._selectedDate);
@ -526,7 +478,7 @@ var Calendar = new Lang.Class({
this._backButton.grab_key_focus();
this.setDate(newDate);
},
}
_onNextMonthButtonClicked() {
let newDate = new Date(this._selectedDate);
@ -550,14 +502,14 @@ var Calendar = new Lang.Class({
this._forwardButton.grab_key_focus();
this.setDate(newDate);
},
}
_onSettingsChange() {
this._useWeekdate = this._settings.get_boolean(SHOW_WEEKDATE_KEY);
this._buildHeader();
this._rebuildCalendar();
this._update();
},
}
_rebuildCalendar() {
let now = new Date();
@ -678,7 +630,7 @@ var Calendar = new Lang.Class({
// Signal to the event source that we are interested in events
// only from this date range
this._eventSource.requestRange(beginDate, iter);
},
}
_update() {
let now = new Date();
@ -701,18 +653,17 @@ var Calendar = new Lang.Class({
button.remove_style_pseudo_class('selected');
});
}
});
};
Signals.addSignalMethods(Calendar.prototype);
var EventMessage = new Lang.Class({
Name: 'EventMessage',
Extends: MessageList.Message,
var EventMessage = class EventMessage extends MessageList.Message {
constructor(event, date) {
super('', event.summary);
_init(event, date) {
this._event = event;
this._date = date;
this.parent(this._formatEventTime(), event.summary);
this.setTitle(this._formatEventTime());
this._icon = new St.Icon({ icon_name: 'x-office-calendar-symbolic' });
this.setIcon(this._icon);
@ -721,7 +672,7 @@ var EventMessage = new Lang.Class({
let iconVisible = this.actor.get_parent().has_style_pseudo_class('first-child');
this._icon.opacity = (iconVisible ? 255 : 0);
});
},
}
_formatEventTime() {
let periodBegin = _getBeginningOfDay(this._date);
@ -754,23 +705,17 @@ var EventMessage = new Lang.Class({
title = title + ELLIPSIS_CHAR;
}
return title;
},
canClose() {
return isToday(this._date);
}
});
};
var NotificationMessage = new Lang.Class({
Name: 'NotificationMessage',
Extends: MessageList.Message,
_init(notification) {
this.notification = notification;
this.parent(notification.title, notification.bannerBodyText);
var NotificationMessage =
class NotificationMessage extends MessageList.Message {
constructor(notification) {
super(notification.title, notification.bannerBodyText);
this.setUseBodyMarkup(notification.bannerBodyMarkup);
this.notification = notification;
this.setIcon(this._getIcon());
this.connect('close', () => {
@ -779,13 +724,14 @@ var NotificationMessage = new Lang.Class({
this.notification.destroy(MessageTray.NotificationDestroyedReason.DISMISSED);
});
this._destroyId = notification.connect('destroy', () => {
this._disconnectNotificationSignals();
this.notification = null;
if (!this._closed)
this.close();
});
this._updatedId = notification.connect('updated',
this._onUpdated.bind(this));
},
}
_getIcon() {
if (this.notification.gicon)
@ -793,22 +739,25 @@ var NotificationMessage = new Lang.Class({
icon_size: MESSAGE_ICON_SIZE });
else
return this.notification.source.createIcon(MESSAGE_ICON_SIZE);
},
}
_onUpdated(n, clear) {
this.setIcon(this._getIcon());
this.setTitle(n.title);
this.setBody(n.bannerBodyText);
this.setUseBodyMarkup(n.bannerBodyMarkup);
},
}
_onClicked() {
this.notification.activate();
},
}
_onDestroy() {
this.parent();
super._onDestroy();
this._disconnectNotificationSignals();
}
_disconnectNotificationSignals() {
if (this._updatedId)
this.notification.disconnect(this._updatedId);
this._updatedId = 0;
@ -817,21 +766,22 @@ var NotificationMessage = new Lang.Class({
this.notification.disconnect(this._destroyId);
this._destroyId = 0;
}
});
var EventsSection = new Lang.Class({
Name: 'EventsSection',
Extends: MessageList.MessageListSection,
canClose() {
return true;
}
};
var EventsSection = class EventsSection extends MessageList.MessageListSection {
constructor() {
super();
_init() {
this._desktopSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.interface' });
this._desktopSettings.connect('changed', this._reloadEvents.bind(this));
this._eventSource = new EmptyEventSource();
this._messageById = new Map();
this.parent();
this._title = new St.Button({ style_class: 'events-section-title',
label: '',
x_align: St.Align.START,
@ -844,20 +794,16 @@ var EventsSection = new Lang.Class({
Shell.AppSystem.get_default().connect('installed-changed',
this._appInstalledChanged.bind(this));
this._appInstalledChanged();
},
_ignoreEvent(event) {
this._eventSource.ignoreEvent(event);
},
}
setEventSource(eventSource) {
this._eventSource = eventSource;
this._eventSource.connect('changed', this._reloadEvents.bind(this));
},
}
get allowed() {
return Main.sessionMode.showCalendarEvents;
},
}
_updateTitle() {
this._title.visible = !isToday(this._date);
@ -876,7 +822,7 @@ var EventsSection = new Lang.Class({
dayFormat = Shell.util_translate_time_string(NC_("calendar heading",
"%A, %B %-d, %Y"));
this._title.label = this._date.toLocaleFormat(dayFormat);
},
}
_reloadEvents() {
if (this._eventSource.isLoading)
@ -902,9 +848,6 @@ var EventsSection = new Lang.Class({
let message = this._messageById.get(event.id);
if (!message) {
message = new EventMessage(event, this._date);
message.connect('close', () => {
this._ignoreEvent(event);
});
this._messageById.set(event.id, message);
this.addMessage(message, false);
} else {
@ -914,12 +857,12 @@ var EventsSection = new Lang.Class({
this._reloading = false;
this._sync();
},
}
_appInstalledChanged() {
this._calendarApp = undefined;
this._title.reactive = (this._getCalendarApp() != null);
},
}
_getCalendarApp() {
if (this._calendarApp !== undefined)
@ -934,7 +877,7 @@ var EventsSection = new Lang.Class({
this._calendarApp = null;
}
return this._calendarApp;
},
}
_onTitleClicked() {
Main.overview.hide();
@ -944,32 +887,30 @@ var EventsSection = new Lang.Class({
if (app.get_id() == 'evolution.desktop')
app = Gio.DesktopAppInfo.new('evolution-calendar.desktop');
app.launch([], global.create_app_launch_context(0, -1));
},
}
setDate(date) {
this.parent(date);
super.setDate(date);
this._updateTitle();
this._reloadEvents();
},
}
_shouldShow() {
return !this.empty || !isToday(this._date);
},
}
_sync() {
if (this._reloading)
return;
this.parent();
super._sync();
}
});
};
var NotificationSection = new Lang.Class({
Name: 'NotificationSection',
Extends: MessageList.MessageListSection,
_init() {
this.parent();
var NotificationSection =
class NotificationSection extends MessageList.MessageListSection {
constructor() {
super();
this._sources = new Map();
this._nUrgent = 0;
@ -980,12 +921,12 @@ var NotificationSection = new Lang.Class({
});
this.actor.connect('notify::mapped', this._onMapped.bind(this));
},
}
get allowed() {
return Main.sessionMode.hasNotifications &&
!Main.sessionMode.isGreeter;
},
}
_createTimeLabel(datetime) {
let label = new St.Label({ style_class: 'event-time',
@ -996,7 +937,7 @@ var NotificationSection = new Lang.Class({
label.text = Util.formatTimeSpan(datetime);
});
return label;
},
}
_sourceAdded(tray, source) {
let obj = {
@ -1011,7 +952,7 @@ var NotificationSection = new Lang.Class({
this._onNotificationAdded.bind(this));
this._sources.set(source, obj);
},
}
_onNotificationAdded(source, notification) {
let message = new NotificationMessage(notification);
@ -1042,14 +983,14 @@ var NotificationSection = new Lang.Class({
let index = isUrgent ? 0 : this._nUrgent;
this.addMessageAtIndex(message, index, this.actor.mapped);
},
}
_onSourceDestroy(source, obj) {
source.disconnect(obj.destroyId);
source.disconnect(obj.notificationAddedId);
this._sources.delete(source);
},
}
_onMapped() {
if (!this.actor.mapped)
@ -1058,17 +999,15 @@ var NotificationSection = new Lang.Class({
for (let message of this._messages.keys())
if (message.notification.urgency != MessageTray.Urgency.CRITICAL)
message.notification.acknowledged = true;
},
}
_shouldShow() {
return !this.empty && isToday(this._date);
}
});
};
var Placeholder = new Lang.Class({
Name: 'Placeholder',
_init() {
var Placeholder = class Placeholder {
constructor() {
this.actor = new St.BoxLayout({ style_class: 'message-list-placeholder',
vertical: true });
@ -1086,14 +1025,14 @@ var Placeholder = new Lang.Class({
this.actor.add_actor(this._label);
this._sync();
},
}
setDate(date) {
if (sameDay(this._date, date))
return;
this._date = date;
this._sync();
},
}
_sync() {
let today = isToday(this._date);
@ -1110,12 +1049,10 @@ var Placeholder = new Lang.Class({
this._label.text = _("No Events");
}
}
});
};
var CalendarMessageList = new Lang.Class({
Name: 'CalendarMessageList',
_init() {
var CalendarMessageList = class CalendarMessageList {
constructor() {
this.actor = new St.Widget({ style_class: 'message-list',
layout_manager: new Clutter.BinLayout(),
x_expand: true, y_expand: true });
@ -1131,11 +1068,11 @@ var CalendarMessageList = new Lang.Class({
overlay_scrollbars: true,
x_expand: true, y_expand: true,
x_fill: true, y_fill: true });
this._scrollView.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
this._scrollView.set_policy(St.PolicyType.NEVER, St.PolicyType.AUTOMATIC);
box.add_actor(this._scrollView);
this._clearButton = new St.Button({ style_class: 'message-list-clear-button button',
label: _("Clear All"),
label: _("Clear"),
can_focus: true });
this._clearButton.set_x_align(Clutter.ActorAlign.END);
this._clearButton.connect('clicked', () => {
@ -1161,7 +1098,7 @@ var CalendarMessageList = new Lang.Class({
this._addSection(this._eventsSection);
Main.sessionMode.connect('updated', this._sync.bind(this));
},
}
_addSection(section) {
let obj = {
@ -1186,7 +1123,7 @@ var CalendarMessageList = new Lang.Class({
this._sections.set(section, obj);
this._sectionList.add_actor(section.actor);
this._sync();
},
}
_removeSection(section) {
let obj = this._sections.get(section);
@ -1199,11 +1136,11 @@ var CalendarMessageList = new Lang.Class({
this._sections.delete(section);
this._sectionList.remove_actor(section.actor);
this._sync();
},
}
_onKeyFocusIn(section, actor) {
Util.ensureActorVisibleInScrollView(this._scrollView, actor);
},
}
_sync() {
let sections = [...this._sections.keys()];
@ -1218,15 +1155,15 @@ var CalendarMessageList = new Lang.Class({
let canClear = sections.some(s => s.canClear && s.actor.visible);
this._clearButton.reactive = canClear;
},
}
setEventSource(eventSource) {
this._eventsSection.setEventSource(eventSource);
},
}
setDate(date) {
for (let section of this._sections.keys())
section.setDate(date);
this._placeholder.setDate(date);
}
});
};

View File

@ -1,13 +1,7 @@
const Clutter = imports.gi.Clutter;
const Pango = imports.gi.Pango;
const St = imports.gi.St;
const { Clutter, Pango, St } = imports.gi;
const Lang = imports.lang;
var CheckBox = new Lang.Class({
Name: 'CheckBox',
_init(label) {
var CheckBox = class CheckBox {
constructor(label) {
let container = new St.BoxLayout();
this.actor = new St.Button({ style_class: 'check-box',
child: container,
@ -28,13 +22,13 @@ var CheckBox = new Lang.Class({
if (label)
this.setLabel(label);
},
}
setLabel(label) {
this._label.set_text(label);
},
}
getLabelActor() {
return this._label;
}
});
};

View File

@ -1,12 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Lang = imports.lang;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const { Clutter, Gio, GLib, GObject, Meta, Shell } = imports.gi;
const Dialog = imports.ui.dialog;
const Main = imports.ui.main;
@ -16,31 +10,29 @@ var FROZEN_WINDOW_BRIGHTNESS = -0.3
var DIALOG_TRANSITION_TIME = 0.15
var ALIVE_TIMEOUT = 5000;
var CloseDialog = new Lang.Class({
Name: 'CloseDialog',
Extends: GObject.Object,
var CloseDialog = GObject.registerClass({
Implements: [ Meta.CloseDialog ],
Properties: {
'window': GObject.ParamSpec.override('window', Meta.CloseDialog)
},
}, class CloseDialog extends GObject.Object {
_init(window) {
this.parent();
super._init();
this._window = window;
this._dialog = null;
this._tracked = undefined;
this._timeoutId = 0;
this._windowFocusChangedId = 0;
this._keyFocusChangedId = 0;
},
}
get window() {
return this._window;
},
}
set window(window) {
this._window = window;
},
}
_createDialogContent() {
let tracker = Shell.WindowTracker.get_default();
@ -52,7 +44,7 @@ var CloseDialog = new Lang.Class({
"continue or force the application to quit entirely.");
let icon = new Gio.ThemedIcon({ name: 'dialog-warning-symbolic' });
return new Dialog.MessageDialogContent({ icon, title, subtitle });
},
}
_initDialog() {
if (this._dialog)
@ -72,7 +64,7 @@ var CloseDialog = new Lang.Class({
key: Clutter.Escape });
global.focus_manager.add_group(this._dialog);
},
}
_addWindowEffect() {
// We set the effect on the surface actor, so the dialog itself
@ -83,21 +75,21 @@ var CloseDialog = new Lang.Class({
let effect = new Clutter.BrightnessContrastEffect();
effect.set_brightness(FROZEN_WINDOW_BRIGHTNESS);
surfaceActor.add_effect_with_name("gnome-shell-frozen-window", effect);
},
}
_removeWindowEffect() {
let windowActor = this._window.get_compositor_private();
let surfaceActor = windowActor.get_first_child();
surfaceActor.remove_effect_by_name("gnome-shell-frozen-window");
},
}
_onWait() {
this.response(Meta.CloseDialogResponse.WAIT);
},
}
_onClose() {
this.response(Meta.CloseDialogResponse.FORCE_CLOSE);
},
}
_onFocusChanged() {
if (Meta.is_wayland_compositor())
@ -128,7 +120,7 @@ var CloseDialog = new Lang.Class({
});
this._tracked = shouldTrack;
},
}
vfunc_show() {
if (this._dialog != null)
@ -162,7 +154,7 @@ var CloseDialog = new Lang.Class({
time: DIALOG_TRANSITION_TIME,
onComplete: this._onFocusChanged.bind(this)
});
},
}
vfunc_hide() {
if (this._dialog == null)
@ -191,7 +183,7 @@ var CloseDialog = new Lang.Class({
dialog.destroy();
}
});
},
}
vfunc_focus() {
if (this._dialog)

View File

@ -1,17 +1,13 @@
const Lang = imports.lang;
const Main = imports.ui.main;
var ComponentManager = new Lang.Class({
Name: 'ComponentManager',
_init() {
var ComponentManager = class {
constructor() {
this._allComponents = {};
this._enabledComponents = [];
Main.sessionMode.connect('updated', this._sessionUpdated.bind(this));
this._sessionUpdated();
},
}
_sessionUpdated() {
let newEnabledComponents = Main.sessionMode.components;
@ -29,12 +25,12 @@ var ComponentManager = new Lang.Class({
});
this._enabledComponents = newEnabledComponents;
},
}
_importComponent(name) {
let module = imports.ui.components[name];
return module.Component;
},
}
_ensureComponent(name) {
let component = this._allComponents[name];
@ -48,13 +44,13 @@ var ComponentManager = new Lang.Class({
component = new constructor();
this._allComponents[name] = component;
return component;
},
}
_enableComponent(name) {
let component = this._ensureComponent(name);
if (component)
component.enable();
},
}
_disableComponent(name) {
let component = this._allComponents[name];
@ -62,4 +58,4 @@ var ComponentManager = new Lang.Class({
return;
component.disable();
}
});
};

View File

@ -1,14 +1,10 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Lang = imports.lang;
const { Gio, GLib } = imports.gi;
const Mainloop = imports.mainloop;
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const Params = imports.misc.params;
const Shell = imports.gi.Shell;
const GnomeSession = imports.misc.gnomeSession;
const Main = imports.ui.main;
const ShellMountOperation = imports.ui.shellMountOperation;
var GNOME_SESSION_AUTOMOUNT_INHIBIT = 16;
@ -19,10 +15,8 @@ const SETTING_ENABLE_AUTOMOUNT = 'automount';
var AUTORUN_EXPIRE_TIMEOUT_SECS = 10;
var AutomountManager = new Lang.Class({
Name: 'AutomountManager',
_init() {
var AutomountManager = class {
constructor() {
this._settings = new Gio.Settings({ schema_id: SETTINGS_SCHEMA });
this._volumeQueue = [];
this._activeOperations = new Map();
@ -34,7 +28,7 @@ var AutomountManager = new Lang.Class({
this._inhibited = false;
this._volumeMonitor = Gio.VolumeMonitor.get();
},
}
enable() {
this._volumeAddedId = this._volumeMonitor.connect('volume-added', this._onVolumeAdded.bind(this));
@ -45,7 +39,7 @@ var AutomountManager = new Lang.Class({
this._mountAllId = Mainloop.idle_add(this._startupMountAll.bind(this));
GLib.Source.set_name_by_id(this._mountAllId, '[gnome-shell] this._startupMountAll');
},
}
disable() {
this._volumeMonitor.disconnect(this._volumeAddedId);
@ -58,7 +52,7 @@ var AutomountManager = new Lang.Class({
Mainloop.source_remove(this._mountAllId);
this._mountAllId = 0;
}
},
}
_InhibitorsChanged(object, senderName, [inhibtor]) {
this._session.IsInhibitedRemote(GNOME_SESSION_AUTOMOUNT_INHIBIT,
@ -67,7 +61,7 @@ var AutomountManager = new Lang.Class({
this._inhibited = result[0];
}
});
},
}
_startupMountAll() {
let volumes = this._volumeMonitor.get_volumes();
@ -79,7 +73,7 @@ var AutomountManager = new Lang.Class({
this._mountAllId = 0;
return GLib.SOURCE_REMOVE;
},
}
_onDriveConnected() {
// if we're not in the current ConsoleKit session,
@ -91,7 +85,7 @@ var AutomountManager = new Lang.Class({
player.play_from_theme('device-added-media',
_("External drive connected"),
null);
},
}
_onDriveDisconnected() {
// if we're not in the current ConsoleKit session,
@ -99,11 +93,11 @@ var AutomountManager = new Lang.Class({
if (!this._session.SessionIsActive)
return;
let sound = global.display.get_sound();
sound.play_from_theme('device-removed-media',
_("External drive disconnected"),
null);
},
let player = global.display.get_sound_player();
player.play_from_theme('device-removed-media',
_("External drive disconnected"),
null);
}
_onDriveEjectButton(monitor, drive) {
// TODO: this code path is not tested, as the GVfs volume monitor
@ -134,11 +128,11 @@ var AutomountManager = new Lang.Class({
}
});
}
},
}
_onVolumeAdded(monitor, volume) {
this._checkAndMountVolume(volume);
},
}
_checkAndMountVolume(volume, params) {
params = Params.parse(params, { checkSession: true,
@ -178,7 +172,7 @@ var AutomountManager = new Lang.Class({
} else {
this._mountVolume(volume, null, params.allowAutorun);
}
},
}
_mountVolume(volume, operation, allowAutorun) {
if (allowAutorun)
@ -189,7 +183,7 @@ var AutomountManager = new Lang.Class({
volume.mount(0, mountOp, null,
this._onVolumeMounted.bind(this));
},
}
_onVolumeMounted(volume, res) {
this._allowAutorunExpire(volume);
@ -214,7 +208,7 @@ var AutomountManager = new Lang.Class({
this._closeOperation(volume);
}
}
},
}
_onVolumeRemoved(monitor, volume) {
if (volume._allowAutorunExpireId && volume._allowAutorunExpireId > 0) {
@ -223,7 +217,7 @@ var AutomountManager = new Lang.Class({
}
this._volumeQueue =
this._volumeQueue.filter(element => (element != volume));
},
}
_reaskPassword(volume) {
let prevOperation = this._activeOperations.get(volume);
@ -232,7 +226,7 @@ var AutomountManager = new Lang.Class({
new ShellMountOperation.ShellMountOperation(volume,
{ existingDialog: existingDialog });
this._mountVolume(volume, operation);
},
}
_closeOperation(volume) {
let operation = this._activeOperations.get(volume);
@ -240,11 +234,11 @@ var AutomountManager = new Lang.Class({
return;
operation.close();
this._activeOperations.delete(volume);
},
}
_allowAutorun(volume) {
volume.allowAutorun = true;
},
}
_allowAutorunExpire(volume) {
let id = Mainloop.timeout_add_seconds(AUTORUN_EXPIRE_TIMEOUT_SECS, () => {
@ -255,5 +249,5 @@ var AutomountManager = new Lang.Class({
volume._allowAutorunExpireId = id;
GLib.Source.set_name_by_id(id, '[gnome-shell] volume.allowAutorun');
}
});
};
var Component = AutomountManager;

View File

@ -1,8 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Lang = imports.lang;
const Gio = imports.gi.Gio;
const St = imports.gi.St;
const { Gio, St } = imports.gi;
const GnomeSession = imports.misc.gnomeSession;
const Main = imports.ui.main;
@ -84,13 +82,11 @@ function HotplugSniffer() {
'/org/gnome/Shell/HotplugSniffer');
}
var ContentTypeDiscoverer = new Lang.Class({
Name: 'ContentTypeDiscoverer',
_init(callback) {
var ContentTypeDiscoverer = class {
constructor(callback) {
this._callback = callback;
this._settings = new Gio.Settings({ schema_id: SETTINGS_SCHEMA });
},
}
guessContentTypes(mount) {
let autorunEnabled = !this._settings.get_boolean(SETTING_DISABLE_AUTORUN);
@ -103,7 +99,7 @@ var ContentTypeDiscoverer = new Lang.Class({
} else {
this._emitCallback(mount, []);
}
},
}
_onContentTypeGuessed(mount, res) {
let contentTypes = [];
@ -126,7 +122,7 @@ var ContentTypeDiscoverer = new Lang.Class({
this._emitCallback(mount, contentTypes);
});
}
},
}
_emitCallback(mount, contentTypes) {
if (!contentTypes)
@ -150,27 +146,25 @@ var ContentTypeDiscoverer = new Lang.Class({
this._callback(mount, apps, contentTypes);
}
});
};
var AutorunManager = new Lang.Class({
Name: 'AutorunManager',
_init() {
var AutorunManager = class {
constructor() {
this._session = new GnomeSession.SessionManager();
this._volumeMonitor = Gio.VolumeMonitor.get();
this._dispatcher = new AutorunDispatcher(this);
},
}
enable() {
this._mountAddedId = this._volumeMonitor.connect('mount-added', this._onMountAdded.bind(this));
this._mountRemovedId = this._volumeMonitor.connect('mount-removed', this._onMountRemoved.bind(this));
},
}
disable() {
this._volumeMonitor.disconnect(this._mountAddedId);
this._volumeMonitor.disconnect(this._mountRemovedId);
},
}
_onMountAdded(monitor, mount) {
// don't do anything if our session is not the currently
@ -182,21 +176,19 @@ var AutorunManager = new Lang.Class({
this._dispatcher.addMount(mount, apps, contentTypes);
});
discoverer.guessContentTypes(mount);
},
}
_onMountRemoved(monitor, mount) {
this._dispatcher.removeMount(mount);
}
});
};
var AutorunDispatcher = new Lang.Class({
Name: 'AutorunDispatcher',
_init(manager) {
var AutorunDispatcher = class {
constructor(manager) {
this._manager = manager;
this._sources = [];
this._settings = new Gio.Settings({ schema_id: SETTINGS_SCHEMA });
},
}
_getAutorunSettingForType(contentType) {
let runApp = this._settings.get_strv(SETTING_START_APP);
@ -212,7 +204,7 @@ var AutorunDispatcher = new Lang.Class({
return AutorunSetting.FILES;
return AutorunSetting.ASK;
},
}
_getSourceForMount(mount) {
let filtered = this._sources.filter(source => (source.mount == mount));
@ -224,7 +216,7 @@ var AutorunDispatcher = new Lang.Class({
return filtered[0];
return null;
},
}
_addSource(mount, apps) {
// if we already have a source showing for this
@ -234,7 +226,7 @@ var AutorunDispatcher = new Lang.Class({
// add a new source
this._sources.push(new AutorunSource(this._manager, mount, apps));
},
}
addMount(mount, apps, contentTypes) {
// if autorun is disabled globally, return
@ -272,7 +264,7 @@ var AutorunDispatcher = new Lang.Class({
// but we failed launching the default app or the default file manager
if (!success)
this._addSource(mount, apps);
},
}
removeMount(mount) {
let source = this._getSourceForMount(mount);
@ -284,45 +276,39 @@ var AutorunDispatcher = new Lang.Class({
// destroy the notification source
source.destroy();
}
});
};
var AutorunSource = new Lang.Class({
Name: 'AutorunSource',
Extends: MessageTray.Source,
var AutorunSource = class extends MessageTray.Source {
constructor(manager, mount, apps) {
super(mount.get_name());
_init(manager, mount, apps) {
this._manager = manager;
this.mount = mount;
this.apps = apps;
this.parent(mount.get_name());
this._notification = new AutorunNotification(this._manager, this);
// add ourselves as a source, and popup the notification
Main.messageTray.add(this);
this.notify(this._notification);
},
}
getIcon() {
return this.mount.get_icon();
},
}
_createPolicy() {
return new MessageTray.NotificationApplicationPolicy('org.gnome.Nautilus');
}
});
};
var AutorunNotification = new Lang.Class({
Name: 'AutorunNotification',
Extends: MessageTray.Notification,
_init(manager, source) {
this.parent(source, source.title);
var AutorunNotification = class extends MessageTray.Notification {
constructor(manager, source) {
super(source, source.title);
this._manager = manager;
this._mount = source.mount;
},
}
createBanner() {
let banner = new MessageTray.NotificationBanner(this);
@ -335,7 +321,7 @@ var AutorunNotification = new Lang.Class({
});
return banner;
},
}
_buttonForApp(app) {
let box = new St.BoxLayout();
@ -362,14 +348,14 @@ var AutorunNotification = new Lang.Class({
});
return button;
},
}
activate() {
this.parent();
super.activate();
let app = Gio.app_info_get_default_for_type('inode/directory', false);
startAppForMount(app, this._mount);
}
});
};
var Component = AutorunManager;

View File

@ -1,31 +1,18 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Lang = imports.lang;
const Shell = imports.gi.Shell;
const Clutter = imports.gi.Clutter;
const St = imports.gi.St;
const Pango = imports.gi.Pango;
const Gio = imports.gi.Gio;
const GObject = imports.gi.GObject;
const Gcr = imports.gi.Gcr;
const { Clutter, Gcr, Gio, GObject, Pango, Shell, St } = imports.gi;
const Animation = imports.ui.animation;
const Dialog = imports.ui.dialog;
const ModalDialog = imports.ui.modalDialog;
const ShellEntry = imports.ui.shellEntry;
const CheckBox = imports.ui.checkBox;
const Tweener = imports.ui.tweener;
var WORK_SPINNER_ICON_SIZE = 16;
var WORK_SPINNER_ANIMATION_DELAY = 1.0;
var WORK_SPINNER_ANIMATION_TIME = 0.3;
var KeyringDialog = new Lang.Class({
Name: 'KeyringDialog',
Extends: ModalDialog.ModalDialog,
_init() {
this.parent({ styleClass: 'prompt-dialog' });
var KeyringDialog = class extends ModalDialog.ModalDialog {
constructor() {
super({ styleClass: 'prompt-dialog' });
this.prompt = new Shell.KeyringPrompt();
this.prompt.connect('show-password', this._onShowPassword.bind(this));
@ -63,34 +50,17 @@ var KeyringDialog = new Lang.Class({
this.prompt.bind_property('cancel-label', this._cancelButton, 'label', GObject.BindingFlags.SYNC_CREATE);
this.prompt.bind_property('continue-label', this._continueButton, 'label', GObject.BindingFlags.SYNC_CREATE);
},
}
_setWorking(working) {
if (!this._workSpinner)
return;
Tweener.removeTweens(this._workSpinner.actor);
if (working) {
if (working)
this._workSpinner.play();
Tweener.addTween(this._workSpinner.actor,
{ opacity: 255,
delay: WORK_SPINNER_ANIMATION_DELAY,
time: WORK_SPINNER_ANIMATION_TIME,
transition: 'linear'
});
} else {
Tweener.addTween(this._workSpinner.actor,
{ opacity: 0,
time: WORK_SPINNER_ANIMATION_TIME,
transition: 'linear',
onCompleteScope: this,
onComplete() {
if (this._workSpinner)
this._workSpinner.stop();
}
});
}
},
else
this._workSpinner.stop();
}
_buildControlTable() {
let layout = new Clutter.GridLayout({ orientation: Clutter.Orientation.VERTICAL });
@ -114,9 +84,7 @@ var KeyringDialog = new Lang.Class({
ShellEntry.addContextMenu(this._passwordEntry, { isPassword: true });
this._passwordEntry.clutter_text.connect('activate', this._onPasswordActivate.bind(this));
let spinnerIcon = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/process-working.svg');
this._workSpinner = new Animation.AnimatedIcon(spinnerIcon, WORK_SPINNER_ICON_SIZE);
this._workSpinner.actor.opacity = 0;
this._workSpinner = new Animation.Spinner(WORK_SPINNER_ICON_SIZE, true);
if (rtl) {
layout.attach(this._workSpinner.actor, 0, row, 1, 1);
@ -183,7 +151,7 @@ var KeyringDialog = new Lang.Class({
this._controlTable = table;
this._content.messageBox.add(table, { x_fill: true, y_fill: true });
},
}
_updateSensitivity(sensitive) {
if (this._passwordEntry) {
@ -199,7 +167,7 @@ var KeyringDialog = new Lang.Class({
this._continueButton.can_focus = sensitive;
this._continueButton.reactive = sensitive;
this._setWorking(!sensitive);
},
}
_ensureOpen() {
// NOTE: ModalDialog.open() is safe to call if the dialog is
@ -217,65 +185,61 @@ var KeyringDialog = new Lang.Class({
' Dismissing prompt request');
this.prompt.cancel()
return false;
},
}
_onShowPassword(prompt) {
this._buildControlTable();
this._ensureOpen();
this._updateSensitivity(true);
this._passwordEntry.grab_key_focus();
},
}
_onShowConfirm(prompt) {
this._buildControlTable();
this._ensureOpen();
this._updateSensitivity(true);
this._continueButton.grab_key_focus();
},
}
_onHidePrompt(prompt) {
this.close();
},
}
_onPasswordActivate() {
if (this.prompt.confirm_visible)
this._confirmEntry.grab_key_focus();
else
this._onContinueButton();
},
}
_onConfirmActivate() {
this._onContinueButton();
},
}
_onContinueButton() {
this._updateSensitivity(false);
this.prompt.complete();
},
}
_onCancelButton() {
this.prompt.cancel();
},
});
}
};
var KeyringDummyDialog = new Lang.Class({
Name: 'KeyringDummyDialog',
_init() {
var KeyringDummyDialog = class {
constructor() {
this.prompt = new Shell.KeyringPrompt();
this.prompt.connect('show-password', this._cancelPrompt.bind(this));
this.prompt.connect('show-confirm', this._cancelPrompt.bind(this));
},
}
_cancelPrompt() {
this.prompt.cancel();
}
});
};
var KeyringPrompter = new Lang.Class({
Name: 'KeyringPrompter',
_init() {
var KeyringPrompter = class {
constructor() {
this._prompter = new Gcr.SystemPrompter();
this._prompter.connect('new-prompt', () => {
let dialog = this._enabled ? new KeyringDialog()
@ -287,7 +251,7 @@ var KeyringPrompter = new Lang.Class({
this._registered = false;
this._enabled = false;
this._currentPrompt = null;
},
}
enable() {
if (!this._registered) {
@ -297,7 +261,7 @@ var KeyringPrompter = new Lang.Class({
this._registered = true;
}
this._enabled = true;
},
}
disable() {
this._enabled = false;
@ -306,6 +270,6 @@ var KeyringPrompter = new Lang.Class({
this._currentPrompt.cancel();
this._currentPrompt = null;
}
});
};
var Component = KeyringPrompter;

View File

@ -1,32 +1,20 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
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 NM = imports.gi.NM;
const Pango = imports.gi.Pango;
const Shell = imports.gi.Shell;
const { Clutter, Gio, GLib, NM, Pango, Shell, St } = imports.gi;
const Signals = imports.signals;
const St = imports.gi.St;
const Config = imports.misc.config;
const Dialog = imports.ui.dialog;
const Main = imports.ui.main;
const MessageTray = imports.ui.messageTray;
const ModalDialog = imports.ui.modalDialog;
const PopupMenu = imports.ui.popupMenu;
const ShellEntry = imports.ui.shellEntry;
const VPN_UI_GROUP = 'VPN Plugin UI';
var NetworkSecretDialog = new Lang.Class({
Name: 'NetworkSecretDialog',
Extends: ModalDialog.ModalDialog,
_init(agent, requestId, connection, settingName, hints, contentOverride) {
this.parent({ styleClass: 'prompt-dialog' });
var NetworkSecretDialog = class extends ModalDialog.ModalDialog {
constructor(agent, requestId, connection, settingName, hints, flags, contentOverride) {
super({ styleClass: 'prompt-dialog' });
this._agent = agent;
this._requestId = requestId;
@ -109,6 +97,18 @@ var NetworkSecretDialog = new Lang.Class({
contentBox.messageBox.add(secretTable);
if (flags & NM.SecretAgentGetSecretsFlags.WPS_PBC_ACTIVE) {
let descriptionLabel = new St.Label({ style_class: 'prompt-dialog-description',
text: _("Alternatively you can connect by pushing the “WPS” button on your router.") });
descriptionLabel.clutter_text.line_wrap = true;
descriptionLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
contentBox.messageBox.add(descriptionLabel,
{ y_fill: true,
y_align: St.Align.START,
expand: true });
}
this._okButton = { label: _("Connect"),
action: this._onOk.bind(this),
default: true
@ -121,7 +121,7 @@ var NetworkSecretDialog = new Lang.Class({
this._okButton]);
this._updateOkButton();
},
}
_updateOkButton() {
let valid = true;
@ -132,7 +132,7 @@ var NetworkSecretDialog = new Lang.Class({
this._okButton.button.reactive = valid;
this._okButton.button.can_focus = valid;
},
}
_onOk() {
let valid = true;
@ -148,12 +148,12 @@ var NetworkSecretDialog = new Lang.Class({
this.close(global.get_current_time());
}
// do nothing if not valid
},
}
cancel() {
this._agent.respond(this._requestId, Shell.NetworkAgentResponse.USER_CANCELED);
this.close(global.get_current_time());
},
}
_validateWpaPsk(secret) {
let value = secret.value;
@ -169,7 +169,7 @@ var NetworkSecretDialog = new Lang.Class({
}
return (value.length >= 8 && value.length <= 63);
},
}
_validateStaticWep(secret) {
let value = secret.value;
@ -194,7 +194,7 @@ var NetworkSecretDialog = new Lang.Class({
return false;
}
return true;
},
}
_getWirelessSecrets(secrets, wirelessSetting) {
let wirelessSecuritySetting = this._connection.get_setting_wireless_security();
@ -231,7 +231,7 @@ var NetworkSecretDialog = new Lang.Class({
default:
log('Invalid wireless key management: ' + wirelessSecuritySetting.key_mgmt);
}
},
}
_get8021xSecrets(secrets) {
let ieee8021xSetting = this._connection.get_setting_802_1x();
@ -274,7 +274,7 @@ var NetworkSecretDialog = new Lang.Class({
default:
log('Invalid EAP/IEEE802.1x method: ' + ieee8021xSetting.get_eap_method(0));
}
},
}
_getPPPoESecrets(secrets) {
let pppoeSetting = this._connection.get_setting_pppoe();
@ -284,7 +284,7 @@ var NetworkSecretDialog = new Lang.Class({
value: pppoeSetting.service || '', password: false });
secrets.push({ label: _("Password: "), key: 'password',
value: pppoeSetting.password || '', password: true });
},
}
_getMobileSecrets(secrets, connectionType) {
let setting;
@ -294,7 +294,7 @@ var NetworkSecretDialog = new Lang.Class({
setting = this._connection.get_setting_by_name(connectionType);
secrets.push({ label: _("Password: "), key: 'password',
value: setting.value || '', password: true });
},
}
_getContent() {
let connectionSetting = this._connection.get_setting_connection();
@ -347,15 +347,14 @@ var NetworkSecretDialog = new Lang.Class({
return content;
}
});
};
var VPNRequestHandler = new Lang.Class({
Name: 'VPNRequestHandler',
_init(agent, requestId, authHelper, serviceType, connection, hints, flags) {
var VPNRequestHandler = class {
constructor(agent, requestId, authHelper, serviceType, connection, hints, flags) {
this._agent = agent;
this._requestId = requestId;
this._connection = connection;
this._flags = flags;
this._pluginOutBuffer = [];
this._title = null;
this._description = null;
@ -412,7 +411,7 @@ var VPNRequestHandler = new Lang.Class({
this._agent.respond(requestId, Shell.NetworkAgentResponse.INTERNAL_ERROR);
}
},
}
cancel(respond) {
if (respond)
@ -428,7 +427,7 @@ var VPNRequestHandler = new Lang.Class({
}
this.destroy();
},
}
destroy() {
if (this._destroyed)
@ -442,7 +441,7 @@ var VPNRequestHandler = new Lang.Class({
// Stdout is closed when we finish reading from it
this._destroyed = true;
},
}
_vpnChildFinished(pid, status, requestObj) {
this._childWatch = 0;
@ -463,7 +462,7 @@ var VPNRequestHandler = new Lang.Class({
this._agent.respond(this._requestId, Shell.NetworkAgentResponse.INTERNAL_ERROR);
this.destroy();
},
}
_vpnChildProcessLineOldStyle(line) {
if (this._previousLine != undefined) {
@ -481,7 +480,7 @@ var VPNRequestHandler = new Lang.Class({
} else {
this._previousLine = line;
}
},
}
_readStdoutOldStyle() {
this._dataStdout.read_line_async(GLib.PRIORITY_DEFAULT, null, (stream, result) => {
@ -498,7 +497,7 @@ var VPNRequestHandler = new Lang.Class({
// try to read more!
this._readStdoutOldStyle();
});
},
}
_readStdoutNewStyle() {
this._dataStdout.fill_async(-1, GLib.PRIORITY_DEFAULT, null, (stream, result) => {
@ -516,7 +515,7 @@ var VPNRequestHandler = new Lang.Class({
this._dataStdout.set_buffer_size(2 * this._dataStdout.get_buffer_size());
this._readStdoutNewStyle();
});
},
}
_showNewStyleDialog() {
let keyfile = new GLib.KeyFile();
@ -574,13 +573,13 @@ var VPNRequestHandler = new Lang.Class({
if (contentOverride && contentOverride.secrets.length) {
// Only show the dialog if we actually have something to ask
this._shellDialog = new NetworkSecretDialog(this._agent, this._requestId, this._connection, 'vpn', [], contentOverride);
this._shellDialog = new NetworkSecretDialog(this._agent, this._requestId, this._connection, 'vpn', [], this._flags, contentOverride);
this._shellDialog.open(global.get_current_time());
} else {
this._agent.respond(this._requestId, Shell.NetworkAgentResponse.CONFIRMED);
this.destroy();
}
},
}
_writeConnection() {
let vpnSetting = this._connection.get_setting_vpn();
@ -601,14 +600,12 @@ var VPNRequestHandler = new Lang.Class({
this._agent.respond(this._requestId, Shell.NetworkAgentResponse.INTERNAL_ERROR);
this.destroy();
}
},
});
}
};
Signals.addSignalMethods(VPNRequestHandler.prototype);
var NetworkAgent = new Lang.Class({
Name: 'NetworkAgent',
_init() {
var NetworkAgent = class {
constructor() {
this._native = new Shell.NetworkAgent({ identifier: 'org.gnome.Shell.NetworkAgent',
capabilities: NM.SecretAgentCapabilities.VPN_HINTS,
auto_register: false
@ -639,7 +636,7 @@ var NetworkAgent = new Lang.Class({
logError(e, 'error initializing the NetworkManager Agent');
}
});
},
}
enable() {
if (!this._native)
@ -648,7 +645,7 @@ var NetworkAgent = new Lang.Class({
this._native.auto_register = true;
if (this._initialized && !this._native.registered)
this._native.register_async(null, null);
},
}
disable() {
let requestId;
@ -671,7 +668,7 @@ var NetworkAgent = new Lang.Class({
this._native.auto_register = false;
if (this._initialized && this._native.registered)
this._native.unregister_async(null, null);
},
}
_showNotification(requestId, connection, settingName, hints, flags) {
let source = new MessageTray.Source(_("Network Manager"), 'network-transmit-receive');
@ -700,14 +697,14 @@ var NetworkAgent = new Lang.Class({
if (hints.indexOf('pin') != -1) {
let gsmSetting = connection.get_setting_gsm();
title = _("PIN code required");
message = _("PIN code is needed for the mobile broadband device");
body = _("PIN code is needed for the mobile broadband device");
break;
}
// fall through
case 'cdma':
case 'bluetooth':
title = _("Mobile broadband network password");
message = _("A password is required to connect to “%s”.").format(connectionSetting.get_id());
body = _("A password is required to connect to “%s”.").format(connectionSetting.get_id());
break;
default:
log('Invalid connection type: ' + connectionType);
@ -731,14 +728,14 @@ var NetworkAgent = new Lang.Class({
Main.messageTray.add(source);
source.notify(notification);
},
}
_newRequest(agent, requestId, connection, settingName, hints, flags) {
if (!(flags & NM.SecretAgentGetSecretsFlags.USER_REQUESTED))
this._showNotification(requestId, connection, settingName, hints, flags);
else
this._handleRequest(requestId, connection, settingName, hints, flags);
},
}
_handleRequest(requestId, connection, settingName, hints, flags) {
if (settingName == 'vpn') {
@ -746,13 +743,13 @@ var NetworkAgent = new Lang.Class({
return;
}
let dialog = new NetworkSecretDialog(this._native, requestId, connection, settingName, hints);
let dialog = new NetworkSecretDialog(this._native, requestId, connection, settingName, hints, flags);
dialog.connect('destroy', () => {
delete this._dialogs[requestId];
});
this._dialogs[requestId] = dialog;
dialog.open(global.get_current_time());
},
}
_cancelRequest(agent, requestId) {
if (this._dialogs[requestId]) {
@ -763,7 +760,7 @@ var NetworkAgent = new Lang.Class({
this._vpnRequests[requestId].cancel(false);
delete this._vpnRequests[requestId];
}
},
}
_vpnRequest(requestId, connection, hints, flags) {
let vpnSetting = connection.get_setting_vpn();
@ -785,7 +782,7 @@ var NetworkAgent = new Lang.Class({
delete this._vpnRequests[requestId];
});
this._vpnRequests[requestId] = vpnRequest;
},
}
_buildVPNServiceCache() {
if (this._vpnCacheBuilt)
@ -818,5 +815,5 @@ var NetworkAgent = new Lang.Class({
}
});
}
});
};
var Component = NetworkAgent;

View File

@ -1,39 +1,23 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Lang = imports.lang;
const { AccountsService, Clutter, Gio, GLib,
Pango, PolkitAgent, Polkit, Shell, St } = imports.gi;
const Signals = imports.signals;
const Shell = imports.gi.Shell;
const AccountsService = imports.gi.AccountsService;
const Clutter = imports.gi.Clutter;
const St = imports.gi.St;
const Pango = imports.gi.Pango;
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const Mainloop = imports.mainloop;
const Polkit = imports.gi.Polkit;
const PolkitAgent = imports.gi.PolkitAgent;
const Animation = imports.ui.animation;
const Components = imports.ui.components;
const Dialog = imports.ui.dialog;
const Main = imports.ui.main;
const ModalDialog = imports.ui.modalDialog;
const ShellEntry = imports.ui.shellEntry;
const UserWidget = imports.ui.userWidget;
const Tweener = imports.ui.tweener;
var DIALOG_ICON_SIZE = 48;
var WORK_SPINNER_ICON_SIZE = 16;
var WORK_SPINNER_ANIMATION_DELAY = 1.0;
var WORK_SPINNER_ANIMATION_TIME = 0.3;
var AuthenticationDialog = new Lang.Class({
Name: 'AuthenticationDialog',
Extends: ModalDialog.ModalDialog,
_init(actionId, body, cookie, userNames) {
this.parent({ styleClass: 'prompt-dialog' });
var AuthenticationDialog = class extends ModalDialog.ModalDialog {
constructor(actionId, body, cookie, userNames) {
super({ styleClass: 'prompt-dialog' });
this.actionId = actionId;
this.message = body;
@ -44,6 +28,8 @@ var AuthenticationDialog = new Lang.Class({
this._group.visible = !Main.sessionMode.isLocked;
});
this.connect('closed', this._onDialogClosed.bind(this));
let icon = new Gio.ThemedIcon({ name: 'dialog-password-symbolic' });
let title = _("Authentication Required");
@ -117,10 +103,7 @@ var AuthenticationDialog = new Lang.Class({
this._passwordBox.add(this._passwordEntry,
{ expand: true });
let spinnerIcon = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/process-working.svg');
this._workSpinner = new Animation.AnimatedIcon(spinnerIcon, WORK_SPINNER_ICON_SIZE);
this._workSpinner.actor.opacity = 0;
this._workSpinner = new Animation.Spinner(WORK_SPINNER_ICON_SIZE, true);
this._passwordBox.add(this._workSpinner.actor);
this.setInitialKeyFocus(this._passwordEntry);
@ -161,50 +144,25 @@ var AuthenticationDialog = new Lang.Class({
this._identityToAuth = Polkit.UnixUser.new_for_name(userName);
this._cookie = cookie;
},
}
_setWorking(working) {
Tweener.removeTweens(this._workSpinner.actor);
if (working) {
if (working)
this._workSpinner.play();
Tweener.addTween(this._workSpinner.actor,
{ opacity: 255,
delay: WORK_SPINNER_ANIMATION_DELAY,
time: WORK_SPINNER_ANIMATION_TIME,
transition: 'linear'
});
} else {
Tweener.addTween(this._workSpinner.actor,
{ opacity: 0,
time: WORK_SPINNER_ANIMATION_TIME,
transition: 'linear',
onCompleteScope: this,
onComplete() {
if (this._workSpinner)
this._workSpinner.stop();
}
});
}
},
else
this._workSpinner.stop();
}
performAuthentication() {
this.destroySession();
this._destroySession();
this._session = new PolkitAgent.Session({ identity: this._identityToAuth,
cookie: this._cookie });
this._session.connect('completed', this._onSessionCompleted.bind(this));
this._session.connect('request', this._onSessionRequest.bind(this));
this._session.connect('show-error', this._onSessionShowError.bind(this));
this._session.connect('show-info', this._onSessionShowInfo.bind(this));
this._sessionCompletedId = this._session.connect('completed', this._onSessionCompleted.bind(this));
this._sessionRequestId = this._session.connect('request', this._onSessionRequest.bind(this));
this._sessionShowErrorId = this._session.connect('show-error', this._onSessionShowError.bind(this));
this._sessionShowInfoId = this._session.connect('show-info', this._onSessionShowInfo.bind(this));
this._session.initiate();
},
close(timestamp) {
this.parent(timestamp);
if (this._sessionUpdatedId)
Main.sessionMode.disconnect(this._sessionUpdatedId);
this._sessionUpdatedId = 0;
},
}
_ensureOpen() {
// NOTE: ModalDialog.open() is safe to call if the dialog is
@ -226,14 +184,14 @@ var AuthenticationDialog = new Lang.Class({
' cookie ' + this._cookie);
this._emitDone(true);
}
},
}
_emitDone(dismissed) {
if (!this._doneEmitted) {
this._doneEmitted = true;
this.emit('done', dismissed);
}
},
}
_updateSensitivity(sensitive) {
this._passwordEntry.reactive = sensitive;
@ -242,7 +200,7 @@ var AuthenticationDialog = new Lang.Class({
this._okButton.can_focus = sensitive;
this._okButton.reactive = sensitive;
this._setWorking(!sensitive);
},
}
_onEntryActivate() {
let response = this._passwordEntry.get_text();
@ -253,11 +211,11 @@ var AuthenticationDialog = new Lang.Class({
this._errorMessageLabel.hide();
this._infoMessageLabel.hide();
this._nullMessageLabel.show();
},
}
_onAuthenticateButtonPressed() {
this._onEntryActivate();
},
}
_onSessionCompleted(session, gainedAuthorization) {
if (this._completed || this._doneEmitted)
@ -289,7 +247,7 @@ var AuthenticationDialog = new Lang.Class({
/* Try and authenticate again */
this.performAuthentication();
}
},
}
_onSessionRequest(session, request, echo_on) {
// Cheap localization trick
@ -308,7 +266,7 @@ var AuthenticationDialog = new Lang.Class({
this._passwordEntry.grab_key_focus();
this._updateSensitivity(true);
this._ensureOpen();
},
}
_onSessionShowError(session, text) {
this._passwordEntry.set_text('');
@ -317,7 +275,7 @@ var AuthenticationDialog = new Lang.Class({
this._infoMessageLabel.hide();
this._nullMessageLabel.hide();
this._ensureOpen();
},
}
_onSessionShowInfo(session, text) {
this._passwordEntry.set_text('');
@ -326,43 +284,60 @@ var AuthenticationDialog = new Lang.Class({
this._errorMessageLabel.hide();
this._nullMessageLabel.hide();
this._ensureOpen();
},
}
destroySession() {
_destroySession() {
if (this._session) {
if (!this._completed)
this._session.cancel();
this._completed = false;
this._session.disconnect(this._sessionCompletedId);
this._session.disconnect(this._sessionRequestId);
this._session.disconnect(this._sessionShowErrorId);
this._session.disconnect(this._sessionShowInfoId);
this._session = null;
}
},
}
_onUserChanged() {
if (this._user.is_loaded && this._userAvatar) {
this._userAvatar.update();
this._userAvatar.actor.show();
}
},
}
cancel() {
this._wasDismissed = true;
this.close(global.get_current_time());
this._emitDone(true);
},
});
}
_onDialogClosed() {
if (this._sessionUpdatedId)
Main.sessionMode.disconnect(this._sessionUpdatedId);
this._sessionUpdatedId = 0;
if (this._user) {
this._user.disconnect(this._userLoadedId);
this._user.disconnect(this._userChangedId);
this._user = null;
}
this._destroySession();
}
};
Signals.addSignalMethods(AuthenticationDialog.prototype);
var AuthenticationAgent = new Lang.Class({
Name: 'AuthenticationAgent',
_init() {
var AuthenticationAgent = class {
constructor() {
this._currentDialog = null;
this._handle = null;
this._native = new Shell.PolkitAuthenticationAgent();
this._native.connect('initiate', this._onInitiate.bind(this));
this._native.connect('cancel', this._onCancel.bind(this));
this._sessionUpdatedId = 0;
},
}
enable() {
try {
@ -370,7 +345,7 @@ var AuthenticationAgent = new Lang.Class({
} catch(e) {
log('Failed to register AuthenticationAgent');
}
},
}
disable() {
try {
@ -378,7 +353,7 @@ var AuthenticationAgent = new Lang.Class({
} catch(e) {
log('Failed to unregister AuthenticationAgent');
}
},
}
_onInitiate(nativeAgent, actionId, message, iconName, cookie, userNames) {
// Don't pop up a dialog while locked
@ -406,19 +381,18 @@ var AuthenticationAgent = new Lang.Class({
this._currentDialog.connect('done', this._onDialogDone.bind(this));
this._currentDialog.performAuthentication();
},
}
_onCancel(nativeAgent) {
this._completeRequest(false);
},
}
_onDialogDone(dialog, dismissed) {
this._completeRequest(dismissed);
},
}
_completeRequest(dismissed) {
this._currentDialog.close();
this._currentDialog.destroySession();
this._currentDialog = null;
if (this._sessionUpdatedId)
@ -426,7 +400,7 @@ var AuthenticationAgent = new Lang.Class({
this._sessionUpdatedId = 0;
this._native.complete(dismissed);
},
});
}
};
var Component = AuthenticationAgent;

View File

@ -1,19 +1,13 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Gtk = imports.gi.Gtk;
const { Clutter, Gio, GLib, GObject, St } = imports.gi;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Signals = imports.signals;
const St = imports.gi.St;
var Tpl = null;
var Tp = null;
try {
Tpl = imports.gi.TelepathyLogger;
Tp = imports.gi.TelepathyGLib;
({ TelepathyGLib: Tp, TelepathyLogger: Tpl } = imports.gi);
} catch(e) {
log('Telepathy is not available, chat integration will be disabled.');
}
@ -23,7 +17,6 @@ const Main = imports.ui.main;
const MessageList = imports.ui.messageList;
const MessageTray = imports.ui.messageTray;
const Params = imports.misc.params;
const PopupMenu = imports.ui.popupMenu;
const Util = imports.misc.util;
const HAVE_TP = (Tp != null && Tpl != null);
@ -79,17 +72,15 @@ function makeMessageFromTplEvent(event) {
};
}
var TelepathyComponent = new Lang.Class({
Name: 'TelepathyComponent',
_init() {
var TelepathyComponent = class {
constructor() {
this._client = null;
if (!HAVE_TP)
return; // Telepathy isn't available
this._client = new TelepathyClient();
},
}
enable() {
if (!this._client)
@ -103,7 +94,7 @@ var TelepathyComponent = new Lang.Class({
if (!this._client.account_manager.is_prepared(Tp.AccountManager.get_feature_quark_core()))
this._client.account_manager.prepare_async(null, null);
},
}
disable() {
if (!this._client)
@ -111,12 +102,10 @@ var TelepathyComponent = new Lang.Class({
this._client.unregister();
}
});
var TelepathyClient = HAVE_TP ? new Lang.Class({
Name: 'TelepathyClient',
Extends: Tp.BaseClient,
};
var TelepathyClient = HAVE_TP ? GObject.registerClass(
class TelepathyClient extends Tp.BaseClient {
_init() {
// channel path -> ChatSource
this._chatSources = {};
@ -140,7 +129,7 @@ var TelepathyClient = HAVE_TP ? new Lang.Class({
// channel matching its filters is detected.
// The second argument, recover, means _observeChannels will be run
// for any existing channel as well.
this.parent({ name: 'GnomeShell',
super._init({ name: 'GnomeShell',
account_manager: this._accountManager,
uniquify_name: true });
@ -158,7 +147,7 @@ var TelepathyClient = HAVE_TP ? new Lang.Class({
// needed
this.set_delegated_channels_callback(
this._delegatedChannelsCb.bind(this));
},
}
vfunc_observe_channels(account, conn, channels,
dispatchOp, requests, context) {
@ -179,7 +168,7 @@ var TelepathyClient = HAVE_TP ? new Lang.Class({
}
context.accept();
},
}
_createChatSource(account, conn, channel, contact) {
if (this._chatSources[channel.get_object_path()])
@ -191,13 +180,13 @@ var TelepathyClient = HAVE_TP ? new Lang.Class({
source.connect('destroy', () => {
delete this._chatSources[channel.get_object_path()];
});
},
}
vfunc_handle_channels(account, conn, channels, requests,
user_action_time, context) {
this._handlingChannels(account, conn, channels, true);
context.accept();
},
}
_handlingChannels(account, conn, channels, notify) {
let len = channels.length;
@ -231,7 +220,7 @@ var TelepathyClient = HAVE_TP ? new Lang.Class({
source.notify();
}
}
},
}
vfunc_add_dispatch_operation(account, conn, channels,
dispatchOp, context) {
@ -249,7 +238,7 @@ var TelepathyClient = HAVE_TP ? new Lang.Class({
else
context.fail(new Tp.Error({ code: Tp.Error.INVALID_ARGUMENT,
message: 'Unsupported channel type' }));
},
}
_approveTextChannel(account, conn, channel, dispatchOp, context) {
let [targetHandle, targetHandleType] = channel.get_handle();
@ -271,25 +260,22 @@ var TelepathyClient = HAVE_TP ? new Lang.Class({
});
context.accept();
},
}
_delegatedChannelsCb(client, channels) {
// Nothing to do as we don't make a distinction between observed and
// handled channels.
},
}
}) : null;
var ChatSource = new Lang.Class({
Name: 'ChatSource',
Extends: MessageTray.Source,
var ChatSource = class extends MessageTray.Source {
constructor(account, conn, channel, contact, client) {
super(contact.get_alias());
_init(account, conn, channel, contact, client) {
this._account = account;
this._contact = contact;
this._client = client;
this.parent(contact.get_alias());
this.isChat = true;
this._pendingMessages = [];
@ -313,7 +299,7 @@ var ChatSource = new Lang.Class({
Main.messageTray.add(this);
this._getLogMessages();
},
}
_ensureNotification() {
if (this._notification)
@ -329,13 +315,13 @@ var ChatSource = new Lang.Class({
this._notification = null;
});
this.pushNotification(this._notification);
},
}
_createPolicy() {
if (this._account.protocol_name == 'irc')
return new MessageTray.NotificationApplicationPolicy('org.gnome.Polari');
return new MessageTray.NotificationApplicationPolicy('empathy');
},
}
createBanner() {
this._banner = new ChatNotificationBanner(this._notification);
@ -348,7 +334,7 @@ var ChatSource = new Lang.Class({
});
return this._banner;
},
}
_updateAlias() {
let oldAlias = this.title;
@ -360,7 +346,7 @@ var ChatSource = new Lang.Class({
this.setTitle(newAlias);
if (this._notification)
this._notification.appendAliasChange(oldAlias, newAlias);
},
}
getIcon() {
let file = this._contact.get_avatar_file();
@ -369,7 +355,7 @@ var ChatSource = new Lang.Class({
} else {
return new Gio.ThemedIcon({ name: 'avatar-default' });
}
},
}
getSecondaryIcon() {
let iconName;
@ -398,7 +384,7 @@ var ChatSource = new Lang.Class({
iconName = 'user-offline';
}
return new Gio.ThemedIcon({ name: iconName });
},
}
_updateAvatarIcon() {
this.iconUpdated();
@ -406,7 +392,7 @@ var ChatSource = new Lang.Class({
this._notification.update(this._notification.title,
this._notification.bannerBodyText,
{ gicon: this.getIcon() });
},
}
open() {
Main.overview.hide();
@ -431,7 +417,7 @@ var ChatSource = new Lang.Class({
cd.present_channel_async(this._channel, global.get_current_time(), null);
}
},
}
_getLogMessages() {
let logManager = Tpl.LogManager.dup_singleton();
@ -440,7 +426,7 @@ var ChatSource = new Lang.Class({
logManager.get_filtered_events_async(this._account, entity,
Tpl.EventTypeMask.TEXT, SCROLLBACK_HISTORY_LINES,
null, this._displayPendingMessages.bind(this));
},
}
_displayPendingMessages(logManager, result) {
let [success, events] = logManager.get_filtered_events_finish(result);
@ -493,7 +479,7 @@ var ChatSource = new Lang.Class({
if (pendingMessages.length > 0)
this.notify();
},
}
destroy(reason) {
if (this._client.is_handling_channel(this._channel)) {
@ -527,25 +513,25 @@ var ChatSource = new Lang.Class({
this._contact.disconnect(this._notifyAvatarId);
this._contact.disconnect(this._presenceChangedId);
this.parent(reason);
},
super.destroy(reason);
}
_channelClosed() {
this.destroy(MessageTray.NotificationDestroyedReason.SOURCE_CLOSED);
},
}
/* All messages are new messages for Telepathy sources */
get count() {
return this._pendingMessages.length;
},
}
get unseenCount() {
return this.count;
},
}
get countVisible() {
return this.count > 0;
},
}
_messageReceived(channel, message) {
if (message.get_message_type() == Tp.ChannelTextMessageType.DELIVERY_REPORT)
@ -565,7 +551,7 @@ var ChatSource = new Lang.Class({
this._notifyTimeoutId = Mainloop.timeout_add(500,
this._notifyTimeout.bind(this));
GLib.Source.set_name_by_id(this._notifyTimeoutId, '[gnome-shell] this._notifyTimeout');
},
}
_notifyTimeout() {
if (this._pendingMessages.length != 0)
@ -574,7 +560,7 @@ var ChatSource = new Lang.Class({
this._notifyTimeoutId = 0;
return GLib.SOURCE_REMOVE;
},
}
// This is called for both messages we send from
// our client and other clients as well.
@ -582,11 +568,11 @@ var ChatSource = new Lang.Class({
this._ensureNotification();
message = makeMessageFromTpMessage(message, NotificationDirection.SENT);
this._notification.appendMessage(message);
},
}
notify() {
this.parent(this._notification);
},
super.notify(this._notification);
}
respond(text) {
let type;
@ -601,7 +587,7 @@ var ChatSource = new Lang.Class({
this._channel.send_message_async(msg, 0, (src, result) => {
this._channel.send_message_finish(result);
});
},
}
setChatState(state) {
// We don't want to send COMPOSING every time a letter is typed into
@ -614,14 +600,14 @@ var ChatSource = new Lang.Class({
this._chatState = state;
this._channel.set_chat_state_async(state, null);
}
},
}
_presenceChanged(contact, presence, status, message) {
if (this._notification)
this._notification.update(this._notification.title,
this._notification.bannerBodyText,
{ secondaryGIcon: this.getSecondaryIcon() });
},
}
_pendingRemoved(channel, message) {
let idx = this._pendingMessages.indexOf(message);
@ -634,35 +620,32 @@ var ChatSource = new Lang.Class({
if (this._pendingMessages.length == 0 &&
this._banner && !this._banner.expanded)
this._banner.hide();
},
}
_ackMessages() {
// Don't clear our messages here, tp-glib will send a
// 'pending-message-removed' for each one.
this._channel.ack_all_pending_messages_async(null);
}
});
};
var ChatNotification = new Lang.Class({
Name: 'ChatNotification',
Extends: MessageTray.Notification,
_init(source) {
this.parent(source, source.title, null,
{ secondaryGIcon: source.getSecondaryIcon() });
var ChatNotification = class extends MessageTray.Notification {
constructor(source) {
super(source, source.title, null,
{ secondaryGIcon: source.getSecondaryIcon() });
this.setUrgency(MessageTray.Urgency.HIGH);
this.setResident(true);
this.messages = [];
this._timestampTimeoutId = 0;
},
}
destroy(reason) {
if (this._timestampTimeoutId)
Mainloop.source_remove(this._timestampTimeoutId);
this._timestampTimeoutId = 0;
this.parent(reason);
},
super.destroy(reason);
}
/**
* appendMessage:
@ -700,7 +683,7 @@ var ChatNotification = new Lang.Class({
styles: styles,
timestamp: message.timestamp,
noTimestamp: noTimestamp });
},
}
_filterMessages() {
if (this.messages.length < 1)
@ -725,7 +708,7 @@ var ChatNotification = new Lang.Class({
for (let i = 0; i < expired.length; i++)
this.emit('message-removed', expired[i]);
}
},
}
/**
* _append:
@ -773,7 +756,7 @@ var ChatNotification = new Lang.Class({
}
this._filterMessages();
},
}
appendTimestamp() {
this._timestampTimeoutId = 0;
@ -784,7 +767,7 @@ var ChatNotification = new Lang.Class({
this._filterMessages();
return GLib.SOURCE_REMOVE;
},
}
appendAliasChange(oldAlias, newAlias) {
oldAlias = GLib.markup_escape_text(oldAlias, -1);
@ -800,24 +783,19 @@ var ChatNotification = new Lang.Class({
this._filterMessages();
}
});
var ChatLineBox = new Lang.Class({
Name: 'ChatLineBox',
Extends: St.BoxLayout,
};
var ChatLineBox = GObject.registerClass(
class ChatLineBox extends St.BoxLayout {
vfunc_get_preferred_height(forWidth) {
let [, natHeight] = this.parent(forWidth);
let [, natHeight] = super.vfunc_get_preferred_height(forWidth);
return [natHeight, natHeight];
}
});
var ChatNotificationBanner = new Lang.Class({
Name: 'ChatNotificationBanner',
Extends: MessageTray.NotificationBanner,
_init(notification) {
this.parent(notification);
var ChatNotificationBanner = class extends MessageTray.NotificationBanner {
constructor(notification) {
super(notification);
this._responseEntry = new St.Entry({ style_class: 'chat-response',
x_expand: true,
@ -835,8 +813,8 @@ var ChatNotificationBanner = new Lang.Class({
});
this._scrollArea = new St.ScrollView({ style_class: 'chat-scrollview vfade',
vscrollbar_policy: Gtk.PolicyType.AUTOMATIC,
hscrollbar_policy: Gtk.PolicyType.NEVER,
vscrollbar_policy: St.PolicyType.AUTOMATIC,
hscrollbar_policy: St.PolicyType.NEVER,
visible: this.expanded });
this._contentArea = new St.BoxLayout({ style_class: 'chat-body',
vertical: true });
@ -880,14 +858,14 @@ var ChatNotificationBanner = new Lang.Class({
for (let i = this.notification.messages.length - 1; i >= 0; i--)
this._addMessage(this.notification.messages[i]);
},
}
_onDestroy() {
this.parent();
super._onDestroy();
this.notification.disconnect(this._messageAddedId);
this.notification.disconnect(this._messageRemovedId);
this.notification.disconnect(this._timestampChangedId);
},
}
scrollTo(side) {
let adjustment = this._scrollArea.vscroll.adjustment;
@ -895,11 +873,11 @@ var ChatNotificationBanner = new Lang.Class({
adjustment.value = adjustment.lower;
else if (side == St.Side.BOTTOM)
adjustment.value = adjustment.upper;
},
}
hide() {
this.emit('done-displaying');
},
}
_addMessage(message) {
let highlighter = new MessageList.URLHighlighter(message.body, true, true);
@ -921,7 +899,7 @@ var ChatNotificationBanner = new Lang.Class({
this._messageActors.set(message, lineBox);
this._updateTimestamp(message);
},
}
_updateTimestamp(message) {
let actor = this._messageActors.get(message);
@ -942,7 +920,7 @@ var ChatNotificationBanner = new Lang.Class({
actor.add_actor(timeLabel);
}
},
}
_onEntryActivated() {
let text = this._responseEntry.get_text();
@ -955,7 +933,7 @@ var ChatNotificationBanner = new Lang.Class({
// see Source._messageSent
this._responseEntry.set_text('');
this.notification.source.respond(text);
},
}
_composingStopTimeout() {
this._composingTimeoutId = 0;
@ -963,7 +941,7 @@ var ChatNotificationBanner = new Lang.Class({
this.notification.source.setChatState(Tp.ChannelChatState.PAUSED);
return GLib.SOURCE_REMOVE;
},
}
_onEntryChanged() {
let text = this._responseEntry.get_text();
@ -990,6 +968,6 @@ var ChatNotificationBanner = new Lang.Class({
this.notification.source.setChatState(Tp.ChannelChatState.ACTIVE);
}
}
});
};
var Component = TelepathyComponent;

View File

@ -1,16 +1,10 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const { Clutter, GObject, Meta, Shell, St } = imports.gi;
const Main = imports.ui.main;
const SwitcherPopup = imports.ui.switcherPopup;
const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
var POPUP_APPICON_SIZE = 96;
var POPUP_FADE_TIME = 0.1; // seconds
@ -21,15 +15,13 @@ var SortGroup = {
BOTTOM: 2
};
var CtrlAltTabManager = new Lang.Class({
Name: 'CtrlAltTabManager',
_init() {
var CtrlAltTabManager = class CtrlAltTabManager {
constructor() {
this._items = [];
this.addGroup(global.window_group, _("Windows"),
'focus-windows-symbolic', { sortGroup: SortGroup.TOP,
focusCallback: this._focusWindows.bind(this) });
},
}
addGroup(root, name, icon, params) {
let item = Params.parse(params, { sortGroup: SortGroup.MIDDLE,
@ -44,7 +36,7 @@ var CtrlAltTabManager = new Lang.Class({
root.connect('destroy', () => { this.removeGroup(root); });
if (root instanceof St.Widget)
global.focus_manager.add_group(root);
},
}
removeGroup(root) {
if (root instanceof St.Widget)
@ -55,14 +47,14 @@ var CtrlAltTabManager = new Lang.Class({
return;
}
}
},
}
focusGroup(item, timestamp) {
if (item.focusCallback)
item.focusCallback(timestamp);
else
item.root.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
},
item.root.navigate_focus(null, St.DirectionType.TAB_FORWARD, false);
}
// Sort the items into a consistent order; panel first, tray last,
// and everything else in between, sorted by X coordinate, so that
@ -77,7 +69,7 @@ var CtrlAltTabManager = new Lang.Class({
[bx, y] = b.proxy.get_transformed_position();
return ax - bx;
},
}
popup(backward, binding, mask) {
// Start with the set of focus groups that are currently mapped
@ -102,7 +94,9 @@ var CtrlAltTabManager = new Lang.Class({
if (app)
icon = app.create_icon_texture(POPUP_APPICON_SIZE);
else
icon = textureCache.bind_cairo_surface_property(windows[i], 'icon');
icon = textureCache.bind_cairo_surface_property(windows[i],
'icon',
POPUP_APPICON_SIZE);
}
items.push({ name: windows[i].title,
@ -130,22 +124,20 @@ var CtrlAltTabManager = new Lang.Class({
this._popup = null;
});
}
},
}
_focusWindows(timestamp) {
global.display.focus_default_window(timestamp);
}
});
var CtrlAltTabPopup = new Lang.Class({
Name: 'CtrlAltTabPopup',
Extends: SwitcherPopup.SwitcherPopup,
};
var CtrlAltTabPopup = GObject.registerClass(
class CtrlAltTabPopup extends SwitcherPopup.SwitcherPopup {
_init(items) {
this.parent(items);
super._init(items);
this._switcherList = new CtrlAltTabSwitcher(this._items);
},
}
_keyPressHandler(keysym, action) {
if (action == Meta.KeyBindingAction.SWITCH_PANELS)
@ -160,24 +152,22 @@ var CtrlAltTabPopup = new Lang.Class({
return Clutter.EVENT_PROPAGATE;
return Clutter.EVENT_STOP;
},
}
_finish(time) {
this.parent(time);
super._finish(time);
Main.ctrlAltTabManager.focusGroup(this._items[this._selectedIndex], time);
},
}
});
var CtrlAltTabSwitcher = new Lang.Class({
Name: 'CtrlAltTabSwitcher',
Extends: SwitcherPopup.SwitcherList,
var CtrlAltTabSwitcher = GObject.registerClass(
class CtrlAltTabSwitcher extends SwitcherPopup.SwitcherList {
_init(items) {
this.parent(true);
super._init(true);
for (let i = 0; i < items.length; i++)
this._addIcon(items[i]);
},
}
_addIcon(item) {
let box = new St.BoxLayout({ style_class: 'alt-tab-app',

View File

@ -1,14 +1,8 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Signals = imports.signals;
const Lang = imports.lang;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const { Clutter, GLib, GObject, Meta, Shell, St } = imports.gi;
const Mainloop = imports.mainloop;
const Signals = imports.signals;
const AppDisplay = imports.ui.appDisplay;
const AppFavorites = imports.ui.appFavorites;
@ -16,7 +10,6 @@ const DND = imports.ui.dnd;
const IconGrid = imports.ui.iconGrid;
const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
const Workspace = imports.ui.workspace;
var DASH_ANIMATION_TIME = 0.2;
var DASH_ITEM_LABEL_SHOW_TIME = 0.15;
@ -33,12 +26,10 @@ function getAppFromSource(source) {
// A container like StBin, but taking the child's scale into account
// when requesting a size
var DashItemContainer = new Lang.Class({
Name: 'DashItemContainer',
Extends: St.Widget,
var DashItemContainer = GObject.registerClass(
class DashItemContainer extends St.Widget {
_init() {
this.parent({ style_class: 'dash-item-container',
super._init({ style_class: 'dash-item-container',
pivot_point: new Clutter.Point({ x: .5, y: .5 }),
x_expand: true,
x_align: Clutter.ActorAlign.CENTER });
@ -59,23 +50,23 @@ var DashItemContainer = new Lang.Class({
this.child.destroy();
this.label.destroy();
});
},
}
vfunc_get_preferred_height(forWidth) {
let themeNode = this.get_theme_node();
forWidth = themeNode.adjust_for_width(forWidth);
let [minHeight, natHeight] = this.parent(forWidth);
let [minHeight, natHeight] = super.vfunc_get_preferred_height(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();
forHeight = themeNode.adjust_for_height(forHeight);
let [minWidth, natWidth] = this.parent(forHeight);
let [minWidth, natWidth] = super.vfunc_get_preferred_width(forHeight);
return themeNode.adjust_preferred_width(minWidth * this.scale_x,
natWidth * this.scale_x);
},
}
showLabel() {
if (!this._labelText)
@ -109,12 +100,12 @@ var DashItemContainer = new Lang.Class({
time: DASH_ITEM_LABEL_SHOW_TIME,
transition: 'easeOutQuad',
});
},
}
setLabelText(text) {
this._labelText = text;
this.child.accessible_name = text;
},
}
hideLabel() {
Tweener.addTween(this.label,
@ -125,7 +116,7 @@ var DashItemContainer = new Lang.Class({
this.label.hide();
}
});
},
}
setChild(actor) {
if (this.child == actor)
@ -138,7 +129,7 @@ var DashItemContainer = new Lang.Class({
this.set_scale(this._childScale, this._childScale);
this.set_opacity(this._childOpacity);
},
}
show(animate) {
if (this.child == null)
@ -151,7 +142,7 @@ var DashItemContainer = new Lang.Class({
time: time,
transition: 'easeOutQuad'
});
},
}
animateOutAndDestroy() {
this.label.hide();
@ -171,37 +162,35 @@ var DashItemContainer = new Lang.Class({
this.destroy();
}
});
},
}
set childScale(scale) {
this._childScale = scale;
this.set_scale(scale, scale);
this.queue_relayout();
},
}
get childScale() {
return this._childScale;
},
}
set childOpacity(opacity) {
this._childOpacity = opacity;
this.set_opacity(opacity);
this.queue_redraw();
},
}
get childOpacity() {
return this._childOpacity;
}
});
var ShowAppsIcon = new Lang.Class({
Name: 'ShowAppsIcon',
Extends: DashItemContainer,
var ShowAppsIcon = GObject.registerClass(
class ShowAppsIcon extends DashItemContainer {
_init() {
this.parent();
super._init();
this.toggleButton = new St.Button({ style_class: 'show-apps',
track_hover: true,
@ -217,7 +206,7 @@ var ShowAppsIcon = new Lang.Class({
this.setChild(this.toggleButton);
this.setDragApp(null);
},
}
_createIcon(size) {
this._iconActor = new St.Icon({ icon_name: 'view-app-grid-symbolic',
@ -225,7 +214,7 @@ var ShowAppsIcon = new Lang.Class({
style_class: 'show-apps-icon',
track_hover: true });
return this._iconActor;
},
}
_canRemoveApp(app) {
if (app == null)
@ -237,7 +226,7 @@ var ShowAppsIcon = new Lang.Class({
let id = app.get_id();
let isFavorite = AppFavorites.getAppFavorites().isFavorite(id);
return isFavorite;
},
}
setDragApp(app) {
let canRemove = this._canRemoveApp(app);
@ -250,14 +239,14 @@ var ShowAppsIcon = new Lang.Class({
this.setLabelText(_("Remove from Favorites"));
else
this.setLabelText(_("Show Applications"));
},
}
handleDragOver(source, actor, x, y, time) {
if (!this._canRemoveApp(getAppFromSource(source)))
return DND.DragMotionResult.NO_DROP;
return DND.DragMotionResult.MOVE_DROP;
},
}
acceptDrop(source, actor, x, y, time) {
let app = getAppFromSource(source);
@ -275,36 +264,30 @@ var ShowAppsIcon = new Lang.Class({
}
});
var DragPlaceholderItem = new Lang.Class({
Name: 'DragPlaceholderItem',
Extends: DashItemContainer,
var DragPlaceholderItem = GObject.registerClass(
class DragPlaceholderItem extends DashItemContainer {
_init() {
this.parent();
super._init();
this.setChild(new St.Bin({ style_class: 'placeholder' }));
}
});
var EmptyDropTargetItem = new Lang.Class({
Name: 'EmptyDropTargetItem',
Extends: DashItemContainer,
var EmptyDropTargetItem = GObject.registerClass(
class EmptyDropTargetItem extends DashItemContainer {
_init() {
this.parent();
super._init();
this.setChild(new St.Bin({ style_class: 'empty-dash-drop-target' }));
}
});
var DashActor = new Lang.Class({
Name: 'DashActor',
Extends: St.Widget,
var DashActor = GObject.registerClass(
class DashActor extends St.Widget {
_init() {
let layout = new Clutter.BoxLayout({ orientation: Clutter.Orientation.VERTICAL });
this.parent({ name: 'dash',
super._init({ name: 'dash',
layout_manager: layout,
clip_to_allocation: true });
},
}
vfunc_allocate(box, flags) {
let contentBox = this.get_theme_node().get_content_box(box);
@ -325,7 +308,7 @@ var DashActor = new Lang.Class({
childBox.y1 = contentBox.y2 - showAppsNatHeight;
childBox.y2 = contentBox.y2;
showAppsButton.allocate(childBox, flags);
},
}
vfunc_get_preferred_height(forWidth) {
// We want to request the natural height of all our children
@ -333,7 +316,7 @@ var DashActor = new Lang.Class({
// then calls BoxLayout), but we only request the showApps
// button as the minimum size
let [, natHeight] = this.parent(forWidth);
let [, natHeight] = super.vfunc_get_preferred_height(forWidth);
let themeNode = this.get_theme_node();
let adjustedForWidth = themeNode.adjust_for_width(forWidth);
@ -347,10 +330,8 @@ var DashActor = new Lang.Class({
const baseIconSizes = [ 16, 22, 24, 32, 48, 64 ];
var Dash = new Lang.Class({
Name: 'Dash',
_init() {
var Dash = class Dash {
constructor() {
this._maxHeight = -1;
this.iconSize = 64;
this._shownInitially = false;
@ -407,7 +388,7 @@ var Dash = new Lang.Class({
// Translators: this is the name of the dock/favorites area on
// the left of the overview
Main.ctrlAltTabManager.addGroup(this.actor, _("Dash"), 'user-bookmarks-symbolic');
},
}
_onDragBegin() {
this._dragCancelled = false;
@ -421,26 +402,26 @@ var Dash = new Lang.Class({
this._box.insert_child_at_index(this._emptyDropTarget, 0);
this._emptyDropTarget.show(true);
}
},
}
_onDragCancelled() {
this._dragCancelled = true;
this._endDrag();
},
}
_onDragEnd() {
if (this._dragCancelled)
return;
this._endDrag();
},
}
_endDrag() {
this._clearDragPlaceholder();
this._clearEmptyDropTarget();
this._showAppsIcon.setDragApp(null);
DND.removeDragMonitor(this._dragMonitor);
},
}
_onDragMotion(dragEvent) {
let app = getAppFromSource(dragEvent.source);
@ -459,18 +440,18 @@ var Dash = new Lang.Class({
this._showAppsIcon.setDragApp(null);
return DND.DragMotionResult.CONTINUE;
},
}
_appIdListToHash(apps) {
let ids = {};
for (let i = 0; i < apps.length; i++)
ids[apps[i].get_id()] = apps[i];
return ids;
},
}
_queueRedisplay() {
Main.queueDeferredWork(this._workId);
},
}
_hookUpLabel(item, appIcon) {
item.child.connect('notify::hover', () => {
@ -490,7 +471,7 @@ var Dash = new Lang.Class({
this._syncLabel(item, appIcon);
});
}
},
}
_createAppItem(app) {
let appIcon = new AppDisplay.AppIcon(app,
@ -524,7 +505,7 @@ var Dash = new Lang.Class({
this._hookUpLabel(item, appIcon);
return item;
},
}
_itemMenuStateChanged(item, opened) {
// When the menu closes, it calls sync_hover, which means
@ -537,7 +518,7 @@ var Dash = new Lang.Class({
item.hideLabel();
}
},
}
_syncLabel(item, appIcon) {
let shouldShow = appIcon ? appIcon.shouldShowTooltip() : item.child.get_hover();
@ -573,7 +554,7 @@ var Dash = new Lang.Class({
GLib.Source.set_name_by_id(this._resetHoverTimeoutId, '[gnome-shell] this._labelShowing');
}
}
},
}
_adjustIconSize() {
// For the icon size, we only consider children which are "proper"
@ -603,22 +584,18 @@ var Dash = new Lang.Class({
let firstButton = iconChildren[0].child;
let firstIcon = firstButton._delegate.icon;
let minHeight, natHeight;
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
// Enforce the current icon size during the size request
// Enforce valid spacings during the size request
firstIcon.icon.ensure_style();
let [, currentHeight] = firstIcon.icon.get_size();
firstIcon.icon.set_height(this.iconSize * scaleFactor);
[minHeight, natHeight] = firstButton.get_preferred_height(-1);
firstIcon.icon.set_height(currentHeight);
let [, iconHeight] = firstIcon.icon.get_preferred_height(-1);
let [, buttonHeight] = firstButton.get_preferred_height(-1);
// Subtract icon padding and box spacing from the available height
availHeight -= iconChildren.length * (natHeight - this.iconSize * scaleFactor) +
availHeight -= iconChildren.length * (buttonHeight - iconHeight) +
(iconChildren.length - 1) * spacing;
let availSize = availHeight / iconChildren.length;
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
let iconSizes = baseIconSizes.map(s => s * scaleFactor);
let newIconSize = baseIconSizes[0];
@ -663,7 +640,7 @@ var Dash = new Lang.Class({
transition: 'easeOutQuad',
});
}
},
}
_redisplay() {
let favorites = AppFavorites.getAppFavorites().getFavoriteMap();
@ -792,7 +769,7 @@ var Dash = new Lang.Class({
// Workaround for https://bugzilla.gnome.org/show_bug.cgi?id=692744
// Without it, StBoxLayout may use a stale size cache
this._box.queue_relayout();
},
}
_clearDragPlaceholder() {
if (this._dragPlaceholder) {
@ -804,14 +781,14 @@ var Dash = new Lang.Class({
this._dragPlaceholder = null;
}
this._dragPlaceholderPos = -1;
},
}
_clearEmptyDropTarget() {
if (this._emptyDropTarget) {
this._emptyDropTarget.animateOutAndDestroy();
this._emptyDropTarget = null;
}
},
}
handleDragOver(source, actor, x, y, time) {
let app = getAppFromSource(source);
@ -888,7 +865,7 @@ var Dash = new Lang.Class({
return DND.DragMotionResult.MOVE_DROP;
return DND.DragMotionResult.COPY_DROP;
},
}
// Draggable target interface
acceptDrop(source, actor, x, y, time) {
@ -938,6 +915,5 @@ var Dash = new Lang.Class({
return true;
}
});
};
Signals.addSignalMethods(Dash.prototype);

View File

@ -1,29 +1,17 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const GnomeDesktop = imports.gi.GnomeDesktop;
const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
const GWeather = imports.gi.GWeather;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Pango = imports.gi.Pango;
const Cairo = imports.cairo;
const Clutter = imports.gi.Clutter;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const Atk = imports.gi.Atk;
const { Clutter, GLib, GnomeDesktop,
GObject, GWeather, Shell, St } = imports.gi;
const Params = imports.misc.params;
const Util = imports.misc.util;
const Main = imports.ui.main;
const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;
const Calendar = imports.ui.calendar;
const Weather = imports.misc.weather;
const System = imports.system;
const MAX_FORECASTS = 5;
function _isToday(date) {
let now = new Date();
return now.getYear() == date.getYear() &&
@ -31,10 +19,8 @@ function _isToday(date) {
now.getDate() == date.getDate();
}
var TodayButton = new Lang.Class({
Name: 'TodayButton',
_init(calendar) {
var TodayButton = class TodayButton {
constructor(calendar) {
// Having the ability to go to the current date if the user is already
// on the current date can be confusing. So don't make the button reactive
// until the selected date changes.
@ -63,7 +49,7 @@ var TodayButton = new Lang.Class({
// current date.
this.actor.reactive = !_isToday(date)
});
},
}
setDate(date) {
this._dayLabel.set_text(date.toLocaleFormat('%A'));
@ -83,12 +69,10 @@ var TodayButton = new Lang.Class({
dateFormat = Shell.util_translate_time_string (N_("%A %B %e %Y"));
this.actor.accessible_name = date.toLocaleFormat(dateFormat);
}
});
};
var WorldClocksSection = new Lang.Class({
Name: 'WorldClocksSection',
_init() {
var WorldClocksSection = class WorldClocksSection {
constructor() {
this._clock = new GnomeDesktop.WallClock();
this._clockNotifyId = 0;
@ -118,11 +102,11 @@ var WorldClocksSection = new Lang.Class({
this._clockAppMon.watchSetting('world-clocks',
this._clocksChanged.bind(this));
this._sync();
},
}
_sync() {
this.actor.visible = this._clockAppMon.available;
},
}
_clocksChanged(settings) {
this._grid.destroy_all_children();
@ -152,26 +136,37 @@ var WorldClocksSection = new Lang.Class({
layout.attach(header, 0, 0, 2, 1);
this.actor.label_actor = header;
let localOffset = GLib.DateTime.new_now_local().get_utc_offset();
for (let i = 0; i < this._locations.length; i++) {
let l = this._locations[i].location;
let name = l.get_level() == GWeather.LocationLevel.NAMED_TIMEZONE ? l.get_name()
: l.get_city_name();
let name = l.get_city_name() || l.get_name();
let label = new St.Label({ style_class: 'world-clocks-city',
text: name,
x_align: Clutter.ActorAlign.START,
y_align: Clutter.ActorAlign.CENTER,
x_expand: true });
let time = new St.Label({ style_class: 'world-clocks-time',
x_align: Clutter.ActorAlign.END,
x_expand: true });
let time = new St.Label({ style_class: 'world-clocks-time' });
let otherOffset = this._getTimeAtLocation(l).get_utc_offset();
let offset = (otherOffset - localOffset) / GLib.TIME_SPAN_HOUR;
let fmt = (Math.trunc(offset) == offset) ? '%s%.0f' : '%s%.1f';
let prefix = (offset >= 0) ? '+' : '-';
let tz = new St.Label({ style_class: 'world-clocks-timezone',
text: fmt.format(prefix, Math.abs(offset)),
x_align: Clutter.ActorAlign.END,
y_align: Clutter.ActorAlign.CENTER });
if (this._grid.text_direction == Clutter.TextDirection.RTL) {
layout.attach(time, 0, i + 1, 1, 1);
layout.attach(label, 1, i + 1, 1, 1);
layout.attach(tz, 0, i + 1, 1, 1);
layout.attach(time, 1, i + 1, 1, 1);
layout.attach(label, 2, i + 1, 1, 1);
} else {
layout.attach(label, 0, i + 1, 1, 1);
layout.attach(time, 1, i + 1, 1, 1);
layout.attach(tz, 2, i + 1, 1, 1);
}
this._locations[i].actor = time;
@ -187,22 +182,24 @@ var WorldClocksSection = new Lang.Class({
this._clock.disconnect(this._clockNotifyId);
this._clockNotifyId = 0;
}
},
}
_getTimeAtLocation(location) {
let tz = GLib.TimeZone.new(location.get_timezone().get_tzid());
return GLib.DateTime.new_now(tz);
}
_updateLabels() {
for (let i = 0; i < this._locations.length; i++) {
let l = this._locations[i];
let tz = GLib.TimeZone.new(l.location.get_timezone().get_tzid());
let now = GLib.DateTime.new_now(tz);
let now = this._getTimeAtLocation(l.location);
l.actor.text = Util.formatTime(now, { timeOnly: true });
}
}
});
};
var WeatherSection = new Lang.Class({
Name: 'WeatherSection',
_init() {
var WeatherSection = class WeatherSection {
constructor() {
this._weatherClient = new Weather.WeatherClient();
this.actor = new St.Button({ style_class: 'weather-button',
@ -224,111 +221,115 @@ var WeatherSection = new Lang.Class({
this.actor.child = box;
box.add_child(new St.Label({ style_class: 'weather-header',
x_align: Clutter.ActorAlign.START,
text: _("Weather") }));
let titleBox = new St.BoxLayout();
titleBox.add_child(new St.Label({ style_class: 'weather-header',
x_align: Clutter.ActorAlign.START,
x_expand: true,
text: _("Weather") }));
box.add_child(titleBox);
this._conditionsLabel = new St.Label({ style_class: 'weather-conditions',
x_align: Clutter.ActorAlign.START });
this._conditionsLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
this._conditionsLabel.clutter_text.line_wrap = true;
box.add_child(this._conditionsLabel);
this._titleLocation = new St.Label({ style_class: 'weather-header location',
x_align: Clutter.ActorAlign.END });
titleBox.add_child(this._titleLocation);
let layout = new Clutter.GridLayout({ orientation: Clutter.Orientation.VERTICAL });
this._forecastGrid = new St.Widget({ style_class: 'weather-grid',
layout_manager: layout });
layout.hookup_style(this._forecastGrid);
box.add_child(this._forecastGrid);
this._weatherClient.connect('changed', this._sync.bind(this));
this._sync();
},
}
_getSummary(info, capitalize=false) {
let options = capitalize ? GWeather.FormatOptions.SENTENCE_CAPITALIZATION
: GWeather.FormatOptions.NO_CAPITALIZATION;
let [ok, phenomenon, qualifier] = info.get_value_conditions();
if (ok)
return new GWeather.Conditions({ significant: true,
phenomenon,
qualifier }).to_string_full(options);
let [, sky] = info.get_value_sky();
return GWeather.Sky.to_string_full(sky, options);
},
_sameSummary(info1, info2) {
let [ok1, phenom1, qualifier1] = info1.get_value_conditions();
let [ok2, phenom2, qualifier2] = info2.get_value_conditions();
if (ok1 || ok2)
return ok1 == ok2 && phenom1 == phenom2 && qualifier1 == qualifier2;
let [, sky1] = info1.get_value_sky();
let [, sky2] = info2.get_value_sky();
return sky1 == sky2;
},
_getSummaryText() {
_getInfos() {
let info = this._weatherClient.info;
let forecasts = info.get_forecast_list();
if (forecasts.length == 0) // No forecasts, just current conditions
return '%s.'.format(this._getSummary(info, true));
let current = info;
let infos = [info];
for (let i = 0; i < forecasts.length; i++) {
let [ok, timestamp] = forecasts[i].get_value_update();
if (!_isToday(new Date(timestamp * 1000)))
let datetime = new Date(timestamp * 1000);
if (!_isToday(datetime))
continue; // Ignore forecasts from other days
if (this._sameSummary(current, forecasts[i]))
continue; // Ignore consecutive runs of equal summaries
[ok, timestamp] = current.get_value_update();
let currenttime = new Date(timestamp * 1000);
if (currenttime.getHours() == datetime.getHours())
continue; // Enforce a minimum interval of 1h
current = forecasts[i];
if (infos.push(current) == 3)
break; // Use a maximum of three summaries
if (infos.push(current) == MAX_FORECASTS)
break; // Use a maximum of five forecasts
}
return infos;
}
let fmt;
switch(infos.length) {
/* Translators: %s is a weather condition like "Clear sky"; see
libgweather for the possible condition strings. If at all
possible, the sentence should match the grammatical case etc. of
the inserted conditions. */
case 1: fmt = _("%s all day."); break;
_addForecasts() {
let layout = this._forecastGrid.layout_manager;
/* Translators: %s is a weather condition like "Clear sky"; see
libgweather for the possible condition strings. If at all
possible, the sentence should match the grammatical case etc. of
the inserted conditions. */
case 2: fmt = _("%s, then %s later."); break;
let infos = this._getInfos();
if (this._forecastGrid.text_direction == Clutter.TextDirection.RTL)
infos.reverse();
/* Translators: %s is a weather condition like "Clear sky"; see
libgweather for the possible condition strings. If at all
possible, the sentence should match the grammatical case etc. of
the inserted conditions. */
case 3: fmt = _("%s, then %s, followed by %s later."); break;
}
let summaries = infos.map((info, i) => {
let capitalize = i == 0 && fmt.startsWith('%s');
return this._getSummary(info, capitalize);
let col = 0;
infos.forEach(fc => {
let [ok, timestamp] = fc.get_value_update();
let timeStr = Util.formatTime(new Date(timestamp * 1000), {
timeOnly: true
});
let icon = new St.Icon({ style_class: 'weather-forecast-icon',
icon_name: fc.get_symbolic_icon_name(),
x_align: Clutter.ActorAlign.CENTER,
x_expand: true });
let temp = new St.Label({ style_class: 'weather-forecast-temp',
text: fc.get_temp_summary(),
x_align: Clutter.ActorAlign.CENTER });
let time = new St.Label({ style_class: 'weather-forecast-time',
text: timeStr,
x_align: Clutter.ActorAlign.CENTER });
layout.attach(icon, col, 0, 1, 1);
layout.attach(temp, col, 1, 1, 1);
layout.attach(time, col, 2, 1, 1);
col++;
});
return String.prototype.format.apply(fmt, summaries);
},
}
_getLabelText() {
if (!this._weatherClient.hasLocation)
return _("Select a location…");
_setStatusLabel(text) {
let layout = this._forecastGrid.layout_manager;
let label = new St.Label({ text });
layout.attach(label, 0, 0, 1, 1);
}
if (this._weatherClient.loading)
return _("Loading…");
_updateForecasts() {
this._forecastGrid.destroy_all_children();
if (!this._weatherClient.hasLocation) {
this._setStatusLabel(_("Select a location…"));
return;
}
let info = this._weatherClient.info;
if (info.is_valid())
return this._getSummaryText() + ' ' +
/* Translators: %s is a temperature with unit, e.g. "23℃" */
_("Feels like %s.").format(info.get_apparent());
this._titleLocation.text = info.get_location().get_name();
if (this._weatherClient.loading) {
this._setStatusLabel(_("Loading…"));
return;
}
if (info.is_valid()) {
this._addForecasts();
return;
}
if (info.network_error())
return _("Go online for weather information");
return _("Weather information is currently unavailable");
},
this._setStatusLabel(_("Go online for weather information"));
else
this._setStatusLabel(_("Weather information is currently unavailable"));
}
_sync() {
this.actor.visible = this._weatherClient.available;
@ -336,14 +337,14 @@ var WeatherSection = new Lang.Class({
if (!this.actor.visible)
return;
this._conditionsLabel.text = this._getLabelText();
this._titleLocation.visible = this._weatherClient.hasLocation;
this._updateForecasts();
}
});
};
var MessagesIndicator = new Lang.Class({
Name: 'MessagesIndicator',
_init() {
var MessagesIndicator = class MessagesIndicator {
constructor() {
this.actor = new St.Icon({ icon_name: 'message-indicator-symbolic',
icon_size: 16,
visible: false, y_expand: true,
@ -357,18 +358,18 @@ var MessagesIndicator = new Lang.Class({
let sources = Main.messageTray.getSources();
sources.forEach(source => { this._onSourceAdded(null, source); });
},
}
_onSourceAdded(tray, source) {
source.connect('count-updated', this._updateCount.bind(this));
this._sources.push(source);
this._updateCount();
},
}
_onSourceRemoved(tray, source) {
this._sources.splice(this._sources.indexOf(source), 1);
this._updateCount();
},
}
_updateCount() {
let count = 0;
@ -377,42 +378,39 @@ var MessagesIndicator = new Lang.Class({
this.actor.visible = (count > 0);
}
});
var IndicatorPad = new Lang.Class({
Name: 'IndicatorPad',
Extends: St.Widget,
};
var IndicatorPad = GObject.registerClass(
class IndicatorPad extends St.Widget {
_init(actor) {
this._source = actor;
this._source.connect('notify::visible', () => { this.queue_relayout(); });
this.parent();
},
this._source.connect('notify::size', () => { this.queue_relayout(); });
super._init();
}
vfunc_get_preferred_width(container, forHeight) {
vfunc_get_preferred_width(forHeight) {
if (this._source.visible)
return this._source.get_preferred_width(forHeight);
return [0, 0];
},
}
vfunc_get_preferred_height(container, forWidth) {
vfunc_get_preferred_height(forWidth) {
if (this._source.visible)
return this._source.get_preferred_height(forWidth);
return [0, 0];
}
});
var FreezableBinLayout = new Lang.Class({
Name: 'FreezableBinLayout',
Extends: Clutter.BinLayout,
var FreezableBinLayout = GObject.registerClass(
class FreezableBinLayout extends Clutter.BinLayout {
_init() {
this.parent();
super._init();
this._frozen = false;
this._savedWidth = [NaN, NaN];
this._savedHeight = [NaN, NaN];
},
}
set frozen(v) {
if (this._frozen == v)
@ -421,22 +419,22 @@ var FreezableBinLayout = new Lang.Class({
this._frozen = v;
if (!this._frozen)
this.layout_changed();
},
}
vfunc_get_preferred_width(container, forHeight) {
if (!this._frozen || this._savedWidth.some(isNaN))
return this.parent(container, forHeight);
return super.vfunc_get_preferred_width(container, forHeight);
return this._savedWidth;
},
}
vfunc_get_preferred_height(container, forWidth) {
if (!this._frozen || this._savedHeight.some(isNaN))
return this.parent(container, forWidth);
return super.vfunc_get_preferred_height(container, forWidth);
return this._savedHeight;
},
}
vfunc_allocate(container, allocation, flags) {
this.parent(container, allocation, flags);
super.vfunc_allocate(container, allocation, flags);
let [width, height] = allocation.get_size();
this._savedWidth = [width, width];
@ -444,26 +442,22 @@ var FreezableBinLayout = new Lang.Class({
}
});
var CalendarColumnLayout = new Lang.Class({
Name: 'CalendarColumnLayout',
Extends: Clutter.BoxLayout,
var CalendarColumnLayout = GObject.registerClass(
class CalendarColumnLayout extends Clutter.BoxLayout {
_init(actor) {
this.parent({ orientation: Clutter.Orientation.VERTICAL });
super._init({ orientation: Clutter.Orientation.VERTICAL });
this._calActor = actor;
},
}
vfunc_get_preferred_width(container, forHeight) {
if (!this._calActor || this._calActor.get_parent() != container)
return this.parent(container, forHeight);
return super.vfunc_get_preferred_width(container, forHeight);
return this._calActor.get_preferred_width(forHeight);
}
});
var DateMenuButton = new Lang.Class({
Name: 'DateMenuButton',
Extends: PanelMenu.Button,
var DateMenuButton = GObject.registerClass(
class DateMenuButton extends PanelMenu.Button {
_init() {
let item;
let hbox;
@ -472,7 +466,7 @@ var DateMenuButton = new Lang.Class({
let menuAlignment = 0.5;
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
menuAlignment = 1.0 - menuAlignment;
this.parent(menuAlignment);
super._init(menuAlignment);
this._clockDisplay = new St.Label({ y_align: Clutter.ActorAlign.CENTER });
this._indicator = new MessagesIndicator();
@ -532,7 +526,7 @@ var DateMenuButton = new Lang.Class({
this._displaysSection = new St.ScrollView({ style_class: 'datemenu-displays-section vfade',
x_expand: true, x_fill: true,
overlay_scrollbars: true });
this._displaysSection.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
this._displaysSection.set_policy(St.PolicyType.NEVER, St.PolicyType.AUTOMATIC);
vbox.add_actor(this._displaysSection);
let displaysBox = new St.BoxLayout({ vertical: true,
@ -553,11 +547,11 @@ var DateMenuButton = new Lang.Class({
Main.sessionMode.connect('updated', this._sessionUpdated.bind(this));
this._sessionUpdated();
},
}
_getEventSource() {
return new Calendar.DBusEventSource();
},
}
_setEventSource(eventSource) {
if (this._eventSource)
@ -567,7 +561,7 @@ var DateMenuButton = new Lang.Class({
this._messageList.setEventSource(eventSource);
this._eventSource = eventSource;
},
}
_updateTimeZone() {
// SpiderMonkey caches the time zone so we must explicitly clear it
@ -576,7 +570,7 @@ var DateMenuButton = new Lang.Class({
System.clearDateCaches();
this._calendar.updateTimeZone();
},
}
_sessionUpdated() {
let eventSource;

View File

@ -1,18 +1,11 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const GObject = imports.gi.GObject;
const Pango = imports.gi.Pango;
const St = imports.gi.St;
const Lang = imports.lang;
var Dialog = new Lang.Class({
Name: 'Dialog',
Extends: St.Widget,
const { Clutter, Gio, GObject, Pango, St } = imports.gi;
var Dialog = GObject.registerClass(
class Dialog extends St.Widget {
_init(parentActor, styleClass) {
this.parent({ layout_manager: new Clutter.BinLayout() });
super._init({ layout_manager: new Clutter.BinLayout() });
this.connect('destroy', this._onDestroy.bind(this));
this._initialKeyFocus = null;
@ -28,7 +21,7 @@ var Dialog = new Lang.Class({
this._parentActor = parentActor;
this._eventId = this._parentActor.connect('event', this._modalEventHandler.bind(this));
this._parentActor.add_child(this);
},
}
_createDialog() {
this._dialog = new St.BoxLayout({ style_class: 'modal-dialog',
@ -55,13 +48,13 @@ var Dialog = new Lang.Class({
this._dialog.add(this.buttonLayout,
{ x_align: St.Align.MIDDLE,
y_align: St.Align.START });
},
}
_onDestroy() {
if (this._eventId != 0)
this._parentActor.disconnect(this._eventId);
this._eventId = 0;
},
}
_modalEventHandler(actor, event) {
if (event.type() == Clutter.EventType.KEY_PRESS) {
@ -87,7 +80,7 @@ var Dialog = new Lang.Class({
}
return Clutter.EVENT_PROPAGATE;
},
}
_setInitialKeyFocus(actor) {
if (this._initialKeyFocus)
@ -99,15 +92,15 @@ var Dialog = new Lang.Class({
this._initialKeyFocus = null;
this._initialKeyFocusDestroyId = 0;
});
},
}
get initialKeyFocus() {
return this._initialKeyFocus || this;
},
}
addContent(actor) {
this.contentLayout.add (actor, { expand: true });
},
}
addButton(buttonInfo) {
let { label, action, key } = buttonInfo;
@ -144,17 +137,15 @@ var Dialog = new Lang.Class({
this.buttonLayout.add_actor(button);
return button;
},
}
clearButtons() {
this.buttonLayout.destroy_all_children();
this._buttonKeys = {};
},
}
});
var MessageDialogContent = new Lang.Class({
Name: 'MessageDialogContent',
Extends: St.BoxLayout,
var MessageDialogContent = GObject.registerClass({
Properties: {
'icon': GObject.ParamSpec.object('icon', 'icon', 'icon',
GObject.ParamFlags.READWRITE |
@ -172,8 +163,8 @@ var MessageDialogContent = new Lang.Class({
GObject.ParamFlags.READWRITE |
GObject.ParamFlags.CONSTRUCT,
null)
},
}
}, class MessageDialogContent extends St.BoxLayout {
_init(params) {
this._icon = new St.Icon({ y_align: Clutter.ActorAlign.START });
this._title = new St.Label({ style_class: 'headline' });
@ -192,7 +183,7 @@ var MessageDialogContent = new Lang.Class({
if (!params.hasOwnProperty('style_class'))
params.style_class = 'message-dialog-main-layout';
this.parent(params);
super._init(params);
this.messageBox = new St.BoxLayout({ style_class: 'message-dialog-content',
x_expand: true,
@ -204,45 +195,45 @@ var MessageDialogContent = new Lang.Class({
this.add_actor(this._icon);
this.add_actor(this.messageBox);
},
}
get icon() {
return this._icon.gicon;
},
}
get title() {
return this._title.text;
},
}
get subtitle() {
return this._subtitle.text;
},
}
get body() {
return this._body.text;
},
}
set icon(icon) {
Object.assign(this._icon, { gicon: icon, visible: icon != null });
this.notify('icon');
},
}
set title(title) {
this._setLabel(this._title, 'title', title);
},
}
set subtitle(subtitle) {
this._setLabel(this._subtitle, 'subtitle', subtitle);
},
}
set body(body) {
this._setLabel(this._body, 'body', body);
},
}
_setLabel(label, prop, value) {
Object.assign(label, { text: value || '', visible: value != null });
this.notify(prop);
},
}
insertBeforeBody(actor) {
this.messageBox.insert_child_below(actor, this._body);

View File

@ -1,17 +1,11 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const GLib = imports.gi.GLib;
const Gtk = imports.gi.Gtk;
const St = imports.gi.St;
const Lang = imports.lang;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const { Clutter, GLib, Meta, Shell, St } = imports.gi;
const Signals = imports.signals;
const Tweener = imports.ui.tweener;
const Main = imports.ui.main;
const Main = imports.ui.main;
const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
// Time to scale down to maxDragActorSize
var SCALE_ANIMATION_TIME = 0.25;
@ -74,10 +68,8 @@ function removeDragMonitor(monitor) {
}
}
var _Draggable = new Lang.Class({
Name: 'Draggable',
_init(actor, params) {
var _Draggable = class _Draggable {
constructor(actor, params) {
params = Params.parse(params, { manualMode: false,
restoreOnSuccess: false,
dragActorMaxSize: undefined,
@ -112,7 +104,8 @@ var _Draggable = new Lang.Class({
this._dragCancellable = true;
this._eventsGrabbed = false;
},
this._capturedEventId = 0;
}
_onButtonPress(actor, event) {
if (event.get_button() != 1)
@ -122,16 +115,26 @@ var _Draggable = new Lang.Class({
return Clutter.EVENT_PROPAGATE;
this._buttonDown = true;
this._grabActor();
this._grabActor(event.get_device());
let [stageX, stageY] = event.get_coords();
this._dragStartX = stageX;
this._dragStartY = stageY;
return Clutter.EVENT_PROPAGATE;
},
}
_onTouchEvent(actor, event) {
// We only handle touch events here on wayland. On X11
// we do get emulated pointer events, which already works
// for single-touch cases. Besides, the X11 passive touch grab
// set up by Mutter will make us see first the touch events
// and later the pointer events, so it will look like two
// unrelated series of events, we want to avoid double handling
// in these cases.
if (!Meta.is_wayland_compositor())
return Clutter.EVENT_PROPAGATE;
if (event.type() != Clutter.EventType.TOUCH_BEGIN ||
!global.display.is_pointer_emulating_sequence(event.get_event_sequence()))
return Clutter.EVENT_PROPAGATE;
@ -139,31 +142,40 @@ var _Draggable = new Lang.Class({
if (Tweener.getTweenCount(actor))
return Clutter.EVENT_PROPAGATE;
this._touchSequence = event.get_event_sequence();
this._buttonDown = true;
this._grabActor();
this._grabActor(event.get_device(), event.get_event_sequence());
let [stageX, stageY] = event.get_coords();
this._dragStartX = stageX;
this._dragStartY = stageY;
return Clutter.EVENT_PROPAGATE;
},
}
_grabDevice(actor) {
let manager = Clutter.DeviceManager.get_default();
let pointer = manager.get_core_device(Clutter.InputDeviceType.POINTER_DEVICE);
if (pointer && this._touchSequence)
pointer.sequence_grab(this._touchSequence, actor);
_grabDevice(actor, pointer, touchSequence) {
if (touchSequence)
pointer.sequence_grab(touchSequence, actor);
else if (pointer)
pointer.grab (actor);
this._grabbedDevice = pointer;
},
this._touchSequence = touchSequence;
this._capturedEventId = global.stage.connect('captured-event', (actor, event) => {
let device = event.get_device();
if (device != this._grabbedDevice &&
device.get_device_type() != Clutter.InputDeviceType.KEYBOARD_DEVICE)
return Clutter.EVENT_STOP;
return Clutter.EVENT_PROPAGATE;
});
}
_ungrabDevice() {
if (this._capturedEventId != 0) {
global.stage.disconnect(this._capturedEventId);
this._capturedEventId = 0;
}
if (this._touchSequence)
this._grabbedDevice.sequence_ungrab (this._touchSequence);
else
@ -171,13 +183,13 @@ var _Draggable = new Lang.Class({
this._touchSequence = null;
this._grabbedDevice = null;
},
}
_grabActor() {
this._grabDevice(this.actor);
_grabActor(device, touchSequence) {
this._grabDevice(this.actor, device, touchSequence);
this._onEventId = this.actor.connect('event',
this._onEvent.bind(this));
},
}
_ungrabActor() {
if (!this._onEventId)
@ -186,15 +198,15 @@ var _Draggable = new Lang.Class({
this._ungrabDevice();
this.actor.disconnect(this._onEventId);
this._onEventId = null;
},
}
_grabEvents() {
_grabEvents(device, touchSequence) {
if (!this._eventsGrabbed) {
this._eventsGrabbed = Main.pushModal(_getEventHandlerActor());
if (this._eventsGrabbed)
this._grabDevice(_getEventHandlerActor());
this._grabDevice(_getEventHandlerActor(), device, touchSequence);
}
},
}
_ungrabEvents() {
if (this._eventsGrabbed) {
@ -202,16 +214,38 @@ var _Draggable = new Lang.Class({
Main.popModal(_getEventHandlerActor());
this._eventsGrabbed = false;
}
},
}
_eventIsRelease(event) {
if (event.type() == Clutter.EventType.BUTTON_RELEASE) {
let buttonMask = (Clutter.ModifierType.BUTTON1_MASK |
Clutter.ModifierType.BUTTON2_MASK |
Clutter.ModifierType.BUTTON3_MASK);
/* We only obey the last button release from the device,
* other buttons may get pressed/released during the DnD op.
*/
return (event.get_state() & buttonMask) == 0;
} else if (event.type() == Clutter.EventType.TOUCH_END) {
/* For touch, we only obey the pointer emulating sequence */
return global.display.is_pointer_emulating_sequence(event.get_event_sequence());
}
return false;
}
_onEvent(actor, event) {
let device = event.get_device();
if (this._grabbedDevice &&
device != this._grabbedDevice &&
device.get_device_type() != Clutter.InputDeviceType.KEYBOARD_DEVICE)
return Clutter.EVENT_PROPAGATE;
// We intercept BUTTON_RELEASE event to know that the button was released in case we
// didn't start the drag, to drop the draggable in case the drag was in progress, and
// to complete the drag and ensure that whatever happens to be under the pointer does
// not get triggered if the drag was cancelled with Esc.
if (event.type() == Clutter.EventType.BUTTON_RELEASE ||
(event.type() == Clutter.EventType.TOUCH_END &&
global.display.is_pointer_emulating_sequence(event.get_event_sequence()))) {
if (this._eventIsRelease(event)) {
this._buttonDown = false;
if (this._dragState == DragState.DRAGGING) {
return this._dragActorDropped(event);
@ -246,7 +280,7 @@ var _Draggable = new Lang.Class({
}
return Clutter.EVENT_PROPAGATE;
},
}
/**
* fakeRelease:
@ -259,7 +293,7 @@ var _Draggable = new Lang.Class({
fakeRelease() {
this._buttonDown = false;
this._ungrabActor();
},
}
/**
* startDrag:
@ -271,7 +305,22 @@ var _Draggable = new Lang.Class({
* This function is useful to call if you've specified manualMode
* for the draggable.
*/
startDrag(stageX, stageY, time, sequence) {
startDrag(stageX, stageY, time, sequence, device) {
if (currentDraggable)
return;
if (device == undefined) {
let event = Clutter.get_current_event();
if (event)
device = event.get_device();
if (device == undefined) {
let manager = Clutter.DeviceManager.get_default();
device = manager.get_core_device(Clutter.InputDeviceType.POINTER_DEVICE);
}
}
currentDraggable = this;
this._dragState = DragState.DRAGGING;
@ -286,8 +335,7 @@ var _Draggable = new Lang.Class({
if (this._onEventId)
this._ungrabActor();
this._touchSequence = sequence;
this._grabEvents();
this._grabEvents(device, sequence);
global.display.set_cursor(Meta.Cursor.DND_IN_DRAG);
this._dragX = this._dragStartX = stageX;
@ -355,7 +403,8 @@ var _Draggable = new Lang.Class({
this._finishAnimation();
this._dragActor = null;
this._dragState = DragState.CANCELLED;
if (this._dragState == DragState.DRAGGING)
this._dragState = DragState.CANCELLED;
});
this._dragOrigOpacity = this._dragActor.opacity;
if (this._dragActorOpacity != undefined)
@ -395,26 +444,28 @@ var _Draggable = new Lang.Class({
onUpdateScope: this });
}
}
},
}
_maybeStartDrag(event) {
let [stageX, stageY] = event.get_coords();
// See if the user has moved the mouse enough to trigger a drag
let threshold = Gtk.Settings.get_default().gtk_dnd_drag_threshold;
if ((Math.abs(stageX - this._dragStartX) > threshold ||
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
let threshold = St.Settings.get().drag_threshold * scaleFactor;
if (!currentDraggable &&
(Math.abs(stageX - this._dragStartX) > threshold ||
Math.abs(stageY - this._dragStartY) > threshold)) {
this.startDrag(stageX, stageY, event.get_time(), this._touchSequence);
this.startDrag(stageX, stageY, event.get_time(), this._touchSequence, event.get_device());
this._updateDragPosition(event);
}
return true;
},
}
_pickTargetActor() {
return this._dragActor.get_stage().get_actor_at_pos(Clutter.PickMode.ALL,
this._dragX, this._dragY);
},
}
_updateDragHover() {
this._updateHoverId = 0;
@ -471,7 +522,7 @@ var _Draggable = new Lang.Class({
}
global.display.set_cursor(Meta.Cursor.DND_IN_DRAG);
return GLib.SOURCE_REMOVE;
},
}
_queueUpdateDragHover() {
if (this._updateHoverId)
@ -480,7 +531,7 @@ var _Draggable = new Lang.Class({
this._updateHoverId = GLib.idle_add(GLib.PRIORITY_DEFAULT,
this._updateDragHover.bind(this));
GLib.Source.set_name_by_id(this._updateHoverId, '[gnome-shell] this._updateDragHover');
},
}
_updateDragPosition(event) {
let [stageX, stageY] = event.get_coords();
@ -491,7 +542,7 @@ var _Draggable = new Lang.Class({
this._queueUpdateDragHover();
return true;
},
}
_dragActorDropped(event) {
let [dropX, dropY] = event.get_coords();
@ -554,7 +605,7 @@ var _Draggable = new Lang.Class({
this._cancelDrag(event.get_time());
return true;
},
}
_getRestoreLocation() {
let x, y, scale;
@ -586,7 +637,7 @@ var _Draggable = new Lang.Class({
}
return [x, y, scale];
},
}
_cancelDrag(eventTime) {
this.emit('drag-cancelled', eventTime);
@ -613,7 +664,7 @@ var _Draggable = new Lang.Class({
scale_y: snapBackScale,
time: SNAP_BACK_ANIMATION_TIME,
});
},
}
_restoreDragActor(eventTime) {
this._dragState = DragState.INIT;
@ -626,7 +677,7 @@ var _Draggable = new Lang.Class({
this._animateDragEnd(eventTime,
{ time: REVERT_ANIMATION_TIME });
},
}
_animateDragEnd(eventTime, params) {
this._animationInProgress = true;
@ -639,7 +690,7 @@ var _Draggable = new Lang.Class({
// start the animation
Tweener.addTween(this._dragActor, params)
},
}
_finishAnimation() {
if (!this._animationInProgress)
@ -650,7 +701,7 @@ var _Draggable = new Lang.Class({
this._dragComplete();
global.display.set_cursor(Meta.Cursor.DEFAULT);
},
}
_onAnimationComplete(dragActor, eventTime) {
if (this._dragOrigParent) {
@ -664,7 +715,7 @@ var _Draggable = new Lang.Class({
this.emit('drag-end', eventTime, false);
this._finishAnimation();
},
}
_dragComplete() {
if (!this._actorDestroyed && this._dragActor)
@ -686,8 +737,7 @@ var _Draggable = new Lang.Class({
this._dragState = DragState.INIT;
currentDraggable = null;
}
});
};
Signals.addSignalMethods(_Draggable.prototype);
/**

View File

@ -1,38 +1,32 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Lang = imports.lang;
const Signals = imports.signals;
const Meta = imports.gi.Meta;
const Clutter = imports.gi.Clutter;
const St = imports.gi.St;
const { Clutter, GObject, Meta, St } = imports.gi;
const Main = imports.ui.main;
var EDGE_THRESHOLD = 20;
var DRAG_DISTANCE = 80;
var EdgeDragAction = new Lang.Class({
Name: 'EdgeDragAction',
Extends: Clutter.GestureAction,
var EdgeDragAction = GObject.registerClass({
Signals: { 'activated': {} },
}, class EdgeDragAction extends Clutter.GestureAction {
_init(side, allowedModes) {
this.parent();
super._init();
this._side = side;
this._allowedModes = allowedModes;
this.set_n_touch_points(1);
global.display.connect('grab-op-begin', () => { this.cancel(); });
},
}
_getMonitorRect(x, y) {
let rect = new Meta.Rectangle({ x: x - 1, y: y - 1, width: 1, height: 1 });
let monitorIndex = global.display.get_monitor_index_for_rect(rect);
return global.display.get_monitor_geometry(monitorIndex);
},
}
vfunc_gesture_prepare(action, actor) {
vfunc_gesture_prepare(actor) {
if (this.get_n_current_points() == 0)
return false;
@ -46,9 +40,9 @@ var EdgeDragAction = new Lang.Class({
(this._side == St.Side.RIGHT && x > monitorRect.x + monitorRect.width - EDGE_THRESHOLD) ||
(this._side == St.Side.TOP && y < monitorRect.y + EDGE_THRESHOLD) ||
(this._side == St.Side.BOTTOM && y > monitorRect.y + monitorRect.height - EDGE_THRESHOLD));
},
}
vfunc_gesture_progress(action, actor) {
vfunc_gesture_progress(actor) {
let [startX, startY] = this.get_press_coords(0);
let [x, y] = this.get_motion_coords(0);
let offsetX = Math.abs (x - startX);
@ -66,9 +60,9 @@ var EdgeDragAction = new Lang.Class({
}
return true;
},
}
vfunc_gesture_end(action, actor) {
vfunc_gesture_end(actor) {
let [startX, startY] = this.get_press_coords(0);
let [x, y] = this.get_motion_coords(0);
let monitorRect = this._getMonitorRect(startX, startY);

View File

@ -16,24 +16,15 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const AccountsService = imports.gi.AccountsService;
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Gtk = imports.gi.Gtk;
const Pango = imports.gi.Pango;
const Polkit = imports.gi.Polkit;
const St = imports.gi.St;
const Shell = imports.gi.Shell;
const { AccountsService, Clutter, Gio,
GLib, Pango, Polkit, Shell, St } = imports.gi;
const CheckBox = imports.ui.checkBox;
const GnomeSession = imports.misc.gnomeSession;
const LoginManager = imports.misc.loginManager;
const ModalDialog = imports.ui.modalDialog;
const Tweener = imports.ui.tweener;
const UserWidget = imports.ui.userWidget;
const { loadInterfaceXML } = imports.misc.fileUtils;
@ -235,13 +226,10 @@ function init() {
_endSessionDialog = new EndSessionDialog();
}
var EndSessionDialog = new Lang.Class({
Name: 'EndSessionDialog',
Extends: ModalDialog.ModalDialog,
_init() {
this.parent({ styleClass: 'end-session-dialog',
destroyOnClose: false });
var EndSessionDialog = class EndSessionDialog extends ModalDialog.ModalDialog {
constructor() {
super({ styleClass: 'end-session-dialog',
destroyOnClose: false });
this._loginManager = LoginManager.getLoginManager();
this._userManager = AccountsService.UserManager.get_default();
@ -324,7 +312,7 @@ var EndSessionDialog = new Lang.Class({
messageLayout.add(this._batteryWarning);
this._scrollView = new St.ScrollView({ style_class: 'end-session-dialog-list' });
this._scrollView.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
this._scrollView.set_policy(St.PolicyType.NEVER, St.PolicyType.AUTOMATIC);
this.contentLayout.add(this._scrollView,
{ x_fill: true,
y_fill: true });
@ -356,12 +344,12 @@ var EndSessionDialog = new Lang.Class({
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(EndSessionDialogIface, this);
this._dbusImpl.export(Gio.DBus.session, '/org/gnome/SessionManager/EndSessionDialog');
},
}
_onDestroy() {
this._user.disconnect(this._userLoadedId);
this._user.disconnect(this._userChangedId);
},
}
_sync() {
let open = (this.state == ModalDialog.State.OPENING || this.state == ModalDialog.State.OPENED);
@ -434,7 +422,7 @@ var EndSessionDialog = new Lang.Class({
this._scrollView.visible = hasApplications || hasSessions;
this._applicationHeader.visible = hasApplications;
this._sessionHeader.visible = hasSessions;
},
}
_updateButtons() {
let dialogContent = DialogContent[this._type];
@ -456,20 +444,20 @@ var EndSessionDialog = new Lang.Class({
}
this.setButtons(buttons);
},
}
close(skipSignal) {
this.parent();
super.close();
if (!skipSignal)
this._dbusImpl.emit_signal('Closed', null);
},
}
cancel() {
this._stopTimer();
this._dbusImpl.emit_signal('Canceled', null);
this.close();
},
}
_confirm(signal) {
let callback = () => {
@ -504,11 +492,11 @@ var EndSessionDialog = new Lang.Class({
} else {
this._triggerOfflineUpdateCancel(callback);
}
},
}
_onOpened() {
this._sync();
},
}
_triggerOfflineUpdateReboot(callback) {
this._pkOfflineProxy.TriggerRemote('reboot', (result, error) => {
@ -517,7 +505,7 @@ var EndSessionDialog = new Lang.Class({
callback();
});
},
}
_triggerOfflineUpdateShutdown(callback) {
this._pkOfflineProxy.TriggerRemote('power-off', (result, error) => {
@ -526,7 +514,7 @@ var EndSessionDialog = new Lang.Class({
callback();
});
},
}
_triggerOfflineUpdateCancel(callback) {
this._pkOfflineProxy.CancelRemote((result, error) => {
@ -535,7 +523,7 @@ var EndSessionDialog = new Lang.Class({
callback();
});
},
}
_startTimer() {
let startTime = GLib.get_monotonic_time();
@ -559,7 +547,7 @@ var EndSessionDialog = new Lang.Class({
return GLib.SOURCE_REMOVE;
});
GLib.Source.set_name_by_id(this._timerId, '[gnome-shell] this._confirm');
},
}
_stopTimer() {
if (this._timerId > 0) {
@ -568,7 +556,7 @@ var EndSessionDialog = new Lang.Class({
}
this._secondsLeft = 0;
},
}
_constructListItemForApp(inhibitor, app) {
let actor = new St.BoxLayout({ style_class: 'end-session-dialog-app-list-item',
@ -593,7 +581,7 @@ var EndSessionDialog = new Lang.Class({
}
return actor;
},
}
_onInhibitorLoaded(inhibitor) {
if (this._applications.indexOf(inhibitor) < 0) {
@ -612,7 +600,7 @@ var EndSessionDialog = new Lang.Class({
}
this._sync();
},
}
_constructListItemForSession(session) {
let avatar = new UserWidget.Avatar(session.user, { iconSize: _ITEM_ICON_SIZE });
@ -642,7 +630,7 @@ var EndSessionDialog = new Lang.Class({
actor.label_actor = nameLabel;
return actor;
},
}
_loadSessions() {
this._loginManager.listSessions(result => {
@ -684,7 +672,7 @@ var EndSessionDialog = new Lang.Class({
this._sync();
});
},
}
OpenAsync(parameters, invocation) {
let [type, timestamp, totalSecondsToStayOpen, inhibitorObjectPaths] = parameters;
@ -754,9 +742,9 @@ var EndSessionDialog = new Lang.Class({
invocation.return_value(null);
this.disconnect(signalId);
});
},
}
Close(parameters, invocation) {
this.close();
}
});
};

View File

@ -4,19 +4,13 @@ const Config = imports.misc.config;
imports.gi.versions.Clutter = Config.LIBMUTTER_API_VERSION;
imports.gi.versions.Gio = '2.0';
imports.gi.versions.Gdk = '3.0';
imports.gi.versions.GdkPixbuf = '2.0';
imports.gi.versions.Gtk = '3.0';
imports.gi.versions.TelepathyGLib = '0.12';
imports.gi.versions.TelepathyLogger = '0.2';
const Clutter = imports.gi.Clutter;
const { Clutter, GLib, Shell, St } = imports.gi;
const Gettext = imports.gettext;
const GLib = imports.gi.GLib;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
// We can't import shell JS modules yet, because they may have
// variable initializations, etc, that depend on init() already having

View File

@ -1,13 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Lang = imports.lang;
const Clutter = imports.gi.Clutter;
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const Soup = imports.gi.Soup;
const St = imports.gi.St;
const Shell = imports.gi.Shell;
const { Clutter, Gio, GLib, Soup, St } = imports.gi;
const Config = imports.misc.config;
const ExtensionUtils = imports.misc.extensionUtils;
@ -183,12 +176,10 @@ function checkForUpdates() {
});
}
var InstallExtensionDialog = new Lang.Class({
Name: 'InstallExtensionDialog',
Extends: ModalDialog.ModalDialog,
_init(uuid, info, invocation) {
this.parent({ styleClass: 'extension-dialog' });
var InstallExtensionDialog =
class InstallExtensionDialog extends ModalDialog.ModalDialog {
constructor(uuid, info, invocation) {
super({ styleClass: 'extension-dialog' });
this._uuid = uuid;
this._info = info;
@ -216,12 +207,12 @@ var InstallExtensionDialog = new Lang.Class({
let label = new St.Label({ style_class: 'message-dialog-title headline',
text: message });
box.add(label);
},
}
_onCancelButtonPressed(button, event) {
this.close();
this._invocation.return_value(GLib.Variant.new('(s)', ['cancelled']));
},
}
_onInstallButtonPressed(button, event) {
let params = { shell_version: Config.PACKAGE_VERSION };
@ -264,7 +255,7 @@ var InstallExtensionDialog = new Lang.Class({
this.close();
}
});
};
function init() {
_httpSession = new Soup.SessionAsync({ ssl_use_system_ca_file: true });

View File

@ -1,12 +1,8 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Lang = imports.lang;
const { Gio, St } = imports.gi;
const Signals = imports.signals;
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const St = imports.gi.St;
const ExtensionUtils = imports.misc.extensionUtils;
const Main = imports.ui.main;

View File

@ -22,29 +22,26 @@
*/
const Atspi = imports.gi.Atspi;
const Lang = imports.lang;
const Signals = imports.signals;
const CARETMOVED = 'object:text-caret-moved';
const STATECHANGED = 'object:state-changed';
var FocusCaretTracker = new Lang.Class({
Name: 'FocusCaretTracker',
_init() {
var FocusCaretTracker = class FocusCaretTracker {
constructor() {
this._atspiListener = Atspi.EventListener.new(this._onChanged.bind(this));
this._atspiInited = false;
this._focusListenerRegistered = false;
this._caretListenerRegistered = false;
},
}
_onChanged(event) {
if (event.type.indexOf(STATECHANGED) == 0)
this.emit('focus-changed', event);
else if (event.type == CARETMOVED)
this.emit('caret-moved', event);
},
}
_initAtspi() {
if (!this._atspiInited && Atspi.init() == 0) {
@ -53,7 +50,7 @@ var FocusCaretTracker = new Lang.Class({
}
return this._atspiInited;
},
}
registerFocusListener() {
if (!this._initAtspi() || this._focusListenerRegistered)
@ -62,7 +59,7 @@ var FocusCaretTracker = new Lang.Class({
this._atspiListener.register(STATECHANGED + ':focused');
this._atspiListener.register(STATECHANGED + ':selected');
this._focusListenerRegistered = true;
},
}
registerCaretListener() {
if (!this._initAtspi() || this._caretListenerRegistered)
@ -70,7 +67,7 @@ var FocusCaretTracker = new Lang.Class({
this._atspiListener.register(CARETMOVED);
this._caretListenerRegistered = true;
},
}
deregisterFocusListener() {
if (!this._focusListenerRegistered)
@ -79,7 +76,7 @@ var FocusCaretTracker = new Lang.Class({
this._atspiListener.deregister(STATECHANGED + ':focused');
this._atspiListener.deregister(STATECHANGED + ':selected');
this._focusListenerRegistered = false;
},
}
deregisterCaretListener() {
if (!this._caretListenerRegistered)
@ -88,5 +85,5 @@ var FocusCaretTracker = new Lang.Class({
this._atspiListener.deregister(CARETMOVED);
this._caretListenerRegistered = false;
}
});
};
Signals.addSignalMethods(FocusCaretTracker.prototype);

View File

@ -1,11 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const { Clutter, St } = imports.gi;
const Main = imports.ui.main;
const Params = imports.misc.params;
@ -46,10 +41,8 @@ function _popGrabHelper(grabHelper) {
// your code just needs to deal with it; you shouldn't adjust behavior directly
// after you call ungrab(), but instead pass an 'onUngrab' callback when you
// call grab().
var GrabHelper = new Lang.Class({
Name: 'GrabHelper',
_init(owner, params) {
var GrabHelper = class GrabHelper {
constructor(owner, params) {
this._owner = owner;
this._modalParams = params;
@ -59,7 +52,7 @@ var GrabHelper = new Lang.Class({
this._ignoreUntilRelease = false;
this._modalCount = 0;
},
}
// addActor:
// @actor: an actor
@ -71,7 +64,7 @@ var GrabHelper = new Lang.Class({
this.removeActor(actor);
});
this._actors.push(actor);
},
}
// removeActor:
// @actor: an actor
@ -86,7 +79,7 @@ var GrabHelper = new Lang.Class({
actor.disconnect(actor.__grabHelperDestroyId);
delete actor.__grabHelperDestroyId;
}
},
}
_isWithinGrabbedActor(actor) {
let currentActor = this.currentGrab.actor;
@ -98,19 +91,19 @@ var GrabHelper = new Lang.Class({
actor = actor.get_parent();
}
return false;
},
}
get currentGrab() {
return this._grabStack[this._grabStack.length - 1] || {};
},
}
get grabbed() {
return this._grabStack.length > 0;
},
}
get grabStack() {
return this._grabStack;
},
}
_findStackIndex(actor) {
if (!actor)
@ -121,7 +114,7 @@ var GrabHelper = new Lang.Class({
return i;
}
return -1;
},
}
_actorInGrabStack(actor) {
while (actor) {
@ -131,11 +124,11 @@ var GrabHelper = new Lang.Class({
actor = actor.get_parent();
}
return -1;
},
}
isActorGrabbed(actor) {
return this._findStackIndex(actor) >= 0;
},
}
// grab:
// @params: A bunch of parameters, see below
@ -190,12 +183,12 @@ var GrabHelper = new Lang.Class({
if (params.focus) {
params.focus.grab_key_focus();
} else if (newFocus && hadFocus) {
if (!newFocus.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false))
if (!newFocus.navigate_focus(null, St.DirectionType.TAB_FORWARD, false))
newFocus.grab_key_focus();
}
return true;
},
}
_takeModalGrab() {
let firstGrab = (this._modalCount == 0);
@ -208,7 +201,7 @@ var GrabHelper = new Lang.Class({
this._modalCount++;
return true;
},
}
_releaseModalGrab() {
this._modalCount--;
@ -221,7 +214,7 @@ var GrabHelper = new Lang.Class({
Main.popModal(this._owner);
global.sync_pointer();
},
}
// ignoreRelease:
//
@ -231,7 +224,7 @@ var GrabHelper = new Lang.Class({
// the next release event.
ignoreRelease() {
this._ignoreUntilRelease = true;
},
}
// ungrab:
// @params: The parameters for the grab; see below.
@ -274,7 +267,7 @@ var GrabHelper = new Lang.Class({
if (poppedGrab.savedFocus)
poppedGrab.savedFocus.grab_key_focus();
}
},
}
onCapturedEvent(event) {
let type = event.type();
@ -322,5 +315,5 @@ var GrabHelper = new Lang.Class({
}
return Clutter.EVENT_STOP;
},
});
}
};

View File

@ -1,10 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const IBus = imports.gi.IBus;
const Lang = imports.lang;
const { Clutter, IBus, St } = imports.gi;
const Signals = imports.signals;
const St = imports.gi.St;
const BoxPointer = imports.ui.boxpointer;
const Main = imports.ui.main;
@ -14,10 +11,8 @@ var MAX_CANDIDATES_PER_PAGE = 16;
var DEFAULT_INDEX_LABELS = [ '1', '2', '3', '4', '5', '6', '7', '8',
'9', '0', 'a', 'b', 'c', 'd', 'e', 'f' ];
var CandidateArea = new Lang.Class({
Name: 'CandidateArea',
_init() {
var CandidateArea = class CandidateArea {
constructor() {
this.actor = new St.BoxLayout({ vertical: true,
reactive: true,
visible: false });
@ -74,7 +69,7 @@ var CandidateArea = new Lang.Class({
this._orientation = -1;
this._cursorPosition = 0;
},
}
setOrientation(orientation) {
if (this._orientation == orientation)
@ -95,7 +90,7 @@ var CandidateArea = new Lang.Class({
this._previousButton.child.icon_name = 'go-up-symbolic';
this._nextButton.child.icon_name = 'go-down-symbolic';
}
},
}
setCandidates(indexes, candidates, cursorPosition, cursorVisible) {
for (let i = 0; i < MAX_CANDIDATES_PER_PAGE; ++i) {
@ -114,7 +109,7 @@ var CandidateArea = new Lang.Class({
this._cursorPosition = cursorPosition;
if (cursorVisible)
this._candidateBoxes[cursorPosition].add_style_pseudo_class('selected');
},
}
updateButtons(wrapsAround, page, nPages) {
if (nPages < 2) {
@ -124,14 +119,12 @@ var CandidateArea = new Lang.Class({
this._buttonBox.show();
this._previousButton.reactive = wrapsAround || page > 0;
this._nextButton.reactive = wrapsAround || page < nPages - 1;
},
});
}
};
Signals.addSignalMethods(CandidateArea.prototype);
var CandidatePopup = new Lang.Class({
Name: 'CandidatePopup',
_init() {
var CandidatePopup = class CandidatePopup {
constructor() {
this._boxPointer = new BoxPointer.BoxPointer(St.Side.TOP);
this._boxPointer.visible = false;
this._boxPointer.style_class = 'candidate-popup-boxpointer';
@ -171,7 +164,7 @@ var CandidatePopup = new Lang.Class({
});
this._panelService = null;
},
}
setPanelService(panelService) {
this._panelService = panelService;
@ -241,7 +234,7 @@ var CandidatePopup = new Lang.Class({
let indexes = [];
let indexLabel;
for (let i = 0; indexLabel = lookupTable.get_label(i); ++i)
for (let i = 0; (indexLabel = lookupTable.get_label(i)); ++i)
indexes.push(indexLabel.get_text());
Main.keyboard.resetSuggestions();
@ -275,13 +268,13 @@ var CandidatePopup = new Lang.Class({
this._boxPointer.close(BoxPointer.PopupAnimation.NONE);
Main.keyboard.resetSuggestions();
});
},
}
_setDummyCursorGeometry(x, y, w, h) {
Main.layoutManager.setDummyCursorGeometry(x, y, w, h);
if (this._boxPointer.actor.visible)
this._boxPointer.setPosition(Main.layoutManager.dummyCursor, 0);
},
}
_updateVisibility() {
let isVisible = (!Main.keyboard.visible &&
@ -296,12 +289,12 @@ var CandidatePopup = new Lang.Class({
} else {
this._boxPointer.close(BoxPointer.PopupAnimation.NONE);
}
},
}
_setTextAttributes(clutterText, ibusAttrList) {
let attr;
for (let i = 0; attr = ibusAttrList.get(i); ++i)
for (let i = 0; (attr = ibusAttrList.get(i)); ++i)
if (attr.get_attr_type() == IBus.AttrType.BACKGROUND)
clutterText.set_selection(attr.get_start_index(), attr.get_end_index());
}
});
};

View File

@ -1,13 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Gtk = imports.gi.Gtk;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const St = imports.gi.St;
const { Clutter, GObject, Meta, St } = imports.gi;
const Lang = imports.lang;
const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
const Main = imports.ui.main;
@ -34,10 +28,8 @@ var AnimationDirection = {
var APPICON_ANIMATION_OUT_SCALE = 3;
var APPICON_ANIMATION_OUT_TIME = 0.25;
var BaseIcon = new Lang.Class({
Name: 'BaseIcon',
Extends: St.Bin,
var BaseIcon = GObject.registerClass(
class BaseIcon extends St.Bin {
_init(label, params) {
params = Params.parse(params, { createIcon: null,
setSizeManually: false,
@ -47,7 +39,7 @@ var BaseIcon = new Lang.Class({
if (params.showLabel)
styleClass += ' overview-icon-with-label';
this.parent({ style_class: styleClass,
super._init({ style_class: styleClass,
x_fill: true,
y_fill: true });
@ -79,18 +71,18 @@ var BaseIcon = new Lang.Class({
let cache = St.TextureCache.get_default();
this._iconThemeChangedId = cache.connect('icon-theme-changed', this._onIconThemeChanged.bind(this));
},
}
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
// parameter to _init()
createIcon(size) {
throw new Error('no implementation of createIcon in ' + this);
},
}
setIconSize(size) {
if (!this._setSizeManually)
@ -100,7 +92,7 @@ var BaseIcon = new Lang.Class({
return;
this._createIconTexture(size);
},
}
_createIconTexture(size) {
if (this.icon)
@ -109,9 +101,10 @@ var BaseIcon = new Lang.Class({
this.icon = this.createIcon(this.iconSize);
this._iconBin.child = this.icon;
},
}
vfunc_style_changed() {
super.vfunc_style_changed();
let node = this.get_theme_node();
let size;
@ -126,7 +119,7 @@ var BaseIcon = new Lang.Class({
return;
this._createIconTexture(size);
},
}
_onDestroy() {
if (this._iconThemeChangedId > 0) {
@ -134,11 +127,11 @@ var BaseIcon = new Lang.Class({
cache.disconnect(this._iconThemeChangedId);
this._iconThemeChangedId = 0;
}
},
}
_onIconThemeChanged() {
this._createIconTexture(this.iconSize);
},
}
animateZoomOut() {
// Animate only the child instead of the entire actor, so the
@ -187,14 +180,12 @@ function zoomOutActor(actor) {
});
}
var IconGrid = new Lang.Class({
Name: 'IconGrid',
Extends: St.Widget,
var IconGrid = GObject.registerClass({
Signals: {'animation-done': {},
'child-focused': { param_types: [Clutter.Actor.$gtype]} },
}, class IconGrid extends St.Widget {
_init(params) {
this.parent({ style_class: 'icon-grid',
super._init({ style_class: 'icon-grid',
y_align: Clutter.ActorAlign.START });
this.actor = this;
@ -236,19 +227,19 @@ var IconGrid = new Lang.Class({
this.connect('actor-added', this._childAdded.bind(this));
this.connect('actor-removed', this._childRemoved.bind(this));
},
}
_keyFocusIn(actor) {
this.emit('child-focused', actor);
},
}
_childAdded(grid, child) {
child._iconGridKeyFocusInId = child.connect('key-focus-in', this._keyFocusIn.bind(this));
},
}
_childRemoved(grid, child) {
child.disconnect(child._iconGridKeyFocusInId);
},
}
vfunc_get_preferred_width(forHeight) {
if (this._fillParent)
@ -268,11 +259,11 @@ var IconGrid = new Lang.Class({
let natSize = nColumns * this._getHItemSize() + totalSpacing + this.leftPadding + this.rightPadding;
return this.get_theme_node().adjust_preferred_width(minSize, natSize);
},
}
_getVisibleChildren() {
return this.get_children().filter(actor => actor.visible);
},
}
vfunc_get_preferred_height(forWidth) {
if (this._fillParent)
@ -302,7 +293,7 @@ var IconGrid = new Lang.Class({
let height = nRows * this._getVItemSize() + totalSpacing + this.topPadding + this.bottomPadding;
return themeNode.adjust_preferred_height(height, height);
},
}
vfunc_allocate(box, flags) {
this.set_allocation(box, flags);
@ -363,7 +354,7 @@ var IconGrid = new Lang.Class({
x += this._getHItemSize() + spacing;
}
}
},
}
vfunc_get_paint_volume(paintVolume) {
// Setting the paint volume does not make sense when we don't have
@ -402,7 +393,7 @@ var IconGrid = new Lang.Class({
}
return true;
},
}
/**
* Intended to be override by subclasses if they need a different
@ -410,12 +401,12 @@ var IconGrid = new Lang.Class({
*/
_getChildrenToAnimate() {
return this._getVisibleChildren();
},
}
_cancelAnimation() {
this._clonesAnimating.forEach(clone => { clone.destroy(); });
this._clonesAnimating = [];
},
}
_animationDone() {
this._clonesAnimating.forEach(clone => {
@ -425,7 +416,7 @@ var IconGrid = new Lang.Class({
});
this._clonesAnimating = [];
this.emit('animation-done');
},
}
animatePulse(animationDirection) {
if (animationDirection != AnimationDirection.IN)
@ -474,7 +465,7 @@ var IconGrid = new Lang.Class({
}
});
}
},
}
animateSpring(animationDirection, sourceActor) {
this._cancelAnimation();
@ -574,7 +565,7 @@ var IconGrid = new Lang.Class({
Tweener.addTween(actorClone, movementParams);
Tweener.addTween(actorClone, fadeParams);
}
},
}
_getAllocatedChildSizeAndSpacing(child) {
let [,, natWidth, natHeight] = child.get_preferred_size();
@ -583,7 +574,7 @@ var IconGrid = new Lang.Class({
let height = Math.min(this._getVItemSize(), natHeight);
let ySpacing = Math.max(0, height - natHeight) / 2;
return [width, height, xSpacing, ySpacing];
},
}
_calculateChildBox(child, x, y, box) {
/* Center the item in its allocation horizontally */
@ -601,15 +592,15 @@ var IconGrid = new Lang.Class({
childBox.x2 = childBox.x1 + width;
childBox.y2 = childBox.y1 + height;
return childBox;
},
}
columnsForWidth(rowWidth) {
return this._computeLayout(rowWidth)[0];
},
}
getRowLimit() {
return this._rowLimit;
},
}
_computeLayout(forWidth) {
let nColumns = 0;
@ -626,7 +617,7 @@ var IconGrid = new Lang.Class({
usedWidth -= spacing;
return [nColumns, usedWidth];
},
}
_onStyleChanged() {
let themeNode = this.get_theme_node();
@ -634,7 +625,7 @@ var IconGrid = new Lang.Class({
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.queue_relayout();
},
}
nRows(forWidth) {
let children = this._getVisibleChildren();
@ -643,38 +634,38 @@ var IconGrid = new Lang.Class({
if (this._rowLimit)
nRows = Math.min(nRows, this._rowLimit);
return nRows;
},
}
rowsForHeight(forHeight) {
return Math.floor((forHeight - (this.topPadding + this.bottomPadding) + this._getSpacing()) / (this._getVItemSize() + this._getSpacing()));
},
}
usedHeightForNRows(nRows) {
return (this._getVItemSize() + this._getSpacing()) * nRows - this._getSpacing() + this.topPadding + this.bottomPadding;
},
}
usedWidth(forWidth) {
return this.usedWidthForNColumns(this.columnsForWidth(forWidth));
},
}
usedWidthForNColumns(columns) {
let usedWidth = columns * (this._getHItemSize() + this._getSpacing());
usedWidth -= this._getSpacing();
return usedWidth + this.leftPadding + this.rightPadding;
},
}
removeAll() {
this._items = [];
this.remove_all_children();
},
}
destroyAll() {
this._items = [];
this.destroy_all_children();
},
}
addItem(item, index) {
if (!item.icon instanceof BaseIcon)
if (!(item.icon instanceof BaseIcon))
throw new Error('Only items with a BaseIcon icon property can be added to IconGrid');
this._items.push(item);
@ -682,35 +673,35 @@ var IconGrid = new Lang.Class({
this.insert_child_at_index(item.actor, index);
else
this.add_actor(item.actor);
},
}
removeItem(item) {
this.remove_child(item.actor);
},
}
getItemAtIndex(index) {
return this.get_child_at_index(index);
},
}
visibleItemsCount() {
return this.get_children().filter(c => c.is_visible()).length;
},
}
setSpacing(spacing) {
this._fixedSpacing = spacing;
},
}
_getSpacing() {
return this._fixedSpacing ? this._fixedSpacing : this._spacing;
},
}
_getHItemSize() {
return this._fixedHItemSize ? this._fixedHItemSize : this._hItemSize;
},
}
_getVItemSize() {
return this._fixedVItemSize ? this._fixedVItemSize : this._vItemSize;
},
}
_updateSpacingForSize(availWidth, availHeight) {
let maxEmptyVArea = availHeight - this._minRows * this._getVItemSize();
@ -743,7 +734,7 @@ var IconGrid = new Lang.Class({
this.setSpacing(spacing);
if (this._padWithSpacing)
this.topPadding = this.rightPadding = this.bottomPadding = this.leftPadding = spacing;
},
}
/**
* This function must to be called before iconGrid allocation,
@ -768,7 +759,7 @@ var IconGrid = new Lang.Class({
}
Meta.later_add(Meta.LaterType.BEFORE_REDRAW,
this._updateIconSizes.bind(this));
},
}
// Note that this is ICON_SIZE as used by BaseIcon, not elsewhere in IconGrid; it's a bit messed up
_updateIconSizes() {
@ -780,25 +771,23 @@ var IconGrid = new Lang.Class({
}
});
var PaginatedIconGrid = new Lang.Class({
Name: 'PaginatedIconGrid',
Extends: IconGrid,
var PaginatedIconGrid = GObject.registerClass({
Signals: {'space-opened': {},
'space-closed': {} },
}, class PaginatedIconGrid extends IconGrid {
_init(params) {
this.parent(params);
super._init(params);
this._nPages = 0;
this.currentPage = 0;
this._rowsPerPage = 0;
this._spaceBetweenPages = 0;
this._childrenPerPage = 0;
},
}
vfunc_get_preferred_height(forWidth) {
let height = (this._availableHeightPerPageForItems() + this.bottomPadding + this.topPadding) * this._nPages + this._spaceBetweenPages * this._nPages;
return [height, height];
},
}
vfunc_allocate(box, flags) {
if (this._childrenPerPage == 0)
@ -853,7 +842,7 @@ var PaginatedIconGrid = new Lang.Class({
} else
x += this._getHItemSize() + spacing;
}
},
}
// Overriden from IconGrid
_getChildrenToAnimate() {
@ -862,7 +851,7 @@ var PaginatedIconGrid = new Lang.Class({
let lastIndex = firstIndex + this._childrenPerPage;
return children.slice(firstIndex, lastIndex);
},
}
_computePages(availWidthPerPage, availHeightPerPage) {
let [nColumns, usedWidth] = this._computeLayout(availWidthPerPage);
@ -881,24 +870,24 @@ var PaginatedIconGrid = new Lang.Class({
this._nPages = Math.ceil(nRows / this._rowsPerPage);
this._spaceBetweenPages = availHeightPerPage - (this.topPadding + this.bottomPadding) - this._availableHeightPerPageForItems();
this._childrenPerPage = nColumns * this._rowsPerPage;
},
}
adaptToSize(availWidth, availHeight) {
this.parent(availWidth, availHeight);
super.adaptToSize(availWidth, availHeight);
this._computePages(availWidth, availHeight);
},
}
_availableHeightPerPageForItems() {
return this.usedHeightForNRows(this._rowsPerPage) - (this.topPadding + this.bottomPadding);
},
}
nPages() {
return this._nPages;
},
}
getPageHeight() {
return this._availableHeightPerPageForItems();
},
}
getPageY(pageNumber) {
if (!this._nPages)
@ -907,17 +896,15 @@ var PaginatedIconGrid = new Lang.Class({
let firstPageItem = pageNumber * this._childrenPerPage
let childBox = this._getVisibleChildren()[firstPageItem].get_allocation_box();
return childBox.y1 - this.topPadding;
},
}
getItemPage(item) {
let children = this._getVisibleChildren();
let index = children.indexOf(item);
if (index == -1) {
if (index == -1)
throw new Error('Item not found.');
return 0;
}
return Math.floor(index / this._childrenPerPage);
},
}
/**
* openExtraSpace:
@ -930,10 +917,9 @@ var PaginatedIconGrid = new Lang.Class({
openExtraSpace(sourceItem, side, nRows) {
let children = this._getVisibleChildren();
let index = children.indexOf(sourceItem.actor);
if (index == -1) {
if (index == -1)
throw new Error('Item not found.');
return;
}
let pageIndex = Math.floor(index / this._childrenPerPage);
let pageOffset = pageIndex * this._childrenPerPage;
@ -965,18 +951,18 @@ var PaginatedIconGrid = new Lang.Class({
this._translatedChildren = [];
this.emit('space-opened');
} else {
this._translateChildren(childrenUp, Gtk.DirectionType.UP, nRowsUp);
this._translateChildren(childrenDown, Gtk.DirectionType.DOWN, nRowsDown);
this._translateChildren(childrenUp, St.DirectionType.UP, nRowsUp);
this._translateChildren(childrenDown, St.DirectionType.DOWN, nRowsDown);
this._translatedChildren = childrenUp.concat(childrenDown);
}
},
}
_translateChildren(children, direction, nRows) {
let translationY = nRows * (this._getVItemSize() + this._getSpacing());
if (translationY == 0)
return;
if (direction == Gtk.DirectionType.UP)
if (direction == St.DirectionType.UP)
translationY *= -1;
for (let i = 0; i < children.length; i++) {
@ -989,7 +975,7 @@ var PaginatedIconGrid = new Lang.Class({
params.onComplete = () => { this.emit('space-opened'); };
Tweener.addTween(children[i], params);
}
},
}
closeExtraSpace() {
if (!this._translatedChildren || !this._translatedChildren.length) {

View File

@ -1,56 +1,75 @@
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const { Clutter, Gio, GLib, GObject, Gtk, Meta, Shell } = imports.gi;
const Dialog = imports.ui.dialog;
const ModalDialog = imports.ui.modalDialog;
const PermissionStore = imports.misc.permissionStore;
const WAYLAND_KEYBINDINGS_SCHEMA = 'org.gnome.mutter.wayland.keybindings';
const APP_WHITELIST = ['gnome-control-center.desktop'];
const APP_PERMISSIONS_TABLE = 'gnome';
const APP_PERMISSIONS_ID = 'shortcuts-inhibitor';
const GRANTED = 'GRANTED';
const DENIED = 'DENIED';
var DialogResponse = Meta.InhibitShortcutsDialogResponse;
var InhibitShortcutsDialog = new Lang.Class({
Name: 'InhibitShortcutsDialog',
Extends: GObject.Object,
var InhibitShortcutsDialog = GObject.registerClass({
Implements: [Meta.InhibitShortcutsDialog],
Properties: {
'window': GObject.ParamSpec.override('window', Meta.InhibitShortcutsDialog)
},
}
}, class InhibitShortcutsDialog extends GObject.Object {
_init(window) {
this.parent();
super._init();
this._window = window;
this._dialog = new ModalDialog.ModalDialog();
this._buildLayout();
},
}
get window() {
return this._window;
},
}
set window(window) {
this._window = window;
},
}
get _app() {
let windowTracker = Shell.WindowTracker.get_default();
return windowTracker.get_window_app(this._window);
},
}
_getRestoreAccel() {
let settings = new Gio.Settings({ schema_id: WAYLAND_KEYBINDINGS_SCHEMA });
let accel = settings.get_strv('restore-shortcuts')[0] || '';
return Gtk.accelerator_get_label.apply(null,
Gtk.accelerator_parse(accel));
},
}
_shouldUsePermStore() {
return this._app && !this._app.is_window_backed();
}
_saveToPermissionStore(grant) {
if (!this._shouldUsePermStore() || this._permStore == null)
return;
let permissions = {};
permissions[this._app.get_id()] = [grant];
let data = GLib.Variant.new('av', {});
this._permStore.SetRemote(APP_PERMISSIONS_TABLE,
true,
APP_PERMISSIONS_ID,
permissions,
data,
(result, error) => {
if (error != null)
log(error.message);
});
}
_buildLayout() {
let name = this._app ? this._app.get_name() : this._window.title;
@ -73,28 +92,63 @@ var InhibitShortcutsDialog = new Lang.Class({
this._dialog.addButton({ label: _("Deny"),
action: () => {
this._saveToPermissionStore(DENIED);
this._emitResponse(DialogResponse.DENY);
},
key: Clutter.KEY_Escape });
this._dialog.addButton({ label: _("Allow"),
action: () => {
this._saveToPermissionStore(GRANTED);
this._emitResponse(DialogResponse.ALLOW);
},
default: true });
},
}
_emitResponse(response) {
this.emit('response', response);
this._dialog.close();
},
}
vfunc_show() {
if (this._app && APP_WHITELIST.indexOf(this._app.get_id()) != -1)
if (this._app && APP_WHITELIST.indexOf(this._app.get_id()) != -1) {
this._emitResponse(DialogResponse.ALLOW);
else
return;
}
if (!this._shouldUsePermStore()) {
this._dialog.open();
},
return;
}
/* Check with the permission store */
let appId = this._app.get_id();
this._permStore = new PermissionStore.PermissionStore((proxy, error) => {
if (error) {
log(error.message);
this._dialog.open();
return;
}
this._permStore.LookupRemote(APP_PERMISSIONS_TABLE,
APP_PERMISSIONS_ID,
(res, error) => {
if (error) {
this._dialog.open();
log(error.message);
return;
}
let [permissions, data] = res;
if (permissions[appId] === undefined) // Not found
this._dialog.open();
else if (permissions[appId] == GRANTED)
this._emitResponse(DialogResponse.ALLOW);
else
this._emitResponse(DialogResponse.DENY);
});
});
}
vfunc_hide() {
this._dialog.close();

View File

@ -1,7 +1,5 @@
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const GObject = imports.gi.GObject;
const Lang = imports.lang;
const { Clutter, Gio, GObject } = imports.gi;
const Dialog = imports.ui.dialog;
const ModalDialog = imports.ui.modalDialog;
@ -9,17 +7,17 @@ const KEYBOARD_A11Y_SCHEMA = 'org.gnome.desktop.a11y.keyboard';
const KEY_STICKY_KEYS_ENABLED = 'stickykeys-enable';
const KEY_SLOW_KEYS_ENABLED = 'slowkeys-enable';
var KbdA11yDialog = new Lang.Class({
Name: 'KbdA11yDialog',
Extends: GObject.Object,
var KbdA11yDialog = GObject.registerClass(
class KbdA11yDialog extends GObject.Object {
_init() {
super._init();
this._a11ySettings = new Gio.Settings({ schema_id: KEYBOARD_A11Y_SCHEMA });
let deviceManager = Clutter.DeviceManager.get_default();
deviceManager.connect('kbd-a11y-flags-changed',
this._showKbdA11yDialog.bind(this));
},
}
_showKbdA11yDialog(deviceManager, newFlags, whatChanged) {
let dialog = new ModalDialog.ModalDialog();

File diff suppressed because it is too large Load Diff

View File

@ -1,13 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Lang = imports.lang;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const { Clutter, GLib, GObject, Meta, Shell, St } = imports.gi;
const Signals = imports.signals;
const St = imports.gi.St;
const Background = imports.ui.background;
const BackgroundMenu = imports.ui.backgroundMenu;
@ -36,9 +30,7 @@ function isPopupMetaWindow(actor) {
}
}
var MonitorConstraint = new Lang.Class({
Name: 'MonitorConstraint',
Extends: Clutter.Constraint,
var MonitorConstraint = GObject.registerClass({
Properties: {'primary': GObject.ParamSpec.boolean('primary',
'Primary', 'Track primary monitor',
GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE,
@ -51,18 +43,18 @@ var MonitorConstraint = new Lang.Class({
'Work-area', 'Track monitor\'s work-area',
GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE,
false)},
}, class MonitorConstraint extends Clutter.Constraint {
_init(props) {
this._primary = false;
this._index = -1;
this._workArea = false;
this.parent(props);
},
super._init(props);
}
get primary() {
return this._primary;
},
}
set primary(v) {
if (v)
@ -71,11 +63,11 @@ var MonitorConstraint = new Lang.Class({
if (this.actor)
this.actor.queue_relayout();
this.notify('primary');
},
}
get index() {
return this._index;
},
}
set index(v) {
this._primary = false;
@ -83,11 +75,11 @@ var MonitorConstraint = new Lang.Class({
if (this.actor)
this.actor.queue_relayout();
this.notify('index');
},
}
get work_area() {
return this._workArea;
},
}
set work_area(v) {
if (v == this._workArea)
@ -96,7 +88,7 @@ var MonitorConstraint = new Lang.Class({
if (this.actor)
this.actor.queue_relayout();
this.notify('work-area');
},
}
vfunc_set_actor(actor) {
if (actor) {
@ -124,8 +116,8 @@ var MonitorConstraint = new Lang.Class({
this._workareasChangedId = 0;
}
this.parent(actor);
},
super.vfunc_set_actor(actor);
}
vfunc_update_allocation(actor, actorBox) {
if (!this._primary && this._index < 0)
@ -153,21 +145,33 @@ var MonitorConstraint = new Lang.Class({
}
});
var Monitor = new Lang.Class({
Name: 'Monitor',
_init(index, geometry) {
var Monitor = class Monitor {
constructor(index, geometry, geometry_scale) {
this.index = index;
this.x = geometry.x;
this.y = geometry.y;
this.width = geometry.width;
this.height = geometry.height;
},
this.geometry_scale = geometry_scale;
}
get inFullscreen() {
return global.display.get_monitor_in_fullscreen(this.index);
}
})
};
const UiActor = GObject.registerClass(
class UiActor extends St.Widget {
vfunc_get_preferred_width (forHeight) {
let width = global.stage.width;
return [width, width];
}
vfunc_get_preferred_height (forWidth) {
let height = global.stage.height;
return [height, height];
}
});
const defaultParams = {
trackFullscreen: false,
@ -175,17 +179,15 @@ const defaultParams = {
affectsInputRegion: true
};
var LayoutManager = new Lang.Class({
Name: 'LayoutManager',
Extends: GObject.Object,
var LayoutManager = GObject.registerClass({
Signals: { 'hot-corners-changed': {},
'startup-complete': {},
'startup-prepared': {},
'monitors-changed': {},
'keyboard-visible-changed': { param_types: [GObject.TYPE_BOOLEAN] } },
}, class LayoutManager extends GObject.Object {
_init() {
this.parent();
super._init();
this._rtl = (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL);
this.monitors = [];
@ -211,12 +213,8 @@ 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 St.Widget({ name: 'uiGroup' });
this.uiGroup = new UiActor({ name: 'uiGroup' });
this.uiGroup.set_flags(Clutter.ActorFlags.NO_LAYOUT);
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);
@ -254,7 +252,7 @@ var LayoutManager = new Lang.Class({
// A dummy actor that tracks the mouse or text cursor, based on the
// position and size set in setDummyCursorGeometry.
this.dummyCursor = new St.Widget({ width: 0, height: 0, visible: false });
this.dummyCursor = new St.Widget({ width: 0, height: 0, opacity: 0 });
this.uiGroup.add_actor(this.dummyCursor);
global.stage.remove_actor(global.top_window_group);
@ -296,33 +294,33 @@ var LayoutManager = new Lang.Class({
Meta.Background.refresh_all();
});
}
},
}
// This is called by Main after everything else is constructed
init() {
Main.sessionMode.connect('updated', this._sessionUpdated.bind(this));
this._loadBackground();
},
}
showOverview() {
this.overviewGroup.show();
this._inOverview = true;
this._updateVisibility();
},
}
hideOverview() {
this.overviewGroup.hide();
this._inOverview = false;
this._updateVisibility();
},
}
_sessionUpdated() {
this._updateVisibility();
this._queueUpdateRegions();
},
}
_updateMonitors() {
let display = global.display;
@ -330,7 +328,9 @@ var LayoutManager = new Lang.Class({
this.monitors = [];
let nMonitors = display.get_n_monitors();
for (let i = 0; i < nMonitors; i++)
this.monitors.push(new Monitor(i, display.get_monitor_geometry(i)));
this.monitors.push(new Monitor(i,
display.get_monitor_geometry(i),
display.get_monitor_scale(i)));
if (nMonitors == 0) {
this.primaryIndex = this.bottomIndex = -1;
@ -360,7 +360,7 @@ var LayoutManager = new Lang.Class({
this.primaryMonitor = null;
this.bottomMonitor = null;
}
},
}
_updateHotCorners() {
// destroy old hot corners
@ -419,11 +419,11 @@ var LayoutManager = new Lang.Class({
}
this.emit('hot-corners-changed');
},
}
_addBackgroundMenu(bgManager) {
BackgroundMenu.addBackgroundMenu(bgManager.backgroundActor, this);
},
}
_createBackgroundManager(monitorIndex) {
let bgManager = new Background.BackgroundManager({ container: this._backgroundGroup,
@ -434,7 +434,7 @@ var LayoutManager = new Lang.Class({
this._addBackgroundMenu(bgManager);
return bgManager;
},
}
_showSecondaryBackgrounds() {
for (let i = 0; i < this.monitors.length; i++) {
@ -448,7 +448,7 @@ var LayoutManager = new Lang.Class({
transition: 'easeOutQuad' });
}
}
},
}
_updateBackgrounds() {
let i;
@ -467,13 +467,13 @@ var LayoutManager = new Lang.Class({
if (i != this.primaryIndex && this._startingUp)
bgManager.backgroundActor.hide();
}
},
}
_updateKeyboardBox() {
this.keyboardBox.set_position(this.keyboardMonitor.x,
this.keyboardMonitor.y + this.keyboardMonitor.height);
this.keyboardBox.set_size(this.keyboardMonitor.width, -1);
},
}
_updateBoxes() {
this.screenShieldGroup.set_position(0, 0);
@ -486,7 +486,7 @@ var LayoutManager = new Lang.Class({
this.panelBox.set_size(this.primaryMonitor.width, -1);
this.keyboardIndex = this.primaryIndex;
},
}
_panelBoxChanged() {
this._updatePanelBarrier();
@ -496,7 +496,7 @@ var LayoutManager = new Lang.Class({
if (corner)
corner.setBarrierSize(size);
});
},
}
_updatePanelBarrier() {
if (this._rightPanelBarrier) {
@ -515,7 +515,7 @@ var LayoutManager = new Lang.Class({
x2: primary.x + primary.width, y2: primary.y + this.panelBox.height,
directions: Meta.BarrierDirection.NEGATIVE_X });
}
},
}
_monitorsChanged() {
this._updateMonitors();
@ -527,7 +527,7 @@ var LayoutManager = new Lang.Class({
this._queueUpdateRegions();
this.emit('monitors-changed');
},
}
_isAboveOrBelowPrimary(monitor) {
let primary = this.monitors[this.primaryIndex];
@ -541,16 +541,16 @@ var LayoutManager = new Lang.Class({
return true;
return false;
},
}
get currentMonitor() {
let index = global.display.get_current_monitor();
return this.monitors[index];
},
}
get keyboardMonitor() {
return this.monitors[this.keyboardIndex];
},
}
get focusIndex() {
let i = Main.layoutManager.primaryIndex;
@ -560,22 +560,22 @@ var LayoutManager = new Lang.Class({
else if (global.display.focus_window != null)
i = global.display.focus_window.get_monitor();
return i;
},
}
get focusMonitor() {
if (this.focusIndex < 0)
return null;
return this.monitors[this.focusIndex];
},
}
set keyboardIndex(v) {
this._keyboardIndex = v;
this._updateKeyboardBox();
},
}
get keyboardIndex() {
return this._keyboardIndex;
},
}
_loadBackground() {
if (!this.primaryMonitor) {
@ -598,7 +598,7 @@ var LayoutManager = new Lang.Class({
this._prepareStartupAnimation();
});
},
}
// Startup Animations
//
@ -664,7 +664,7 @@ var LayoutManager = new Lang.Class({
return GLib.SOURCE_REMOVE;
});
GLib.Source.set_name_by_id(id, '[gnome-shell] this._startupAnimation');
},
}
_startupAnimation() {
if (Meta.is_restart())
@ -673,7 +673,7 @@ var LayoutManager = new Lang.Class({
this._startupAnimationGreeter();
else
this._startupAnimationSession();
},
}
_startupAnimationGreeter() {
Tweener.addTween(this.panelBox,
@ -682,7 +682,7 @@ var LayoutManager = new Lang.Class({
transition: 'easeOutQuad',
onComplete: this._startupAnimationComplete,
onCompleteScope: this });
},
}
_startupAnimationSession() {
Tweener.addTween(this.uiGroup,
@ -693,7 +693,7 @@ var LayoutManager = new Lang.Class({
transition: 'easeOutQuad',
onComplete: this._startupAnimationComplete,
onCompleteScope: this });
},
}
_startupAnimationComplete() {
this._coverPane.destroy();
@ -714,7 +714,7 @@ var LayoutManager = new Lang.Class({
this._queueUpdateRegions();
this.emit('startup-complete');
},
}
showKeyboard() {
this.keyboardBox.show();
@ -727,7 +727,7 @@ var LayoutManager = new Lang.Class({
onCompleteScope: this
});
this.emit('keyboard-visible-changed', true);
},
}
_showKeyboardComplete() {
// Poke Chrome to update the input shape; it doesn't notice
@ -737,7 +737,7 @@ var LayoutManager = new Lang.Class({
this._keyboardHeightNotifyId = this.keyboardBox.connect('notify::height', () => {
this.keyboardBox.anchor_y = this.keyboardBox.height;
});
},
}
hideKeyboard(immediate) {
if (this._keyboardHeightNotifyId) {
@ -754,12 +754,12 @@ var LayoutManager = new Lang.Class({
});
this.emit('keyboard-visible-changed', false);
},
}
_hideKeyboardComplete() {
this.keyboardBox.hide();
this._updateRegions();
},
}
// setDummyCursorGeometry:
//
@ -774,7 +774,7 @@ var LayoutManager = new Lang.Class({
setDummyCursorGeometry(x, y, w, h) {
this.dummyCursor.set_position(Math.round(x), Math.round(y));
this.dummyCursor.set_size(Math.round(w), Math.round(h));
},
}
// addChrome:
// @actor: an actor to add to the chrome
@ -800,7 +800,7 @@ var LayoutManager = new Lang.Class({
if (this.uiGroup.contains(global.top_window_group))
this.uiGroup.set_child_below_sibling(actor, global.top_window_group);
this._trackActor(actor, params);
},
}
// trackChrome:
// @actor: a descendant of the chrome to begin tracking
@ -832,7 +832,7 @@ var LayoutManager = new Lang.Class({
}
this._trackActor(actor, params);
},
}
// untrackChrome:
// @actor: an actor previously tracked via trackChrome()
@ -840,7 +840,7 @@ var LayoutManager = new Lang.Class({
// Undoes the effect of trackChrome()
untrackChrome(actor) {
this._untrackActor(actor);
},
}
// removeChrome:
// @actor: a chrome actor
@ -849,7 +849,7 @@ var LayoutManager = new Lang.Class({
removeChrome(actor) {
this.uiGroup.remove_actor(actor);
this._untrackActor(actor);
},
}
_findActor(actor) {
for (let i = 0; i < this._trackedActors.length; i++) {
@ -858,7 +858,7 @@ var LayoutManager = new Lang.Class({
return i;
}
return -1;
},
}
_trackActor(actor, params) {
if (this._findActor(actor) != -1)
@ -878,7 +878,7 @@ var LayoutManager = new Lang.Class({
this._trackedActors.push(actorData);
this._updateActorVisibility(actorData);
this._queueUpdateRegions();
},
}
_untrackActor(actor) {
let i = this._findActor(actor);
@ -893,7 +893,7 @@ var LayoutManager = new Lang.Class({
actor.disconnect(actorData.destroyId);
this._queueUpdateRegions();
},
}
_updateActorVisibility(actorData) {
if (!actorData.trackFullscreen)
@ -903,7 +903,7 @@ var LayoutManager = new Lang.Class({
actorData.actor.visible = !(global.window_group.visible &&
monitor &&
monitor.inFullscreen);
},
}
_updateVisibility() {
let windowsVisible = Main.sessionMode.hasWindows && !this._inOverview;
@ -912,7 +912,7 @@ var LayoutManager = new Lang.Class({
global.top_window_group.visible = windowsVisible;
this._trackedActors.forEach(this._updateActorVisibility.bind(this));
},
}
getWorkAreaForMonitor(monitorIndex) {
// Assume that all workspaces will have the same
@ -920,7 +920,7 @@ var LayoutManager = new Lang.Class({
let workspaceManager = global.workspace_manager;
let ws = workspaceManager.get_workspace_by_index(0);
return ws.get_work_area_for_monitor(monitorIndex);
},
}
// This call guarantees that we return some monitor to simplify usage of it
// In practice all tracked actors should be visible on some monitor anyway
@ -929,14 +929,14 @@ var LayoutManager = new Lang.Class({
let [w, h] = actor.get_transformed_size();
let rect = new Meta.Rectangle({ x: x, y: y, width: w, height: h });
return global.display.get_monitor_index_for_rect(rect);
},
}
findMonitorForActor(actor) {
let index = this.findIndexForActor(actor);
if (index >= 0 && index < this.monitors.length)
return this.monitors[index];
return null;
},
}
_queueUpdateRegions() {
if (this._startingUp)
@ -945,19 +945,19 @@ var LayoutManager = new Lang.Class({
if (!this._updateRegionIdle)
this._updateRegionIdle = Meta.later_add(Meta.LaterType.BEFORE_REDRAW,
this._updateRegions.bind(this));
},
}
_getWindowActorsForWorkspace(workspace) {
return global.get_window_actors().filter(actor => {
let win = actor.meta_window;
return win.located_on_workspace(workspace);
});
},
}
_updateFullscreen() {
this._updateVisibility();
this._queueUpdateRegions();
},
}
_windowsRestacked() {
let changed = false;
@ -969,7 +969,7 @@ var LayoutManager = new Lang.Class({
this._updateVisibility();
this._queueUpdateRegions();
}
},
}
_updateRegions() {
if (this._updateRegionIdle) {
@ -1069,13 +1069,13 @@ var LayoutManager = new Lang.Class({
}
return GLib.SOURCE_REMOVE;
},
}
modalEnded() {
// We don't update the stage input region while in a modal,
// so queue an update now.
this._queueUpdateRegions();
},
}
});
@ -1083,10 +1083,8 @@ var LayoutManager = new Lang.Class({
//
// This class manages a "hot corner" that can toggle switching to
// overview.
var HotCorner = new Lang.Class({
Name: 'HotCorner',
_init(layoutManager, monitor, x, y) {
var HotCorner = class HotCorner {
constructor(layoutManager, monitor, x, y) {
// We use this flag to mark the case where the user has entered the
// hot corner and has not left both the hot corner and a surrounding
// guard area (the "environs"). This avoids triggering the hot corner
@ -1114,7 +1112,7 @@ var HotCorner = new Lang.Class({
layoutManager.uiGroup.add_actor(this._ripple1);
layoutManager.uiGroup.add_actor(this._ripple2);
layoutManager.uiGroup.add_actor(this._ripple3);
},
}
setBarrierSize(size) {
if (this._verticalBarrier) {
@ -1149,7 +1147,7 @@ var HotCorner = new Lang.Class({
this._pressureBarrier.addBarrier(this._verticalBarrier);
this._pressureBarrier.addBarrier(this._horizontalBarrier);
}
},
}
_setupFallbackCornerIfNeeded(layoutManager) {
if (!global.display.supports_extended_barriers()) {
@ -1184,7 +1182,7 @@ var HotCorner = new Lang.Class({
this._corner.connect('leave-event',
this._onCornerLeft.bind(this));
}
},
}
destroy() {
this.setBarrierSize(0);
@ -1193,7 +1191,7 @@ var HotCorner = new Lang.Class({
if (this.actor)
this.actor.destroy();
},
}
_animRipple(ripple, delay, time, startScale, startOpacity, finalScale) {
// We draw a ripple by using a source image and animating it scaling
@ -1223,7 +1221,7 @@ var HotCorner = new Lang.Class({
transition: 'linear',
onUpdate() { ripple.opacity = 255 * Math.sqrt(ripple._opacity); },
onComplete() { ripple.visible = false; } });
},
}
_rippleAnimation() {
// Show three concentric ripples expanding outwards; the exact
@ -1234,7 +1232,7 @@ var HotCorner = new Lang.Class({
this._animRipple(this._ripple1, 0.0, 0.83, 0.25, 1.0, 1.5);
this._animRipple(this._ripple2, 0.05, 1.0, 0.0, 0.7, 1.25);
this._animRipple(this._ripple3, 0.35, 1.0, 0.0, 0.3, 1);
},
}
_toggleOverview() {
if (this._monitor.inFullscreen && !Main.overview.visible)
@ -1244,7 +1242,7 @@ var HotCorner = new Lang.Class({
this._rippleAnimation();
Main.overview.toggle();
}
},
}
handleDragOver(source, actor, x, y, time) {
if (source != Main.xdndHandler)
@ -1253,7 +1251,7 @@ var HotCorner = new Lang.Class({
this._toggleOverview();
return DND.DragMotionResult.CONTINUE;
},
}
_onCornerEntered() {
if (!this._entered) {
@ -1261,26 +1259,24 @@ var HotCorner = new Lang.Class({
this._toggleOverview();
}
return Clutter.EVENT_PROPAGATE;
},
}
_onCornerLeft(actor, event) {
if (event.get_related() != this.actor)
this._entered = false;
// Consume event, otherwise this will confuse onEnvironsLeft
return Clutter.EVENT_STOP;
},
}
_onEnvironsLeft(actor, event) {
if (event.get_related() != this._corner)
this._entered = false;
return Clutter.EVENT_PROPAGATE;
}
});
};
var PressureBarrier = new Lang.Class({
Name: 'PressureBarrier',
_init(threshold, timeout, actionMode) {
var PressureBarrier = class PressureBarrier {
constructor(threshold, timeout, actionMode) {
this._threshold = threshold;
this._timeout = timeout;
this._actionMode = actionMode;
@ -1289,57 +1285,57 @@ var PressureBarrier = new Lang.Class({
this._isTriggered = false;
this._reset();
},
}
addBarrier(barrier) {
barrier._pressureHitId = barrier.connect('hit', this._onBarrierHit.bind(this));
barrier._pressureLeftId = barrier.connect('left', this._onBarrierLeft.bind(this));
this._barriers.push(barrier);
},
}
_disconnectBarrier(barrier) {
barrier.disconnect(barrier._pressureHitId);
barrier.disconnect(barrier._pressureLeftId);
},
}
removeBarrier(barrier) {
this._disconnectBarrier(barrier);
this._barriers.splice(this._barriers.indexOf(barrier), 1);
},
}
destroy() {
this._barriers.forEach(this._disconnectBarrier.bind(this));
this._barriers = [];
},
}
setEventFilter(filter) {
this._eventFilter = filter;
},
}
_reset() {
this._barrierEvents = [];
this._currentPressure = 0;
this._lastTime = 0;
},
}
_isHorizontal(barrier) {
return barrier.y1 == barrier.y2;
},
}
_getDistanceAcrossBarrier(barrier, event) {
if (this._isHorizontal(barrier))
return Math.abs(event.dy);
else
return Math.abs(event.dx);
},
}
_getDistanceAlongBarrier(barrier, event) {
if (this._isHorizontal(barrier))
return Math.abs(event.dx);
else
return Math.abs(event.dy);
},
}
_trimBarrierEvents() {
// Events are guaranteed to be sorted in time order from
@ -1363,7 +1359,7 @@ var PressureBarrier = new Lang.Class({
}
this._barrierEvents = this._barrierEvents.slice(firstNewEvent);
},
}
_onBarrierLeft(barrier, event) {
barrier._isHit = false;
@ -1371,13 +1367,13 @@ var PressureBarrier = new Lang.Class({
this._reset();
this._isTriggered = false;
}
},
}
_trigger() {
this._isTriggered = true;
this.emit('trigger');
this._reset();
},
}
_onBarrierHit(barrier, event) {
barrier._isHit = true;
@ -1419,5 +1415,5 @@ var PressureBarrier = new Lang.Class({
if (this._currentPressure >= this._threshold)
this._trigger();
}
});
};
Signals.addSignalMethods(PressureBarrier.prototype);

View File

@ -1,11 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Lang = imports.lang;
const Meta = imports.gi.Meta;
const { Clutter, GObject, Shell, St } = imports.gi;
const Signals = imports.signals;
const St = imports.gi.St;
const Shell = imports.gi.Shell;
const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
@ -27,38 +23,36 @@ t = clamp(t, 0.0, 1.0);\n\
float pixel_brightness = mix(1.0, 1.0 - vignette_sharpness, t);\n\
cogl_color_out.a = cogl_color_out.a * (1 - pixel_brightness * brightness);';
var RadialShaderQuad = new Lang.Class({
Name: 'RadialShaderQuad',
Extends: Shell.GLSLQuad,
var RadialShaderQuad = GObject.registerClass(
class RadialShaderQuad extends Shell.GLSLQuad {
_init(params) {
this.parent(params);
super._init(params);
this._brightnessLocation = this.get_uniform_location('brightness');
this._sharpnessLocation = this.get_uniform_location('vignette_sharpness');
this.brightness = 1.0;
this.vignetteSharpness = 0.0;
},
}
vfunc_build_pipeline() {
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT,
VIGNETTE_DECLARATIONS, VIGNETTE_CODE, true);
},
}
get brightness() {
return this._brightness;
},
}
set brightness(v) {
this._brightness = v;
this.set_uniform_float(this._brightnessLocation,
1, [this._brightness]);
},
}
get vignetteSharpness() {
return this._sharpness;
},
}
set vignetteSharpness(v) {
this._sharpness = v;
@ -91,10 +85,8 @@ var RadialShaderQuad = new Lang.Class({
* @container and will track any changes in its size. You can override
* this by passing an explicit width and height in @params.
*/
var Lightbox = new Lang.Class({
Name: 'Lightbox',
_init(container, params) {
var Lightbox = class Lightbox {
constructor(container, params) {
params = Params.parse(params, { inhibitEvents: false,
width: null,
height: null,
@ -137,7 +129,7 @@ var Lightbox = new Lang.Class({
this._actorRemovedSignalId = container.connect('actor-removed', this._actorRemoved.bind(this));
this._highlighted = null;
},
}
_actorAdded(container, newChild) {
let children = this._container.get_children();
@ -159,7 +151,7 @@ var Lightbox = new Lang.Class({
if (prevChild != -1) // paranoia
this._children.splice(prevChild + 1, 0, newChild);
}
},
}
show(fadeInTime) {
fadeInTime = fadeInTime || 0;
@ -189,7 +181,7 @@ var Lightbox = new Lang.Class({
}
this.actor.show();
},
}
hide(fadeOutTime) {
fadeOutTime = fadeOutTime || 0;
@ -217,7 +209,7 @@ var Lightbox = new Lang.Class({
}
});
}
},
}
_actorRemoved(container, child) {
let index = this._children.indexOf(child);
@ -226,7 +218,7 @@ var Lightbox = new Lang.Class({
if (child == this._highlighted)
this._highlighted = null;
},
}
/**
* highlight:
@ -257,7 +249,7 @@ var Lightbox = new Lang.Class({
}
this._highlighted = window;
},
}
/**
* destroy:
@ -266,7 +258,7 @@ var Lightbox = new Lang.Class({
*/
destroy() {
this.actor.destroy();
},
}
/**
* _onDestroy:
@ -280,5 +272,5 @@ var Lightbox = new Lang.Class({
this.highlight(null);
}
});
};
Signals.addSignalMethods(Lightbox.prototype);

View File

@ -1,18 +1,9 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
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;
const St = imports.gi.St;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const Lang = imports.lang;
const { Clutter, Cogl, Gio, GLib,
GObject, Meta, Pango, Shell, St } = imports.gi;
const Mainloop = imports.mainloop;
const Signals = imports.signals;
const System = imports.system;
const History = imports.misc.history;
@ -26,16 +17,9 @@ const JsParse = imports.misc.jsParse;
const CHEVRON = '>>> ';
/* Imports...feel free to add here as needed */
var commandHeader = 'const Clutter = imports.gi.Clutter; ' +
'const GLib = imports.gi.GLib; ' +
'const GObject = imports.gi.GObject; ' +
'const Gio = imports.gi.Gio; ' +
'const Gtk = imports.gi.Gtk; ' +
'const Mainloop = imports.mainloop; ' +
'const Meta = imports.gi.Meta; ' +
'const Shell = imports.gi.Shell; ' +
var commandHeader = 'const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi; ' +
'const Main = imports.ui.main; ' +
'const Lang = imports.lang; ' +
'const Mainloop = imports.mainloop; ' +
'const Tweener = imports.ui.tweener; ' +
/* Utility functions...we should probably be able to use these
* in the shell core code too. */
@ -62,14 +46,12 @@ function _getAutoCompleteGlobalKeywords() {
return keywords.concat(windowProperties).concat(headerProperties);
}
var AutoComplete = new Lang.Class({
Name: 'AutoComplete',
_init(entry) {
var AutoComplete = class AutoComplete {
constructor(entry) {
this._entry = entry;
this._entry.connect('key-press-event', this._entryKeyPressEvent.bind(this));
this._lastTabTime = global.get_current_time();
},
}
_processCompletionRequest(event) {
if (event.completions.length == 0) {
@ -91,7 +73,7 @@ var AutoComplete = new Lang.Class({
} else if (event.completions.length > 1 && event.tabType === 'double') {
this.emit('suggest', { completions: event.completions});
}
},
}
_entryKeyPressEvent(actor, event) {
let cursorPos = this._entry.clutter_text.get_cursor_position();
@ -114,7 +96,7 @@ var AutoComplete = new Lang.Class({
this._lastTabTime = currTime;
}
return Clutter.EVENT_PROPAGATE;
},
}
// Insert characters of text not already included in head at cursor position. i.e., if text="abc" and head="a",
// the string "bc" will be appended to this._entry
@ -124,21 +106,19 @@ var AutoComplete = new Lang.Class({
this._entry.clutter_text.insert_text(additionalCompletionText, cursorPos);
}
});
};
Signals.addSignalMethods(AutoComplete.prototype);
var Notebook = new Lang.Class({
Name: 'Notebook',
_init() {
var Notebook = class Notebook {
constructor() {
this.actor = new St.BoxLayout({ vertical: true });
this.tabControls = new St.BoxLayout({ style_class: 'labels' });
this._selectedIndex = -1;
this._tabs = [];
},
}
appendPage(name, child) {
let labelBox = new St.BoxLayout({ style_class: 'notebook-tab',
@ -171,7 +151,7 @@ var Notebook = new Lang.Class({
if (this._selectedIndex == -1)
this.selectIndex(0);
},
}
_unselect() {
if (this._selectedIndex < 0)
@ -180,7 +160,7 @@ var Notebook = new Lang.Class({
tabData.labelBox.remove_style_pseudo_class('selected');
tabData.scrollView.hide();
this._selectedIndex = -1;
},
}
selectIndex(index) {
if (index == this._selectedIndex)
@ -193,7 +173,7 @@ var Notebook = new Lang.Class({
// Focus the new tab before unmapping the old one
let tabData = this._tabs[index];
if (!tabData.scrollView.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false))
if (!tabData.scrollView.navigate_focus(null, St.DirectionType.TAB_FORWARD, false))
this.actor.grab_key_focus();
this._unselect();
@ -202,7 +182,7 @@ var Notebook = new Lang.Class({
tabData.scrollView.show();
this._selectedIndex = index;
this.emit('selection', tabData.child);
},
}
selectChild(child) {
if (child == null)
@ -216,26 +196,26 @@ var Notebook = new Lang.Class({
}
}
}
},
}
scrollToBottom(index) {
let tabData = this._tabs[index];
tabData._scrollToBottom = true;
},
}
_onAdjustValueChanged(tabData) {
let vAdjust = tabData.scrollView.vscroll.adjustment;
if (vAdjust.value < (vAdjust.upper - vAdjust.lower - 0.5))
tabData._scrolltoBottom = false;
},
}
_onAdjustScopeChanged(tabData) {
if (!tabData._scrollToBottom)
return;
let vAdjust = tabData.scrollView.vscroll.adjustment;
vAdjust.value = vAdjust.upper - vAdjust.page_size;
},
}
nextTab() {
let nextIndex = this._selectedIndex;
@ -244,7 +224,7 @@ var Notebook = new Lang.Class({
}
this.selectIndex(nextIndex);
},
}
prevTab() {
let prevIndex = this._selectedIndex;
@ -254,7 +234,7 @@ var Notebook = new Lang.Class({
this.selectIndex(prevIndex);
}
});
};
Signals.addSignalMethods(Notebook.prototype);
function objectToString(o) {
@ -266,10 +246,8 @@ function objectToString(o) {
}
}
var ObjLink = new Lang.Class({
Name: 'ObjLink',
_init(lookingGlass, o, title) {
var ObjLink = class ObjLink {
constructor(lookingGlass, o, title) {
let text;
if (title)
text = title;
@ -286,17 +264,15 @@ var ObjLink = new Lang.Class({
this.actor.connect('clicked', this._onClicked.bind(this));
this._lookingGlass = lookingGlass;
},
}
_onClicked(link) {
this._lookingGlass.inspectObject(this._obj, this.actor);
}
});
};
var Result = new Lang.Class({
Name: 'Result',
_init(lookingGlass, command, o, index) {
var Result = class Result {
constructor(lookingGlass, command, o, index) {
this.index = index;
this.o = o;
@ -314,12 +290,10 @@ var Result = new Lang.Class({
let objLink = new ObjLink(this._lookingGlass, o);
box.add(objLink.actor);
}
});
};
var WindowList = new Lang.Class({
Name: 'WindowList',
_init(lookingGlass) {
var WindowList = class WindowList {
constructor(lookingGlass) {
this.actor = new St.BoxLayout({ name: 'Windows', vertical: true, style: 'spacing: 8px' });
let tracker = Shell.WindowTracker.get_default();
this._updateId = Main.initializeDeferredWork(this.actor, this._updateWindowList.bind(this));
@ -327,7 +301,7 @@ var WindowList = new Lang.Class({
tracker.connect('tracked-windows-changed', this._updateWindowList.bind(this));
this._lookingGlass = lookingGlass;
},
}
_updateWindowList() {
this.actor.destroy_all_children();
@ -361,13 +335,11 @@ var WindowList = new Lang.Class({
}
}
}
});
};
Signals.addSignalMethods(WindowList.prototype);
var ObjInspector = new Lang.Class({
Name: 'ObjInspector',
_init(lookingGlass) {
var ObjInspector = class ObjInspector {
constructor(lookingGlass) {
this._obj = null;
this._previousObj = null;
@ -382,7 +354,7 @@ var ObjInspector = new Lang.Class({
this.actor.add_actor(this._container);
this._lookingGlass = lookingGlass;
},
}
selectObject(obj, skipPrevious) {
if (!skipPrevious)
@ -410,6 +382,7 @@ var ObjInspector = new Lang.Class({
}
button = new St.Button({ style_class: 'window-close' });
button.add_actor(new St.Icon({ icon_name: 'window-close-symbolic' }));
button.connect('clicked', this.close.bind(this));
hbox.add(button);
if (typeof(obj) == typeof({})) {
@ -436,7 +409,7 @@ var ObjInspector = new Lang.Class({
this._container.add_actor(hbox);
}
}
},
}
open(sourceActor) {
if (this._open)
@ -452,7 +425,7 @@ var ObjInspector = new Lang.Class({
} else {
this.actor.set_scale(1, 1);
}
},
}
close() {
if (!this._open)
@ -461,23 +434,21 @@ var ObjInspector = new Lang.Class({
this.actor.hide();
this._previousObj = null;
this._obj = null;
},
}
_onInsert() {
let obj = this._obj;
this.close();
this._lookingGlass.insertObject(obj);
},
}
_onBack() {
this.selectObject(this._previousObj, true);
}
});
var RedBorderEffect = new Lang.Class({
Name: 'RedBorderEffect',
Extends: Clutter.Effect,
};
var RedBorderEffect = GObject.registerClass(
class RedBorderEffect extends Clutter.Effect {
vfunc_paint() {
let actor = this.get_actor();
actor.continue_paint();
@ -497,17 +468,15 @@ var RedBorderEffect = new Lang.Class({
geom.width - width, geom.height - width);
Cogl.rectangle(0, geom.height - width,
width, width);
},
}
});
var Inspector = new Lang.Class({
Name: 'Inspector',
Extends: Clutter.Actor,
var Inspector = GObject.registerClass({
Signals: { 'closed': {},
'target': { param_types: [Clutter.Actor.$gtype, GObject.TYPE_DOUBLE, GObject.TYPE_DOUBLE] } },
}, class Inspector extends Clutter.Actor {
_init(lookingGlass) {
this.parent({ width: 0,
super._init({ width: 0,
height: 0 });
Main.uiGroup.add_actor(this);
@ -536,7 +505,7 @@ var Inspector = new Lang.Class({
this._pointerTarget = null;
this._lookingGlass = lookingGlass;
},
}
vfunc_allocate(box, flags) {
this.set_allocation(box, flags);
@ -555,7 +524,7 @@ var Inspector = new Lang.Class({
childBox.y1 = primary.y + Math.floor((primary.height - natHeight) / 2);
childBox.y2 = childBox.y1 + natHeight;
this._eventHandler.allocate(childBox, flags);
},
}
_close() {
Clutter.ungrab_pointer();
@ -563,13 +532,13 @@ var Inspector = new Lang.Class({
this._eventHandler.destroy();
this._eventHandler = null;
this.emit('closed');
},
}
_onKeyPressEvent(actor, event) {
if (event.get_key_symbol() == Clutter.Escape)
this._close();
return Clutter.EVENT_STOP;
},
}
_onButtonPressEvent(actor, event) {
if (this._target) {
@ -578,7 +547,7 @@ var Inspector = new Lang.Class({
}
this._close();
return Clutter.EVENT_STOP;
},
}
_onScrollEvent(actor, event) {
switch (event.get_scroll_direction()) {
@ -612,12 +581,12 @@ var Inspector = new Lang.Class({
break;
}
return Clutter.EVENT_STOP;
},
}
_onMotionEvent(actor, event) {
this._update(event);
return Clutter.EVENT_STOP;
},
}
_update(event) {
let [stageX, stageY] = event.get_coords();
@ -637,10 +606,8 @@ var Inspector = new Lang.Class({
}
});
var Extensions = new Lang.Class({
Name: 'Extensions',
_init(lookingGlass) {
var Extensions = class Extensions {
constructor(lookingGlass) {
this._lookingGlass = lookingGlass;
this.actor = new St.BoxLayout({ vertical: true,
name: 'lookingGlassExtensions' });
@ -657,7 +624,7 @@ var Extensions = new Lang.Class({
ExtensionSystem.connect('extension-loaded',
this._loadExtension.bind(this));
},
}
_loadExtension(o, uuid) {
let extension = ExtensionUtils.extensions[uuid];
@ -672,20 +639,20 @@ var Extensions = new Lang.Class({
this._numExtensions ++;
this._extensionsList.add(extensionDisplay);
},
}
_onViewSource(actor) {
let extension = actor._extension;
let uri = extension.dir.get_uri();
Gio.app_info_launch_default_for_uri(uri, global.create_app_launch_context(0, -1));
this._lookingGlass.close();
},
}
_onWebPage(actor) {
let extension = actor._extension;
Gio.app_info_launch_default_for_uri(extension.metadata.url, global.create_app_launch_context(0, -1));
this._lookingGlass.close();
},
}
_onViewErrors(actor) {
let extension = actor._extension;
@ -713,7 +680,7 @@ var Extensions = new Lang.Class({
}
actor._isShowing = shouldShow;
},
}
_stateToString(extensionState) {
switch (extensionState) {
@ -730,7 +697,7 @@ var Extensions = new Lang.Class({
return _("Downloading");
}
return 'Unknown'; // Not translated, shouldn't appear
},
}
_createExtensionDisplay(extension) {
let box = new St.BoxLayout({ style_class: 'lg-extension', vertical: true });
@ -778,12 +745,10 @@ var Extensions = new Lang.Class({
return box;
}
});
};
var LookingGlass = new Lang.Class({
Name: 'LookingGlass',
_init() {
var LookingGlass = class LookingGlass {
constructor() {
this._borderPaintTarget = null;
this._redBorderEffect = new RedBorderEffect();
@ -917,7 +882,7 @@ var LookingGlass = new Lang.Class({
});
this._resize();
},
}
_updateFont() {
let fontName = this._interfaceSettings.get_string('monospace-font-name');
@ -927,7 +892,7 @@ var LookingGlass = new Lang.Class({
this.actor.style =
'font-size: ' + fontDesc.get_size() / 1024. + (fontDesc.get_size_is_absolute() ? 'px' : 'pt') + ';'
+ 'font-family: "' + fontDesc.get_family() + '";';
},
}
setBorderPaintTarget(obj) {
if (this._borderPaintTarget != null)
@ -935,7 +900,7 @@ var LookingGlass = new Lang.Class({
this._borderPaintTarget = obj;
if (this._borderPaintTarget != null)
this._borderPaintTarget.add_effect(this._redBorderEffect);
},
}
_pushResult(command, obj) {
let index = this._results.length + this._offset;
@ -955,7 +920,7 @@ var LookingGlass = new Lang.Class({
// Scroll to bottom
this._notebook.scrollToBottom(0);
},
}
_showCompletions(completions) {
if (!this._completionActor) {
@ -984,7 +949,7 @@ var LookingGlass = new Lang.Class({
opacity: 255
});
}
},
}
_hideCompletions() {
if (this._completionActor) {
@ -998,46 +963,49 @@ var LookingGlass = new Lang.Class({
}
});
}
},
}
_evaluate(command) {
this._history.addItem(command);
let fullCmd = commandHeader + command;
let lines = command.split(';');
lines.push(`return ${lines.pop()}`);
let fullCmd = commandHeader + lines.join(';');
let resultObj;
try {
resultObj = eval(fullCmd);
resultObj = Function(fullCmd)();
} catch (e) {
resultObj = '<exception ' + e + '>';
}
this._pushResult(command, resultObj);
this._entry.text = '';
},
}
inspect(x, y) {
return global.stage.get_actor_at_pos(Clutter.PickMode.REACTIVE, x, y);
},
}
getIt() {
return this._it;
},
}
getResult(idx) {
return this._results[idx - this._offset].o;
},
}
toggle() {
if (this._open)
this.close();
else
this.open();
},
}
_queueResize() {
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => { this._resize(); });
},
}
_resize() {
let primary = Main.layoutManager.primaryMonitor;
@ -1053,16 +1021,16 @@ var LookingGlass = new Lang.Class({
this._objInspector.actor.set_size(Math.floor(myWidth * 0.8), Math.floor(myHeight * 0.8));
this._objInspector.actor.set_position(this.actor.x + Math.floor(myWidth * 0.1),
this._targetY + Math.floor(myHeight * 0.1));
},
}
insertObject(obj) {
this._pushResult('<insert>', obj);
},
}
inspectObject(obj, sourceActor) {
this._objInspector.open(sourceActor);
this._objInspector.selectObject(obj);
},
}
// Handle key events which are relevant for all tabs of the LookingGlass
_globalKeyPressEvent(actor, event) {
@ -1085,7 +1053,7 @@ var LookingGlass = new Lang.Class({
}
}
return Clutter.EVENT_PROPAGATE;
},
}
open() {
if (this._open)
@ -1107,7 +1075,7 @@ var LookingGlass = new Lang.Class({
transition: 'easeOutQuad',
y: this._targetY
});
},
}
close() {
if (!this._open)
@ -1130,5 +1098,5 @@ var LookingGlass = new Lang.Class({
}
});
}
});
};
Signals.addSignalMethods(LookingGlass.prototype);

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const Main = imports.ui.main;
const { loadInterfaceXML } = imports.misc.fileUtils;
@ -22,15 +21,13 @@ const ZoomRegionIface = loadInterfaceXML('org.gnome.Magnifier.ZoomRegion');
// '/org/gnome/Magnifier/ZoomRegion/zoomer1', etc.
let _zoomRegionInstanceCount = 0;
var ShellMagnifier = new Lang.Class({
Name: 'ShellMagnifier',
_init() {
var ShellMagnifier = class ShellMagnifier {
constructor() {
this._zoomers = {};
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(MagnifierIface, this);
this._dbusImpl.export(Gio.DBus.session, MAG_SERVICE_PATH);
},
}
/**
* setActive:
@ -38,7 +35,7 @@ var ShellMagnifier = new Lang.Class({
*/
setActive(activate) {
Main.magnifier.setActive(activate);
},
}
/**
* isActive:
@ -46,7 +43,7 @@ var ShellMagnifier = new Lang.Class({
*/
isActive() {
return Main.magnifier.isActive();
},
}
/**
* showCursor:
@ -54,7 +51,7 @@ var ShellMagnifier = new Lang.Class({
*/
showCursor() {
Main.magnifier.showSystemCursor();
},
}
/**
* hideCursor:
@ -62,7 +59,7 @@ var ShellMagnifier = new Lang.Class({
*/
hideCursor() {
Main.magnifier.hideSystemCursor();
},
}
/**
* createZoomRegion:
@ -97,7 +94,7 @@ var ShellMagnifier = new Lang.Class({
proxyAndZoomRegion.zoomRegion = realZoomRegion;
this._zoomers[objectPath] = proxyAndZoomRegion;
return objectPath;
},
}
/**
* addZoomRegion:
@ -112,7 +109,7 @@ var ShellMagnifier = new Lang.Class({
}
else
return false;
},
}
/**
* getZoomRegions:
@ -150,7 +147,7 @@ var ShellMagnifier = new Lang.Class({
}
});
return objectPaths;
},
}
/**
* clearAllZoomRegions:
@ -166,7 +163,7 @@ var ShellMagnifier = new Lang.Class({
delete this._zoomers[objectPath];
}
this._zoomers = {};
},
}
/**
* fullScreenCapable:
@ -175,7 +172,7 @@ var ShellMagnifier = new Lang.Class({
*/
fullScreenCapable() {
return true;
},
}
/**
* setCrosswireSize:
@ -184,7 +181,7 @@ var ShellMagnifier = new Lang.Class({
*/
setCrosswireSize(size) {
Main.magnifier.setCrosshairsThickness(size);
},
}
/**
* getCrosswireSize:
@ -193,7 +190,7 @@ var ShellMagnifier = new Lang.Class({
*/
getCrosswireSize() {
return Main.magnifier.getCrosshairsThickness();
},
}
/**
* setCrosswireLength:
@ -202,7 +199,7 @@ var ShellMagnifier = new Lang.Class({
*/
setCrosswireLength(length) {
Main.magnifier.setCrosshairsLength(length);
},
}
/**
* setCrosswireSize:
@ -211,7 +208,7 @@ var ShellMagnifier = new Lang.Class({
*/
getCrosswireLength() {
return Main.magnifier.getCrosshairsLength();
},
}
/**
* setCrosswireClip:
@ -220,7 +217,7 @@ var ShellMagnifier = new Lang.Class({
*/
setCrosswireClip(clip) {
Main.magnifier.setCrosshairsClip(clip);
},
}
/**
* getCrosswireClip:
@ -229,7 +226,7 @@ var ShellMagnifier = new Lang.Class({
*/
getCrosswireClip() {
return Main.magnifier.getCrosshairsClip();
},
}
/**
* setCrosswireColor:
@ -238,7 +235,7 @@ var ShellMagnifier = new Lang.Class({
*/
setCrosswireColor(color) {
Main.magnifier.setCrosshairsColor('#%08x'.format(color));
},
}
/**
* getCrosswireClip:
@ -250,7 +247,7 @@ var ShellMagnifier = new Lang.Class({
// Drop the leading '#'.
return parseInt(colorString.slice(1), 16);
}
});
};
/**
* ShellMagnifierZoomRegion:
@ -258,15 +255,13 @@ var ShellMagnifier = new Lang.Class({
* @zoomerObjectPath: String that is the path to a DBus ZoomRegion.
* @zoomRegion: The actual zoom region associated with the object path.
*/
var ShellMagnifierZoomRegion = new Lang.Class({
Name: 'ShellMagnifierZoomRegion',
_init(zoomerObjectPath, zoomRegion) {
var ShellMagnifierZoomRegion = class ShellMagnifierZoomRegion {
constructor(zoomerObjectPath, zoomRegion) {
this._zoomRegion = zoomRegion;
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(ZoomRegionIface, this);
this._dbusImpl.export(Gio.DBus.session, zoomerObjectPath);
},
}
/**
* setMagFactor:
@ -278,7 +273,7 @@ var ShellMagnifierZoomRegion = new Lang.Class({
*/
setMagFactor(xMagFactor, yMagFactor) {
this._zoomRegion.setMagFactor(xMagFactor, yMagFactor);
},
}
/**
* getMagFactor:
@ -289,7 +284,7 @@ var ShellMagnifierZoomRegion = new Lang.Class({
*/
getMagFactor() {
return this._zoomRegion.getMagFactor();
},
}
/**
* setRoi:
@ -301,7 +296,7 @@ var ShellMagnifierZoomRegion = new Lang.Class({
setRoi(roi) {
let roiObject = { x: roi[0], y: roi[1], width: roi[2] - roi[0], height: roi[3] - roi[1] };
this._zoomRegion.setROI(roiObject);
},
}
/**
* getRoi:
@ -316,7 +311,7 @@ var ShellMagnifierZoomRegion = new Lang.Class({
roi[2] += roi[0];
roi[3] += roi[1];
return roi;
},
}
/**
* Set the "region of interest" by centering the given screen coordinate
@ -329,7 +324,7 @@ var ShellMagnifierZoomRegion = new Lang.Class({
shiftContentsTo(x, y) {
this._zoomRegion.scrollContentsTo(x, y);
return true;
},
}
/**
* moveResize
@ -340,9 +335,9 @@ var ShellMagnifierZoomRegion = new Lang.Class({
moveResize(viewPort) {
let viewRect = { x: viewPort[0], y: viewPort[1], width: viewPort[2] - viewPort[0], height: viewPort[3] - viewPort[1] };
this._zoomRegion.setViewPort(viewRect);
},
}
destroy() {
this._dbusImpl.unexport();
}
});
};

View File

@ -1,22 +1,13 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Gdk = imports.gi.Gdk;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
const { Clutter, Gio, GLib, Meta, Shell, St } = imports.gi;
const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const AccessDialog = imports.ui.accessDialog;
const AudioDeviceSelection = imports.ui.audioDeviceSelection;
const Components = imports.ui.components;
const CtrlAltTab = imports.ui.ctrlAltTab;
const EndSessionDialog = imports.ui.endSessionDialog;
const Environment = imports.ui.environment;
const ExtensionSystem = imports.ui.extensionSystem;
const ExtensionDownloader = imports.ui.extensionDownloader;
const InputMethod = imports.misc.inputMethod;
@ -45,7 +36,6 @@ const ShellMountOperation = imports.ui.shellMountOperation;
const WindowManager = imports.ui.windowManager;
const Magnifier = imports.ui.magnifier;
const XdndHandler = imports.ui.xdndHandler;
const Util = imports.misc.util;
const KbdA11yDialog = imports.ui.kbdA11yDialog;
const A11Y_SCHEMA = 'org.gnome.desktop.a11y.keyboard';
@ -129,9 +119,8 @@ function start() {
sessionMode = new SessionMode.SessionMode();
sessionMode.connect('updated', _sessionUpdated);
Gtk.Settings.get_default().connect('notify::gtk-theme-name',
_loadDefaultStylesheet);
Gtk.IconTheme.get_default().add_resource_path('/org/gnome/shell/theme/icons');
St.Settings.get().connect('notify::gtk-theme', _loadDefaultStylesheet);
_initializeUI();
shellAccessDialogDBusService = new AccessDialog.AccessDialogDBus();
@ -222,13 +211,6 @@ function _initializeUI() {
_startDate = new Date();
let perfModuleName = GLib.getenv("SHELL_PERF_MODULE");
if (perfModuleName) {
let perfOutput = GLib.getenv("SHELL_PERF_OUTPUT");
let module = eval('imports.perf.' + perfModuleName + ';');
Scripting.runPerfScript(module, perfOutput);
}
ExtensionDownloader.init();
ExtensionSystem.init();
@ -250,6 +232,13 @@ function _initializeUI() {
Shell.Global.log_structured('GNOME Shell started at ' + _startDate,
['MESSAGE_ID=' + GNOMESHELL_STARTED_MESSAGE_ID]);
}
let perfModuleName = GLib.getenv("SHELL_PERF_MODULE");
if (perfModuleName) {
let perfOutput = GLib.getenv("SHELL_PERF_OUTPUT");
let module = eval('imports.perf.' + perfModuleName + ';');
Scripting.runPerfScript(module, perfOutput);
}
});
}
@ -281,7 +270,7 @@ function _getDefaultStylesheet() {
// Look for a high-contrast variant first when using GTK+'s HighContrast
// theme
if (Gtk.Settings.get_default().gtk_theme_name == 'HighContrast')
if (St.Settings.get().gtk_theme == 'HighContrast')
stylesheet = _getStylesheet(name.replace('.css', '-high-contrast.css'));
if (stylesheet == null)
@ -700,15 +689,12 @@ function queueDeferredWork(workId) {
}
}
var RestartMessage = new Lang.Class({
Name: 'RestartMessage',
Extends: ModalDialog.ModalDialog,
_init(message) {
this.parent({ shellReactive: true,
styleClass: 'restart-message headline',
shouldFadeIn: false,
destroyOnClose: true });
var RestartMessage = class extends ModalDialog.ModalDialog {
constructor(message) {
super({ shellReactive: true,
styleClass: 'restart-message headline',
shouldFadeIn: false,
destroyOnClose: true });
let label = new St.Label({ text: message });
@ -718,7 +704,7 @@ var RestartMessage = new Lang.Class({
y_align: St.Align.MIDDLE });
this.buttonLayout.hide();
}
});
};
function showRestartMessage(message) {
let restartMessage = new RestartMessage(message);

Some files were not shown because too many files have changed in this diff Show More