Compare commits
7 Commits
gbsneto/fi
...
wip/fmuell
Author | SHA1 | Date | |
---|---|---|---|
![]() |
ee3cd450a5 | ||
![]() |
996369a22d | ||
![]() |
ce6ab7e121 | ||
![]() |
3da747ec2d | ||
![]() |
593f15ad63 | ||
![]() |
acdbd28262 | ||
![]() |
ca70a4fc17 |
@@ -1,18 +0,0 @@
|
||||
stages:
|
||||
- source_check
|
||||
|
||||
variables:
|
||||
JS_LOG: "js-report.txt"
|
||||
|
||||
js_check:
|
||||
image: registry.fedoraproject.org/fedora:latest
|
||||
stage: source_check
|
||||
before_script:
|
||||
- dnf install -y findutils mozjs60-devel
|
||||
script:
|
||||
- find js -name '*.js' -exec js60 -c -s '{}' ';' 2>&1 | tee $JS_LOG
|
||||
- (! grep -q . $JS_LOG)
|
||||
artifacts:
|
||||
paths:
|
||||
- ${JS_LOG}
|
||||
when: on_failure
|
@@ -158,15 +158,15 @@ you to inherit from a type to use it, you can do so:
|
||||
var MyClutterActor = GObject.registerClass(
|
||||
class MyClutterActor extends Clutter.Actor {
|
||||
|
||||
vfunc_get_preferred_width(forHeight) {
|
||||
vfunc_get_preferred_width(actor, forHeight) {
|
||||
return [100, 100];
|
||||
}
|
||||
|
||||
vfunc_get_preferred_height(forWidth) {
|
||||
vfunc_get_preferred_height(actor, forWidth) {
|
||||
return [100, 100];
|
||||
}
|
||||
|
||||
vfunc_paint() {
|
||||
vfunc_paint(actor) {
|
||||
let alloc = this.get_allocation_box();
|
||||
Cogl.set_source_color4ub(255, 0, 0, 255);
|
||||
Cogl.rectangle(alloc.x1, alloc.y1,
|
||||
|
35
NEWS
35
NEWS
@@ -1,38 +1,3 @@
|
||||
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]
|
||||
|
15740
data/emoji.json
15740
data/emoji.json
File diff suppressed because it is too large
Load Diff
@@ -54,6 +54,5 @@
|
||||
<file>us.json</file>
|
||||
<file>vn.json</file>
|
||||
<file>za.json</file>
|
||||
<file>emoji.json</file>
|
||||
</gresource>
|
||||
</gresources>
|
||||
|
@@ -104,13 +104,6 @@
|
||||
|
||||
<schema id="org.gnome.shell.keybindings" path="/org/gnome/shell/keybindings/"
|
||||
gettext-domain="@GETTEXT_PACKAGE@">
|
||||
<key name="open-application-menu" type="as">
|
||||
<default>["<Super>F10"]</default>
|
||||
<summary>Keybinding to open the application menu</summary>
|
||||
<description>
|
||||
Keybinding to open the application menu.
|
||||
</description>
|
||||
</key>
|
||||
<key name="toggle-application-view" type="as">
|
||||
<default>["<Super>a"]</default>
|
||||
<summary>Keybinding to open the “Show Applications” view</summary>
|
||||
@@ -145,42 +138,6 @@
|
||||
<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>["<Super>1"]</default>
|
||||
<summary>Switch to application 1</summary>
|
||||
</key>
|
||||
<key name="switch-to-application-2" type="as">
|
||||
<default>["<Super>2"]</default>
|
||||
<summary>Switch to application 2</summary>
|
||||
</key>
|
||||
<key name="switch-to-application-3" type="as">
|
||||
<default>["<Super>3"]</default>
|
||||
<summary>Switch to application 3</summary>
|
||||
</key>
|
||||
<key name="switch-to-application-4" type="as">
|
||||
<default>["<Super>4"]</default>
|
||||
<summary>Switch to application 4</summary>
|
||||
</key>
|
||||
<key name="switch-to-application-5" type="as">
|
||||
<default>["<Super>5"]</default>
|
||||
<summary>Switch to application 5</summary>
|
||||
</key>
|
||||
<key name="switch-to-application-6" type="as">
|
||||
<default>["<Super>6"]</default>
|
||||
<summary>Switch to application 6</summary>
|
||||
</key>
|
||||
<key name="switch-to-application-7" type="as">
|
||||
<default>["<Super>7"]</default>
|
||||
<summary>Switch to application 7</summary>
|
||||
</key>
|
||||
<key name="switch-to-application-8" type="as">
|
||||
<default>["<Super>8"]</default>
|
||||
<summary>Switch to application 8</summary>
|
||||
</key>
|
||||
<key name="switch-to-application-9" type="as">
|
||||
<default>["<Super>9"]</default>
|
||||
<summary>Switch to application 9</summary>
|
||||
</key>
|
||||
</schema>
|
||||
|
||||
<schema id="org.gnome.shell.keyboard" path="/org/gnome/shell/keyboard/"
|
||||
|
@@ -2,23 +2,26 @@
|
||||
// it gets @if ed depending on $variant
|
||||
|
||||
|
||||
$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);
|
||||
$base_color: if($variant =='light', #ffffff, #292929);
|
||||
$bg_color: if($variant =='light', #ededed, #393f3f);
|
||||
$fg_color: if($variant =='light', #2e3436, #eeeeec);
|
||||
|
||||
$selected_fg_color: #ffffff;
|
||||
$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%));
|
||||
$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%));
|
||||
$top_hilight: $borders_edge;
|
||||
|
||||
$warning_color: #f57900;
|
||||
$error_color: #cc0000;
|
||||
$success_color: if($variant == 'light', #33d17a, darken(#33d17a, 10%));
|
||||
$destructive_color: if($variant == 'light', #e01b24, darken(#e01b24, 10%));
|
||||
$success_color: if($variant =='light', #73d216, darken(#73d216,10%));
|
||||
$destructive_color: if($variant =='light', #ef2929, darken(#ef2929,10%));
|
||||
|
||||
$osd_fg_color: #eeeeec;
|
||||
$osd_bg_color: #2e3436;
|
||||
|
@@ -729,7 +729,9 @@ StScrollBar {
|
||||
/* TOP BAR */
|
||||
|
||||
#panel {
|
||||
background-color: black;
|
||||
background-color: rgba(0, 0, 0, 0.35);
|
||||
/* transition from solid to transparent */
|
||||
transition-duration: 500ms;
|
||||
font-weight: bold;
|
||||
height: 1.86em;
|
||||
font-feature-settings: "tnum";
|
||||
@@ -746,7 +748,7 @@ StScrollBar {
|
||||
|
||||
.panel-corner {
|
||||
-panel-corner-radius: $panel-corner-radius;
|
||||
-panel-corner-background-color: black;
|
||||
-panel-corner-background-color: rgba(0, 0, 0, 0.35);
|
||||
-panel-corner-border-width: 2px;
|
||||
-panel-corner-border-color: transparent;
|
||||
|
||||
@@ -765,7 +767,9 @@ StScrollBar {
|
||||
-natural-hpadding: 12px;
|
||||
-minimum-hpadding: 6px;
|
||||
font-weight: bold;
|
||||
color: #ccc;
|
||||
color: #eee;
|
||||
text-shadow: 0px 1px 2px rgba(0, 0, 0, 0.9);
|
||||
transition-duration: 100ms;
|
||||
|
||||
.app-menu-icon {
|
||||
-st-icon-style: symbolic;
|
||||
@@ -774,8 +778,21 @@ 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 {
|
||||
@@ -784,6 +801,8 @@ 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; }
|
||||
@@ -808,6 +827,31 @@ 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
|
||||
@@ -878,47 +922,14 @@ StScrollBar {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.weather-header.location {
|
||||
font-weight: normal;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.world-clocks-grid,
|
||||
.weather-grid {
|
||||
.world-clocks-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;
|
||||
@@ -1096,11 +1107,6 @@ 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; }
|
||||
@@ -1640,15 +1646,6 @@ StScrollBar {
|
||||
|
||||
#keyboard {
|
||||
background-color: transparentize($osd_bg_color, 0.3);
|
||||
|
||||
.page-indicator {
|
||||
padding: 4px 4px;
|
||||
|
||||
.page-indicator-icon {
|
||||
width: 6px;
|
||||
height: 6px
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.key-container {
|
||||
@@ -1658,8 +1655,8 @@ StScrollBar {
|
||||
|
||||
.keyboard-key {
|
||||
background-color: #393f3f;
|
||||
min-height: 1.2em;
|
||||
min-width: 1.2em;
|
||||
min-height: 2em;
|
||||
min-width: 2em;
|
||||
font-size: 16pt;
|
||||
border-radius: 3px;
|
||||
border: 1px solid #464d4d;
|
||||
@@ -1710,20 +1707,6 @@ 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 {
|
||||
|
@@ -104,111 +104,29 @@ var Application = class {
|
||||
}
|
||||
|
||||
_buildErrorUI(extension, exc) {
|
||||
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 box = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL });
|
||||
let label = new Gtk.Label({
|
||||
label: '<span size="x-large">%s</span>'.format(_("Something’s gone wrong")),
|
||||
use_markup: true
|
||||
});
|
||||
label.get_style_context().add_class(Gtk.STYLE_CLASS_DIM_LABEL);
|
||||
box.add(label);
|
||||
|
||||
label = new Gtk.Label({
|
||||
label: _("We’re very sorry, but there’s been a problem: the settings for this extension can’t be displayed. We recommend that you report the issue to the extension authors."),
|
||||
justify: Gtk.Justification.CENTER,
|
||||
wrap: true
|
||||
label: _("There was an error loading the preferences dialog for %s:").format(extension.metadata.name)
|
||||
});
|
||||
box.add(label);
|
||||
|
||||
let expander = new Expander({
|
||||
label: _("Technical Details"),
|
||||
margin_top: 12
|
||||
});
|
||||
box.add(expander);
|
||||
let errortext = '';
|
||||
errortext += exc;
|
||||
errortext += '\n\n';
|
||||
errortext += 'Stack trace:\n';
|
||||
|
||||
let errortext = `${exc}\n\nStack trace:\n${
|
||||
// Indent stack trace.
|
||||
exc.stack.split('\n').map(line => ` ${line}`).join('\n')
|
||||
}`;
|
||||
// Indent stack trace.
|
||||
errortext += 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,
|
||||
wrap_mode: Gtk.WrapMode.WORD,
|
||||
monospace: true,
|
||||
editable: false,
|
||||
top_margin: 12,
|
||||
bottom_margin: 12,
|
||||
left_margin: 12,
|
||||
right_margin: 12
|
||||
});
|
||||
let textview = new Gtk.TextView({ buffer: buffer });
|
||||
textview.override_font(Pango.font_description_from_string('monospace'));
|
||||
scroll.add(textview);
|
||||
box.add(scroll);
|
||||
|
||||
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;
|
||||
box.show_all();
|
||||
return box;
|
||||
}
|
||||
|
||||
_buildUI(app) {
|
||||
@@ -229,12 +147,8 @@ var Application = 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));
|
||||
@@ -242,8 +156,6 @@ var Application = 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]) => {
|
||||
@@ -288,11 +200,6 @@ var Application = class {
|
||||
}
|
||||
|
||||
_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;
|
||||
@@ -332,171 +239,6 @@ var Application = class {
|
||||
}
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
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 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) {
|
||||
|
@@ -10,7 +10,6 @@ const Animation = imports.ui.animation;
|
||||
const Batch = imports.gdm.batch;
|
||||
const GdmUtil = imports.gdm.util;
|
||||
const Params = imports.misc.params;
|
||||
const Shell = imports.gi.Shell;
|
||||
const ShellEntry = imports.ui.shellEntry;
|
||||
const Tweener = imports.ui.tweener;
|
||||
const UserWidget = imports.ui.userWidget;
|
||||
@@ -97,7 +96,7 @@ var AuthPrompt = 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, actionMode: Shell.ActionMode.NONE });
|
||||
ShellEntry.addContextMenu(this._entry, { isPassword: true });
|
||||
|
||||
this.actor.add(this._entry,
|
||||
{ expand: true,
|
||||
|
@@ -23,6 +23,7 @@ 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 Meta = imports.gi.Meta;
|
||||
const Pango = imports.gi.Pango;
|
||||
const Shell = imports.gi.Shell;
|
||||
@@ -160,8 +161,8 @@ Signals.addSignalMethods(UserListItem.prototype);
|
||||
var UserList = class {
|
||||
constructor() {
|
||||
this.actor = new St.ScrollView({ style_class: 'login-dialog-user-list-view'});
|
||||
this.actor.set_policy(St.PolicyType.NEVER,
|
||||
St.PolicyType.AUTOMATIC);
|
||||
this.actor.set_policy(Gtk.PolicyType.NEVER,
|
||||
Gtk.PolicyType.AUTOMATIC);
|
||||
|
||||
this._box = new St.BoxLayout({ vertical: true,
|
||||
style_class: 'login-dialog-user-list',
|
||||
@@ -182,7 +183,7 @@ var UserList = class {
|
||||
if (global.stage.get_key_focus() != this.actor)
|
||||
return;
|
||||
|
||||
let focusSet = this.actor.navigate_focus(null, St.DirectionType.TAB_FORWARD, false);
|
||||
let focusSet = this.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
|
||||
if (!focusSet) {
|
||||
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
|
||||
this._moveFocusToItems();
|
||||
@@ -334,8 +335,7 @@ var SessionMenuButton = class {
|
||||
this._button.remove_style_pseudo_class('active');
|
||||
});
|
||||
|
||||
this._manager = new PopupMenu.PopupMenuManager({ actor: this._button },
|
||||
{ actionMode: Shell.ActionMode.NONE });
|
||||
this._manager = new PopupMenu.PopupMenuManager({ actor: this._button });
|
||||
this._manager.addMenu(this._menu);
|
||||
|
||||
this._button.connect('clicked', () => { this._menu.toggle(); });
|
||||
@@ -473,8 +473,8 @@ var LoginDialog = GObject.registerClass({
|
||||
|
||||
this._bannerView = new St.ScrollView({ style_class: 'login-dialog-banner-view',
|
||||
opacity: 0,
|
||||
vscrollbar_policy: St.PolicyType.AUTOMATIC,
|
||||
hscrollbar_policy: St.PolicyType.NEVER });
|
||||
vscrollbar_policy: Gtk.PolicyType.AUTOMATIC,
|
||||
hscrollbar_policy: Gtk.PolicyType.NEVER });
|
||||
this.add_child(this._bannerView);
|
||||
|
||||
let bannerBox = new St.BoxLayout({ vertical: true });
|
||||
|
@@ -78,7 +78,6 @@
|
||||
<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>
|
||||
|
@@ -3,7 +3,6 @@
|
||||
// Common utils for the extension system and the extension
|
||||
// preferences tool
|
||||
|
||||
const Gettext = imports.gettext;
|
||||
const Signals = imports.signals;
|
||||
|
||||
const Gio = imports.gi.Gio;
|
||||
@@ -64,66 +63,6 @@ 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,7 +160,7 @@ var ObjectManager = class {
|
||||
try {
|
||||
initable.init_finish(result);
|
||||
} catch(e) {
|
||||
logError(e, 'could not initialize object manager for object ' + this._serviceName);
|
||||
logError(e, 'could not initialize object manager for object ' + params.name);
|
||||
|
||||
this._tryToCompleteLoad();
|
||||
return;
|
||||
@@ -281,8 +281,8 @@ var ObjectManager = class {
|
||||
let object = this._objects[objectPaths];
|
||||
|
||||
let interfaceNames = Object.keys(object);
|
||||
for (let j = 0; j < interfaceNames.length; j++) {
|
||||
let interfaceName = interfaceNames[j];
|
||||
for (let j = 0; i < interfaceNames.length; i++) {
|
||||
let interfaceName = interfaceNames[i];
|
||||
if (object[interfaceName])
|
||||
proxies.push(object(interfaceName));
|
||||
}
|
||||
|
@@ -61,8 +61,8 @@ var WeatherClient = class {
|
||||
this.emit('changed');
|
||||
});
|
||||
|
||||
this._weatherAppMon = new Util.AppSettingsMonitor('org.gnome.Weather.desktop',
|
||||
'org.gnome.Weather');
|
||||
this._weatherAppMon = new Util.AppSettingsMonitor('org.gnome.Weather.Application.desktop',
|
||||
'org.gnome.Weather.Application');
|
||||
this._weatherAppMon.connect('available-changed', () => { this.emit('changed'); });
|
||||
this._weatherAppMon.watchSetting('automatic-location',
|
||||
this._onAutomaticLocationChanged.bind(this));
|
||||
@@ -234,7 +234,7 @@ var WeatherClient = class {
|
||||
if (table != 'gnome' || id != 'geolocation')
|
||||
return;
|
||||
|
||||
let permission = perms['org.gnome.Weather'] || ['NONE'];
|
||||
let permission = perms['org.gnome.Weather.Application'] || ['NONE'];
|
||||
let [accuracy] = permission;
|
||||
this._weatherAuthorized = accuracy != 'NONE';
|
||||
|
||||
|
@@ -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");
|
||||
|
@@ -89,7 +89,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");
|
||||
|
@@ -4,6 +4,7 @@ const Clutter = imports.gi.Clutter;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const GObject = imports.gi.GObject;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Signals = imports.signals;
|
||||
const Meta = imports.gi.Meta;
|
||||
@@ -19,7 +20,6 @@ const IconGrid = imports.ui.iconGrid;
|
||||
const Main = imports.ui.main;
|
||||
const Overview = imports.ui.overview;
|
||||
const OverviewControls = imports.ui.overviewControls;
|
||||
const PageIndicators = imports.ui.pageIndicators;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
const Tweener = imports.ui.tweener;
|
||||
const Workspace = imports.ui.workspace;
|
||||
@@ -175,7 +175,7 @@ class BaseAppView {
|
||||
|
||||
_selectAppInternal(id) {
|
||||
if (this._items[id])
|
||||
this._items[id].actor.navigate_focus(null, St.DirectionType.TAB_FORWARD, false);
|
||||
this._items[id].actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
|
||||
else
|
||||
log('No such application ' + id);
|
||||
}
|
||||
@@ -246,6 +246,116 @@ class BaseAppView {
|
||||
};
|
||||
Signals.addSignalMethods(BaseAppView.prototype);
|
||||
|
||||
var PageIndicatorsActor = GObject.registerClass(
|
||||
class PageIndicatorsActor extends St.BoxLayout {
|
||||
_init() {
|
||||
super._init({ style_class: 'page-indicators',
|
||||
vertical: true,
|
||||
x_expand: true, y_expand: true,
|
||||
x_align: Clutter.ActorAlign.END,
|
||||
y_align: Clutter.ActorAlign.CENTER,
|
||||
reactive: true,
|
||||
clip_to_allocation: true });
|
||||
}
|
||||
|
||||
vfunc_get_preferred_height(forWidth) {
|
||||
// We want to request the natural height of all our children as our
|
||||
// natural height, so we chain up to St.BoxLayout, but we only request 0
|
||||
// as minimum height, since it's not that important if some indicators
|
||||
// are not shown
|
||||
let [, natHeight] = super.vfunc_get_preferred_height(forWidth);
|
||||
return [0, natHeight];
|
||||
}
|
||||
});
|
||||
|
||||
class PageIndicators {
|
||||
constructor() {
|
||||
this.actor = new PageIndicatorsActor();
|
||||
this._nPages = 0;
|
||||
this._currentPage = undefined;
|
||||
|
||||
this.actor.connect('notify::mapped', () => {
|
||||
this.animateIndicators(IconGrid.AnimationDirection.IN);
|
||||
});
|
||||
}
|
||||
|
||||
setNPages(nPages) {
|
||||
if (this._nPages == nPages)
|
||||
return;
|
||||
|
||||
let diff = nPages - this._nPages;
|
||||
if (diff > 0) {
|
||||
for (let i = 0; i < diff; i++) {
|
||||
let pageIndex = this._nPages + i;
|
||||
let indicator = new St.Button({ style_class: 'page-indicator',
|
||||
button_mask: St.ButtonMask.ONE |
|
||||
St.ButtonMask.TWO |
|
||||
St.ButtonMask.THREE,
|
||||
toggle_mode: true,
|
||||
checked: pageIndex == this._currentPage });
|
||||
indicator.child = new St.Widget({ style_class: 'page-indicator-icon' });
|
||||
indicator.connect('clicked', () => {
|
||||
this.emit('page-activated', pageIndex);
|
||||
});
|
||||
this.actor.add_actor(indicator);
|
||||
}
|
||||
} else {
|
||||
let children = this.actor.get_children().splice(diff);
|
||||
for (let i = 0; i < children.length; i++)
|
||||
children[i].destroy();
|
||||
}
|
||||
this._nPages = nPages;
|
||||
this.actor.visible = (this._nPages > 1);
|
||||
}
|
||||
|
||||
setCurrentPage(currentPage) {
|
||||
this._currentPage = currentPage;
|
||||
|
||||
let children = this.actor.get_children();
|
||||
for (let i = 0; i < children.length; i++)
|
||||
children[i].set_checked(i == this._currentPage);
|
||||
}
|
||||
|
||||
animateIndicators(animationDirection) {
|
||||
if (!this.actor.mapped)
|
||||
return;
|
||||
|
||||
let children = this.actor.get_children();
|
||||
if (children.length == 0)
|
||||
return;
|
||||
|
||||
for (let i = 0; i < this._nPages; i++)
|
||||
Tweener.removeTweens(children[i]);
|
||||
|
||||
let offset;
|
||||
if (this.actor.get_text_direction() == Clutter.TextDirection.RTL)
|
||||
offset = -children[0].width;
|
||||
else
|
||||
offset = children[0].width;
|
||||
|
||||
let isAnimationIn = animationDirection == IconGrid.AnimationDirection.IN;
|
||||
let delay = isAnimationIn ? INDICATORS_ANIMATION_DELAY :
|
||||
INDICATORS_ANIMATION_DELAY_OUT;
|
||||
let baseTime = isAnimationIn ? INDICATORS_BASE_TIME : INDICATORS_BASE_TIME_OUT;
|
||||
let totalAnimationTime = baseTime + delay * this._nPages;
|
||||
let maxTime = isAnimationIn ? INDICATORS_ANIMATION_MAX_TIME :
|
||||
INDICATORS_ANIMATION_MAX_TIME_OUT;
|
||||
if (totalAnimationTime > maxTime)
|
||||
delay -= (totalAnimationTime - maxTime) / this._nPages;
|
||||
|
||||
for (let i = 0; i < this._nPages; i++) {
|
||||
children[i].translation_x = isAnimationIn ? offset : 0;
|
||||
Tweener.addTween(children[i],
|
||||
{ translation_x: isAnimationIn ? 0 : offset,
|
||||
time: baseTime + delay * i,
|
||||
transition: 'easeInOutQuad',
|
||||
delay: isAnimationIn ? VIEWS_SWITCH_ANIMATION_DELAY : 0
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
Signals.addSignalMethods(PageIndicators.prototype);
|
||||
|
||||
var AllView = class AllView extends BaseAppView {
|
||||
constructor() {
|
||||
super({ usePagination: true }, null);
|
||||
@@ -260,17 +370,17 @@ var AllView = class AllView extends BaseAppView {
|
||||
x_expand:true, y_expand:true });
|
||||
this.actor.add_actor(this._scrollView);
|
||||
|
||||
this._scrollView.set_policy(St.PolicyType.NEVER,
|
||||
St.PolicyType.EXTERNAL);
|
||||
this._scrollView.set_policy(Gtk.PolicyType.NEVER,
|
||||
Gtk.PolicyType.EXTERNAL);
|
||||
this._adjustment = this._scrollView.vscroll.adjustment;
|
||||
|
||||
this._pageIndicators = new PageIndicators.AnimatedPageIndicators();
|
||||
this._pageIndicators = new PageIndicators();
|
||||
this._pageIndicators.connect('page-activated',
|
||||
(indicators, pageIndex) => {
|
||||
this.goToPage(pageIndex);
|
||||
});
|
||||
this._pageIndicators.connect('scroll-event', this._onScroll.bind(this));
|
||||
this.actor.add_actor(this._pageIndicators);
|
||||
this._pageIndicators.actor.connect('scroll-event', this._onScroll.bind(this));
|
||||
this.actor.add_actor(this._pageIndicators.actor);
|
||||
|
||||
this.folderIcons = [];
|
||||
|
||||
@@ -377,21 +487,15 @@ var AllView = class AllView extends BaseAppView {
|
||||
});
|
||||
}
|
||||
|
||||
getAppInfos() {
|
||||
return this._appInfoList;
|
||||
}
|
||||
|
||||
_loadApps() {
|
||||
this._appInfoList = Shell.AppSystem.get_default().get_installed().filter(appInfo => {
|
||||
let apps = Gio.AppInfo.get_all().filter(appInfo => {
|
||||
try {
|
||||
let id = appInfo.get_id(); // catch invalid file encodings
|
||||
} catch(e) {
|
||||
return false;
|
||||
}
|
||||
return appInfo.should_show();
|
||||
});
|
||||
|
||||
let apps = this._appInfoList.map(app => app.get_id());
|
||||
}).map(app => app.get_id());
|
||||
|
||||
let appSys = Shell.AppSystem.get_default();
|
||||
|
||||
@@ -1014,7 +1118,7 @@ var FolderView = class FolderView extends BaseAppView {
|
||||
this._grid.x_expand = true;
|
||||
|
||||
this.actor = new St.ScrollView({ overlay_scrollbars: true });
|
||||
this.actor.set_policy(St.PolicyType.NEVER, St.PolicyType.AUTOMATIC);
|
||||
this.actor.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
|
||||
let scrollableContainer = new St.BoxLayout({ vertical: true, reactive: true });
|
||||
scrollableContainer.add_actor(this._grid);
|
||||
this.actor.add_actor(scrollableContainer);
|
||||
@@ -1194,13 +1298,15 @@ var FolderIcon = class FolderIcon {
|
||||
folderApps.forEach(addAppId);
|
||||
|
||||
let folderCategories = this._folder.get_strv('categories');
|
||||
let appInfos = this._parentView.getAppInfos();
|
||||
appInfos.forEach(appInfo => {
|
||||
Gio.AppInfo.get_all().forEach(appInfo => {
|
||||
let appCategories = _getCategories(appInfo);
|
||||
if (!_listsIntersect(folderCategories, appCategories))
|
||||
return;
|
||||
|
||||
addAppId(appInfo.get_id());
|
||||
try {
|
||||
addAppId(appInfo.get_id()); // catch invalid file encodings
|
||||
} catch(e) {
|
||||
}
|
||||
});
|
||||
|
||||
this.actor.visible = this.view.getAllItems().length > 0;
|
||||
@@ -1358,18 +1464,18 @@ var AppFolderPopup = class AppFolderPopup {
|
||||
let isLtr = Clutter.get_default_text_direction() == Clutter.TextDirection.LTR;
|
||||
switch (event.get_key_symbol()) {
|
||||
case Clutter.Down:
|
||||
direction = St.DirectionType.TAB_FORWARD;
|
||||
direction = Gtk.DirectionType.TAB_FORWARD;
|
||||
break;
|
||||
case Clutter.Right:
|
||||
direction = isLtr ? St.DirectionType.TAB_FORWARD :
|
||||
St.DirectionType.TAB_BACKWARD;
|
||||
direction = isLtr ? Gtk.DirectionType.TAB_FORWARD :
|
||||
Gtk.DirectionType.TAB_BACKWARD;
|
||||
break;
|
||||
case Clutter.Up:
|
||||
direction = St.DirectionType.TAB_BACKWARD;
|
||||
direction = Gtk.DirectionType.TAB_BACKWARD;
|
||||
break;
|
||||
case Clutter.Left:
|
||||
direction = isLtr ? St.DirectionType.TAB_BACKWARD :
|
||||
St.DirectionType.TAB_FORWARD;
|
||||
direction = isLtr ? Gtk.DirectionType.TAB_BACKWARD :
|
||||
Gtk.DirectionType.TAB_FORWARD;
|
||||
break;
|
||||
default:
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
@@ -1580,7 +1686,7 @@ var AppIcon = class AppIcon {
|
||||
|
||||
_onKeyboardPopupMenu() {
|
||||
this.popupMenu();
|
||||
this._menu.actor.navigate_focus(null, St.DirectionType.TAB_FORWARD, false);
|
||||
this._menu.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
|
||||
}
|
||||
|
||||
getId() {
|
||||
|
@@ -36,14 +36,13 @@ const RENAMED_DESKTOP_IDS = {
|
||||
'gnome-software.desktop': 'org.gnome.Software.desktop',
|
||||
'gnome-terminal.desktop': 'org.gnome.Terminal.desktop',
|
||||
'gnome-tweaks.desktop': 'org.gnome.tweaks.desktop',
|
||||
'gnome-weather.desktop': 'org.gnome.Weather.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',
|
||||
'iagno.desktop': 'org.gnome.Iagno.desktop',
|
||||
'nautilus.desktop': 'org.gnome.Nautilus.desktop',
|
||||
'org.gnome.Weather.Application.desktop': 'org.gnome.Weather.desktop',
|
||||
'polari.desktop': 'org.gnome.Polari.desktop',
|
||||
'totem.desktop': 'org.gnome.Totem.desktop',
|
||||
'evince.desktop': 'org.gnome.Evince.desktop',
|
||||
@@ -154,7 +153,7 @@ class AppFavorites {
|
||||
}
|
||||
|
||||
_removeFavorite(appId) {
|
||||
if (!(appId in this._favorites))
|
||||
if (!appId in this._favorites)
|
||||
return false;
|
||||
|
||||
let ids = this._getIds().filter(id => id != appId);
|
||||
|
@@ -3,6 +3,7 @@
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const St = imports.gi.St;
|
||||
const Signals = imports.signals;
|
||||
const Shell = imports.gi.Shell;
|
||||
@@ -1082,7 +1083,7 @@ var CalendarMessageList = class CalendarMessageList {
|
||||
overlay_scrollbars: true,
|
||||
x_expand: true, y_expand: true,
|
||||
x_fill: true, y_fill: true });
|
||||
this._scrollView.set_policy(St.PolicyType.NEVER, St.PolicyType.AUTOMATIC);
|
||||
this._scrollView.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
|
||||
box.add_actor(this._scrollView);
|
||||
|
||||
this._clearButton = new St.Button({ style_class: 'message-list-clear-button button',
|
||||
|
@@ -111,10 +111,10 @@ var NetworkSecretDialog = class extends ModalDialog.ModalDialog {
|
||||
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 });
|
||||
messageBox.add(descriptionLabel,
|
||||
{ y_fill: true,
|
||||
y_align: St.Align.START,
|
||||
expand: true });
|
||||
}
|
||||
|
||||
this._okButton = { label: _("Connect"),
|
||||
@@ -705,14 +705,14 @@ var NetworkAgent = class {
|
||||
if (hints.indexOf('pin') != -1) {
|
||||
let gsmSetting = connection.get_setting_gsm();
|
||||
title = _("PIN code required");
|
||||
body = _("PIN code is needed for the mobile broadband device");
|
||||
message = _("PIN code is needed for the mobile broadband device");
|
||||
break;
|
||||
}
|
||||
// fall through
|
||||
case 'cdma':
|
||||
case 'bluetooth':
|
||||
title = _("Mobile broadband network password");
|
||||
body = _("A password is required to connect to “%s”.").format(connectionSetting.get_id());
|
||||
message = _("A password is required to connect to “%s”.").format(connectionSetting.get_id());
|
||||
break;
|
||||
default:
|
||||
log('Invalid connection type: ' + connectionType);
|
||||
|
@@ -4,6 +4,7 @@ const Clutter = imports.gi.Clutter;
|
||||
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 Mainloop = imports.mainloop;
|
||||
const Signals = imports.signals;
|
||||
@@ -820,8 +821,8 @@ var ChatNotificationBanner = class extends MessageTray.NotificationBanner {
|
||||
});
|
||||
|
||||
this._scrollArea = new St.ScrollView({ style_class: 'chat-scrollview vfade',
|
||||
vscrollbar_policy: St.PolicyType.AUTOMATIC,
|
||||
hscrollbar_policy: St.PolicyType.NEVER,
|
||||
vscrollbar_policy: Gtk.PolicyType.AUTOMATIC,
|
||||
hscrollbar_policy: Gtk.PolicyType.NEVER,
|
||||
visible: this.expanded });
|
||||
this._contentArea = new St.BoxLayout({ style_class: 'chat-body',
|
||||
vertical: true });
|
||||
|
@@ -1,6 +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 St = imports.gi.St;
|
||||
@@ -57,7 +58,7 @@ var CtrlAltTabManager = class CtrlAltTabManager {
|
||||
if (item.focusCallback)
|
||||
item.focusCallback(timestamp);
|
||||
else
|
||||
item.root.navigate_focus(null, St.DirectionType.TAB_FORWARD, false);
|
||||
item.root.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
|
||||
}
|
||||
|
||||
// Sort the items into a consistent order; panel first, tray last,
|
||||
|
@@ -4,6 +4,7 @@ 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 Mainloop = imports.mainloop;
|
||||
const Pango = imports.gi.Pango;
|
||||
@@ -22,8 +23,6 @@ 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() &&
|
||||
@@ -156,27 +155,18 @@ var WorldClocksSection = class WorldClocksSection {
|
||||
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' });
|
||||
|
||||
let offset = l.get_timezone().get_offset() / 60.;
|
||||
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 });
|
||||
let time = new St.Label({ style_class: 'world-clocks-time',
|
||||
x_align: Clutter.ActorAlign.END,
|
||||
x_expand: true });
|
||||
|
||||
if (this._grid.text_direction == Clutter.TextDirection.RTL) {
|
||||
layout.attach(tz, 0, i + 1, 1, 1);
|
||||
layout.attach(time, 1, i + 1, 1, 1);
|
||||
layout.attach(label, 2, i + 1, 1, 1);
|
||||
layout.attach(time, 0, i + 1, 1, 1);
|
||||
layout.attach(label, 1, 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;
|
||||
@@ -227,114 +217,110 @@ var WeatherSection = class WeatherSection {
|
||||
|
||||
this.actor.child = box;
|
||||
|
||||
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);
|
||||
box.add_child(new St.Label({ style_class: 'weather-header',
|
||||
x_align: Clutter.ActorAlign.START,
|
||||
text: _("Weather") }));
|
||||
|
||||
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._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._weatherClient.connect('changed', this._sync.bind(this));
|
||||
this._sync();
|
||||
}
|
||||
|
||||
_getInfos() {
|
||||
_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() {
|
||||
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();
|
||||
let datetime = new Date(timestamp * 1000);
|
||||
if (!_isToday(datetime))
|
||||
if (!_isToday(new Date(timestamp * 1000)))
|
||||
continue; // Ignore forecasts from other days
|
||||
|
||||
[ok, timestamp] = current.get_value_update();
|
||||
let currenttime = new Date(timestamp * 1000);
|
||||
if (currenttime.getHours() == datetime.getHours())
|
||||
continue; // Enforce a minimum interval of 1h
|
||||
if (this._sameSummary(current, forecasts[i]))
|
||||
continue; // Ignore consecutive runs of equal summaries
|
||||
|
||||
current = forecasts[i];
|
||||
if (infos.push(current) == MAX_FORECASTS)
|
||||
break; // Use a maximum of five forecasts
|
||||
if (infos.push(current) == 3)
|
||||
break; // Use a maximum of three summaries
|
||||
}
|
||||
return infos;
|
||||
}
|
||||
|
||||
_addForecasts() {
|
||||
let layout = this._forecastGrid.layout_manager;
|
||||
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;
|
||||
|
||||
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 2: fmt = _("%s, then %s later."); break;
|
||||
|
||||
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++;
|
||||
/* 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);
|
||||
});
|
||||
return String.prototype.format.apply(fmt, summaries);
|
||||
}
|
||||
|
||||
_setStatusLabel(text) {
|
||||
let layout = this._forecastGrid.layout_manager;
|
||||
let label = new St.Label({ text });
|
||||
layout.attach(label, 0, 0, 1, 1);
|
||||
}
|
||||
_getLabelText() {
|
||||
if (!this._weatherClient.hasLocation)
|
||||
return _("Select a location…");
|
||||
|
||||
_updateForecasts() {
|
||||
this._forecastGrid.destroy_all_children();
|
||||
|
||||
if (!this._weatherClient.hasLocation) {
|
||||
this._setStatusLabel(_("Select a location…"));
|
||||
return;
|
||||
}
|
||||
if (this._weatherClient.loading)
|
||||
return _("Loading…");
|
||||
|
||||
let info = this._weatherClient.info;
|
||||
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.is_valid())
|
||||
return this._getSummaryText() + ' ' +
|
||||
/* Translators: %s is a temperature with unit, e.g. "23℃" */
|
||||
_("Feels like %s.").format(info.get_apparent());
|
||||
|
||||
if (info.network_error())
|
||||
this._setStatusLabel(_("Go online for weather information"));
|
||||
else
|
||||
this._setStatusLabel(_("Weather information is currently unavailable"));
|
||||
return _("Go online for weather information");
|
||||
|
||||
return _("Weather information is currently unavailable");
|
||||
}
|
||||
|
||||
_sync() {
|
||||
@@ -343,9 +329,7 @@ var WeatherSection = class WeatherSection {
|
||||
if (!this.actor.visible)
|
||||
return;
|
||||
|
||||
this._titleLocation.visible = this._weatherClient.hasLocation;
|
||||
|
||||
this._updateForecasts();
|
||||
this._conditionsLabel.text = this._getLabelText();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -394,13 +378,13 @@ class IndicatorPad extends St.Widget {
|
||||
super._init();
|
||||
}
|
||||
|
||||
vfunc_get_preferred_width(forHeight) {
|
||||
vfunc_get_preferred_width(container, forHeight) {
|
||||
if (this._source.visible)
|
||||
return this._source.get_preferred_width(forHeight);
|
||||
return [0, 0];
|
||||
}
|
||||
|
||||
vfunc_get_preferred_height(forWidth) {
|
||||
vfunc_get_preferred_height(container, forWidth) {
|
||||
if (this._source.visible)
|
||||
return this._source.get_preferred_height(forWidth);
|
||||
return [0, 0];
|
||||
@@ -531,7 +515,7 @@ class DateMenuButton extends PanelMenu.Button {
|
||||
this._displaysSection = new St.ScrollView({ style_class: 'datemenu-displays-section vfade',
|
||||
x_expand: true, x_fill: true,
|
||||
overlay_scrollbars: true });
|
||||
this._displaysSection.set_policy(St.PolicyType.NEVER, St.PolicyType.AUTOMATIC);
|
||||
this._displaysSection.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
|
||||
vbox.add_actor(this._displaysSection);
|
||||
|
||||
let displaysBox = new St.BoxLayout({ vertical: true,
|
||||
|
94
js/ui/dnd.js
94
js/ui/dnd.js
@@ -2,6 +2,7 @@
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const St = imports.gi.St;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Shell = imports.gi.Shell;
|
||||
@@ -108,7 +109,6 @@ var _Draggable = class _Draggable {
|
||||
this._dragCancellable = true;
|
||||
|
||||
this._eventsGrabbed = false;
|
||||
this._capturedEventId = 0;
|
||||
}
|
||||
|
||||
_onButtonPress(actor, event) {
|
||||
@@ -119,7 +119,7 @@ var _Draggable = class _Draggable {
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
||||
this._buttonDown = true;
|
||||
this._grabActor(event.get_device());
|
||||
this._grabActor();
|
||||
|
||||
let [stageX, stageY] = event.get_coords();
|
||||
this._dragStartX = stageX;
|
||||
@@ -136,8 +136,10 @@ var _Draggable = class _Draggable {
|
||||
if (Tweener.getTweenCount(actor))
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
||||
this._touchSequence = event.get_event_sequence();
|
||||
|
||||
this._buttonDown = true;
|
||||
this._grabActor(event.get_device(), event.get_event_sequence());
|
||||
this._grabActor();
|
||||
|
||||
let [stageX, stageY] = event.get_coords();
|
||||
this._dragStartX = stageX;
|
||||
@@ -146,30 +148,19 @@ var _Draggable = class _Draggable {
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
}
|
||||
|
||||
_grabDevice(actor, pointer, touchSequence) {
|
||||
if (touchSequence)
|
||||
pointer.sequence_grab(touchSequence, actor);
|
||||
_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);
|
||||
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
|
||||
@@ -179,8 +170,8 @@ var _Draggable = class _Draggable {
|
||||
this._grabbedDevice = null;
|
||||
}
|
||||
|
||||
_grabActor(device, touchSequence) {
|
||||
this._grabDevice(this.actor, device, touchSequence);
|
||||
_grabActor() {
|
||||
this._grabDevice(this.actor);
|
||||
this._onEventId = this.actor.connect('event',
|
||||
this._onEvent.bind(this));
|
||||
}
|
||||
@@ -194,11 +185,11 @@ var _Draggable = class _Draggable {
|
||||
this._onEventId = null;
|
||||
}
|
||||
|
||||
_grabEvents(device, touchSequence) {
|
||||
_grabEvents() {
|
||||
if (!this._eventsGrabbed) {
|
||||
this._eventsGrabbed = Main.pushModal(_getEventHandlerActor());
|
||||
if (this._eventsGrabbed)
|
||||
this._grabDevice(_getEventHandlerActor(), device, touchSequence);
|
||||
this._grabDevice(_getEventHandlerActor());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,36 +201,14 @@ var _Draggable = class _Draggable {
|
||||
}
|
||||
}
|
||||
|
||||
_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 (this._eventIsRelease(event)) {
|
||||
if (event.type() == Clutter.EventType.BUTTON_RELEASE ||
|
||||
(event.type() == Clutter.EventType.TOUCH_END &&
|
||||
global.display.is_pointer_emulating_sequence(event.get_event_sequence()))) {
|
||||
this._buttonDown = false;
|
||||
if (this._dragState == DragState.DRAGGING) {
|
||||
return this._dragActorDropped(event);
|
||||
@@ -299,19 +268,7 @@ var _Draggable = class _Draggable {
|
||||
* This function is useful to call if you've specified manualMode
|
||||
* for the draggable.
|
||||
*/
|
||||
startDrag(stageX, stageY, time, sequence, device) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
startDrag(stageX, stageY, time, sequence) {
|
||||
currentDraggable = this;
|
||||
this._dragState = DragState.DRAGGING;
|
||||
|
||||
@@ -326,7 +283,8 @@ var _Draggable = class _Draggable {
|
||||
if (this._onEventId)
|
||||
this._ungrabActor();
|
||||
|
||||
this._grabEvents(device, sequence);
|
||||
this._touchSequence = sequence;
|
||||
this._grabEvents();
|
||||
global.display.set_cursor(Meta.Cursor.DND_IN_DRAG);
|
||||
|
||||
this._dragX = this._dragStartX = stageX;
|
||||
@@ -394,8 +352,7 @@ var _Draggable = class _Draggable {
|
||||
this._finishAnimation();
|
||||
|
||||
this._dragActor = null;
|
||||
if (this._dragState == DragState.DRAGGING)
|
||||
this._dragState = DragState.CANCELLED;
|
||||
this._dragState = DragState.CANCELLED;
|
||||
});
|
||||
this._dragOrigOpacity = this._dragActor.opacity;
|
||||
if (this._dragActorOpacity != undefined)
|
||||
@@ -441,11 +398,10 @@ var _Draggable = class _Draggable {
|
||||
let [stageX, stageY] = event.get_coords();
|
||||
|
||||
// See if the user has moved the mouse enough to trigger a drag
|
||||
let threshold = St.Settings.get().drag_threshold;
|
||||
if (!currentDraggable &&
|
||||
(Math.abs(stageX - this._dragStartX) > threshold ||
|
||||
let threshold = Gtk.Settings.get_default().gtk_dnd_drag_threshold;
|
||||
if ((Math.abs(stageX - this._dragStartX) > threshold ||
|
||||
Math.abs(stageY - this._dragStartY) > threshold)) {
|
||||
this.startDrag(stageX, stageY, event.get_time(), this._touchSequence, event.get_device());
|
||||
this.startDrag(stageX, stageY, event.get_time(), this._touchSequence);
|
||||
this._updateDragPosition(event);
|
||||
}
|
||||
|
||||
|
@@ -30,7 +30,7 @@ var EdgeDragAction = GObject.registerClass({
|
||||
return global.display.get_monitor_geometry(monitorIndex);
|
||||
}
|
||||
|
||||
vfunc_gesture_prepare(actor) {
|
||||
vfunc_gesture_prepare(action, actor) {
|
||||
if (this.get_n_current_points() == 0)
|
||||
return false;
|
||||
|
||||
@@ -46,7 +46,7 @@ var EdgeDragAction = GObject.registerClass({
|
||||
(this._side == St.Side.BOTTOM && y > monitorRect.y + monitorRect.height - EDGE_THRESHOLD));
|
||||
}
|
||||
|
||||
vfunc_gesture_progress(actor) {
|
||||
vfunc_gesture_progress(action, actor) {
|
||||
let [startX, startY] = this.get_press_coords(0);
|
||||
let [x, y] = this.get_motion_coords(0);
|
||||
let offsetX = Math.abs (x - startX);
|
||||
@@ -66,7 +66,7 @@ var EdgeDragAction = GObject.registerClass({
|
||||
return true;
|
||||
}
|
||||
|
||||
vfunc_gesture_end(actor) {
|
||||
vfunc_gesture_end(action, actor) {
|
||||
let [startX, startY] = this.get_press_coords(0);
|
||||
let [x, y] = this.get_motion_coords(0);
|
||||
let monitorRect = this._getMonitorRect(startX, startY);
|
||||
|
@@ -22,6 +22,7 @@ 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;
|
||||
@@ -319,7 +320,7 @@ var EndSessionDialog = class EndSessionDialog extends ModalDialog.ModalDialog {
|
||||
messageLayout.add(this._batteryWarning);
|
||||
|
||||
this._scrollView = new St.ScrollView({ style_class: 'end-session-dialog-list' });
|
||||
this._scrollView.set_policy(St.PolicyType.NEVER, St.PolicyType.AUTOMATIC);
|
||||
this._scrollView.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
|
||||
this.contentLayout.add(this._scrollView,
|
||||
{ x_fill: true,
|
||||
y_fill: true });
|
||||
|
@@ -4,6 +4,7 @@ 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';
|
||||
|
@@ -1,6 +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 St = imports.gi.St;
|
||||
@@ -186,7 +187,7 @@ var GrabHelper = class GrabHelper {
|
||||
if (params.focus) {
|
||||
params.focus.grab_key_focus();
|
||||
} else if (newFocus && hadFocus) {
|
||||
if (!newFocus.navigate_focus(null, St.DirectionType.TAB_FORWARD, false))
|
||||
if (!newFocus.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false))
|
||||
newFocus.grab_key_focus();
|
||||
}
|
||||
|
||||
|
@@ -236,7 +236,7 @@ var CandidatePopup = class CandidatePopup {
|
||||
|
||||
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();
|
||||
@@ -295,7 +295,7 @@ var CandidatePopup = class CandidatePopup {
|
||||
|
||||
_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());
|
||||
}
|
||||
|
@@ -2,6 +2,7 @@
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const GObject = imports.gi.GObject;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Signals = imports.signals;
|
||||
@@ -669,7 +670,7 @@ var IconGrid = GObject.registerClass({
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -905,8 +906,10 @@ var PaginatedIconGrid = GObject.registerClass({
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -921,9 +924,10 @@ var PaginatedIconGrid = GObject.registerClass({
|
||||
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;
|
||||
|
||||
@@ -955,8 +959,8 @@ var PaginatedIconGrid = GObject.registerClass({
|
||||
this._translatedChildren = [];
|
||||
this.emit('space-opened');
|
||||
} else {
|
||||
this._translateChildren(childrenUp, St.DirectionType.UP, nRowsUp);
|
||||
this._translateChildren(childrenDown, St.DirectionType.DOWN, nRowsDown);
|
||||
this._translateChildren(childrenUp, Gtk.DirectionType.UP, nRowsUp);
|
||||
this._translateChildren(childrenDown, Gtk.DirectionType.DOWN, nRowsDown);
|
||||
this._translatedChildren = childrenUp.concat(childrenDown);
|
||||
}
|
||||
}
|
||||
@@ -966,7 +970,7 @@ var PaginatedIconGrid = GObject.registerClass({
|
||||
if (translationY == 0)
|
||||
return;
|
||||
|
||||
if (direction == St.DirectionType.UP)
|
||||
if (direction == Gtk.DirectionType.UP)
|
||||
translationY *= -1;
|
||||
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
|
@@ -8,7 +8,7 @@ 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 = GObject.registerClass(
|
||||
var KbdA11yDialog = new GObject.registerClass(
|
||||
class KbdA11yDialog extends GObject.Object {
|
||||
_init() {
|
||||
super._init();
|
||||
|
@@ -2,6 +2,7 @@
|
||||
|
||||
const Atspi = imports.gi.Atspi;
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Gdk = imports.gi.Gdk;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const GObject = imports.gi.GObject;
|
||||
@@ -15,15 +16,12 @@ const IBusManager = imports.misc.ibusManager;
|
||||
const BoxPointer = imports.ui.boxpointer;
|
||||
const Layout = imports.ui.layout;
|
||||
const Main = imports.ui.main;
|
||||
const PageIndicators = imports.ui.pageIndicators;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
const Tweener = imports.ui.tweener;
|
||||
const Util = imports.misc.util;
|
||||
|
||||
var KEYBOARD_REST_TIME = Layout.KEYBOARD_ANIMATION_TIME * 2 * 1000;
|
||||
var KEY_LONG_PRESS_TIME = 250;
|
||||
var PANEL_SWITCH_ANIMATION_TIME = 0.5;
|
||||
var PANEL_SWITCH_RELATIVE_DISTANCE = 1 / 3; /* A third of the actor width */
|
||||
|
||||
const A11Y_APPLICATIONS_SCHEMA = 'org.gnome.desktop.a11y.applications';
|
||||
const SHOW_KEYBOARD = 'screen-keyboard-enabled';
|
||||
@@ -42,66 +40,28 @@ const defaultKeysPost = [
|
||||
[ [{ label: '⌫', width: 1.5, keyval: Clutter.KEY_BackSpace }],
|
||||
[{ width: 2, keyval: Clutter.KEY_Return, extraClassName: 'enter-key' }],
|
||||
[{ width: 3, level: 1, right: true, extraClassName: 'shift-key-lowercase' }],
|
||||
[{ label: '☻', action: 'emoji' }, { action: 'languageMenu', extraClassName: 'layout-key' }, { action: 'hide', extraClassName: 'hide-key' }] ],
|
||||
[{ width: 1.5, action: 'languageMenu', extraClassName: 'layout-key' }, { width: 1.5, action: 'hide', extraClassName: 'hide-key' }] ],
|
||||
[ [{ label: '⌫', width: 1.5, keyval: Clutter.KEY_BackSpace }],
|
||||
[{ width: 2, keyval: Clutter.KEY_Return, extraClassName: 'enter-key' }],
|
||||
[{ width: 3, level: 0, right: true, extraClassName: 'shift-key-uppercase' }],
|
||||
[{ label: '☻', action: 'emoji' }, { action: 'languageMenu', extraClassName: 'layout-key' }, { action: 'hide', extraClassName: 'hide-key' }] ],
|
||||
[{ width: 1.5, action: 'languageMenu', extraClassName: 'layout-key' }, { width: 1.5, action: 'hide', extraClassName: 'hide-key' }] ],
|
||||
[ [{ label: '⌫', width: 1.5, keyval: Clutter.KEY_BackSpace }],
|
||||
[{ width: 2, keyval: Clutter.KEY_Return, extraClassName: 'enter-key' }],
|
||||
[{ label: '=/<', width: 3, level: 3, right: true }],
|
||||
[{ label: '☻', action: 'emoji' }, { action: 'languageMenu', extraClassName: 'layout-key' }, { action: 'hide', extraClassName: 'hide-key' }] ],
|
||||
[{ width: 1.5, action: 'languageMenu', extraClassName: 'layout-key' }, { width: 1.5, action: 'hide', extraClassName: 'hide-key' }] ],
|
||||
[ [{ label: '⌫', width: 1.5, keyval: Clutter.KEY_BackSpace }],
|
||||
[{ width: 2, keyval: Clutter.KEY_Return, extraClassName: 'enter-key' }],
|
||||
[{ label: '?123', width: 3, level: 2, right: true }],
|
||||
[{ label: '☻', action: 'emoji' }, { action: 'languageMenu', extraClassName: 'layout-key' }, { action: 'hide', extraClassName: 'hide-key' }] ],
|
||||
[{ width: 1.5, action: 'languageMenu', extraClassName: 'layout-key' }, { width: 1.5, action: 'hide', extraClassName: 'hide-key' }] ],
|
||||
];
|
||||
|
||||
var AspectContainer = GObject.registerClass(
|
||||
class AspectContainer extends St.Widget {
|
||||
_init(params) {
|
||||
super._init(params);
|
||||
this._ratio = 1;
|
||||
}
|
||||
|
||||
setRatio(relWidth, relHeight) {
|
||||
this._ratio = relWidth / relHeight;
|
||||
this.queue_relayout();
|
||||
}
|
||||
|
||||
vfunc_allocate(box, flags) {
|
||||
if (box.get_width() > 0 && box.get_height() > 0) {
|
||||
let sizeRatio = box.get_width() / box.get_height();
|
||||
|
||||
if (sizeRatio >= this._ratio) {
|
||||
/* Restrict horizontally */
|
||||
let width = box.get_height() * this._ratio;
|
||||
let diff = box.get_width() - width;
|
||||
|
||||
box.x1 += Math.floor(diff / 2);
|
||||
box.x2 -= Math.ceil(diff / 2);
|
||||
} else {
|
||||
/* Restrict vertically */
|
||||
let height = box.get_width() / this._ratio;
|
||||
let diff = box.get_height() - height;
|
||||
|
||||
box.y1 += Math.floor(diff / 2);
|
||||
box.y2 -= Math.floor(diff / 2);
|
||||
}
|
||||
}
|
||||
|
||||
super.vfunc_allocate(box, flags);
|
||||
}
|
||||
});
|
||||
|
||||
var KeyContainer = GObject.registerClass(
|
||||
var KeyContainer = new GObject.registerClass(
|
||||
class KeyContainer extends St.Widget {
|
||||
_init() {
|
||||
let gridLayout = new Clutter.GridLayout({ orientation: Clutter.Orientation.HORIZONTAL,
|
||||
column_homogeneous: true,
|
||||
row_homogeneous: true });
|
||||
super._init({ layout_manager: gridLayout,
|
||||
x_expand: true, y_expand: true });
|
||||
super._init({ layout_manager: gridLayout });
|
||||
this._gridLayout = gridLayout;
|
||||
this._currentRow = 0;
|
||||
this._currentCol = 0;
|
||||
@@ -138,7 +98,32 @@ class KeyContainer extends St.Widget {
|
||||
this._maxCols = Math.max(this._currentCol, this._maxCols);
|
||||
}
|
||||
|
||||
layoutButtons(container) {
|
||||
vfunc_allocate(box, flags) {
|
||||
if (box.get_width() > 0 && box.get_height() > 0 && this._maxCols > 0) {
|
||||
let keyboardRatio = this._maxCols / this._rows.length;
|
||||
let sizeRatio = box.get_width() / box.get_height();
|
||||
|
||||
if (sizeRatio >= keyboardRatio) {
|
||||
/* Restrict horizontally */
|
||||
let width = box.get_height() * keyboardRatio;
|
||||
let diff = box.get_width() - width;
|
||||
|
||||
box.x1 += Math.floor(diff / 2);
|
||||
box.x2 -= Math.ceil(diff / 2);
|
||||
} else {
|
||||
/* Restrict vertically */
|
||||
let height = box.get_width() / keyboardRatio;
|
||||
let diff = box.get_height() - height;
|
||||
|
||||
box.y1 += Math.floor(diff / 2);
|
||||
box.y2 -= Math.floor(diff / 2);
|
||||
}
|
||||
}
|
||||
|
||||
super.vfunc_allocate(box, flags);
|
||||
}
|
||||
|
||||
layoutButtons() {
|
||||
let nCol = 0, nRow = 0;
|
||||
|
||||
for (let i = 0; i < this._rows.length; i++) {
|
||||
@@ -165,9 +150,6 @@ class KeyContainer extends St.Widget {
|
||||
nRow += KEY_SIZE;
|
||||
nCol = 0;
|
||||
}
|
||||
|
||||
if (container)
|
||||
container.setRatio(this._maxCols, this._rows.length);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -250,7 +232,7 @@ var LanguageSelectionPopup = class extends PopupMenu.PopupMenu {
|
||||
};
|
||||
|
||||
var Key = class Key {
|
||||
constructor(key, extendedKeys) {
|
||||
constructor(key) {
|
||||
this.key = key || "";
|
||||
this.keyButton = this._makeKey(this.key);
|
||||
|
||||
@@ -276,8 +258,6 @@ var Key = class Key {
|
||||
this._boxPointer.destroy();
|
||||
this._boxPointer = null;
|
||||
}
|
||||
|
||||
this.cancel();
|
||||
}
|
||||
|
||||
_ensureExtendedKeysPopup() {
|
||||
@@ -299,13 +279,11 @@ var Key = class Key {
|
||||
}
|
||||
|
||||
_getKeyval(key) {
|
||||
let unicode = key.charCodeAt(0);
|
||||
return Clutter.unicode_to_keysym(unicode);
|
||||
let unicode = String.charCodeAt(key, 0);
|
||||
return Gdk.unicode_to_keyval(unicode);
|
||||
}
|
||||
|
||||
_press(key) {
|
||||
this.emit('activated')
|
||||
|
||||
if (key != this.key || this._extended_keys.length == 0) {
|
||||
this.emit('pressed', this._getKeyval(key), key);
|
||||
}
|
||||
@@ -346,16 +324,6 @@ var Key = class Key {
|
||||
this._longPress = false;
|
||||
}
|
||||
|
||||
cancel() {
|
||||
if (this._pressTimeoutId != 0) {
|
||||
GLib.source_remove(this._pressTimeoutId);
|
||||
this._pressTimeoutId = 0;
|
||||
}
|
||||
this._touchPressed = false;
|
||||
this.keyButton.set_hover(false);
|
||||
this.keyButton.fake_release();
|
||||
}
|
||||
|
||||
_onCapturedEvent(actor, event) {
|
||||
let type = event.type();
|
||||
let press = (type == Clutter.EventType.BUTTON_PRESS || type == Clutter.EventType.TOUCH_BEGIN);
|
||||
@@ -427,10 +395,13 @@ var Key = class Key {
|
||||
|
||||
if (!this._touchPressed &&
|
||||
event.type() == Clutter.EventType.TOUCH_BEGIN) {
|
||||
device.sequence_grab(sequence, actor);
|
||||
this._touchPressed = true;
|
||||
this._press(key);
|
||||
} else if (this._touchPressed &&
|
||||
event.type() == Clutter.EventType.TOUCH_END) {
|
||||
event.type() == Clutter.EventType.TOUCH_END &&
|
||||
device.sequence_get_grabbed_actor(sequence) == actor) {
|
||||
device.sequence_ungrab(sequence);
|
||||
this._touchPressed = false;
|
||||
this._release(key);
|
||||
}
|
||||
@@ -579,460 +550,10 @@ var FocusTracker = class {
|
||||
};
|
||||
Signals.addSignalMethods(FocusTracker.prototype);
|
||||
|
||||
var EmojiPager = class EmojiPager {
|
||||
constructor(sections, nCols, nRows) {
|
||||
this.actor = new St.Widget({ layout_manager: new Clutter.BinLayout(),
|
||||
reactive: true,
|
||||
clip_to_allocation: true });
|
||||
this._sections = sections;
|
||||
this._nCols = nCols;
|
||||
this._nRows = nRows;
|
||||
|
||||
this._pages = [];
|
||||
this._panel = null;
|
||||
this._curPage = null;
|
||||
this._followingPage = null;
|
||||
this._followingPanel = null;
|
||||
this._currentKey = null;
|
||||
this._delta = 0;
|
||||
this._width = null;
|
||||
|
||||
this._initPagingInfo();
|
||||
|
||||
let panAction = new Clutter.PanAction({ interpolate: false });
|
||||
panAction.connect('pan', this._onPan.bind(this));
|
||||
panAction.connect('gesture-begin', this._onPanBegin.bind(this));
|
||||
panAction.connect('gesture-cancel', this._onPanCancel.bind(this));
|
||||
panAction.connect('gesture-end', this._onPanEnd.bind(this));
|
||||
this._panAction = panAction;
|
||||
this.actor.add_action(panAction);
|
||||
}
|
||||
|
||||
get delta() {
|
||||
return this._delta;
|
||||
}
|
||||
|
||||
set delta(value) {
|
||||
if (value > this._width)
|
||||
value = this._width;
|
||||
else if (value < -this._width)
|
||||
value = -this._width;
|
||||
|
||||
this._delta = value;
|
||||
|
||||
if (value == 0)
|
||||
return;
|
||||
|
||||
let relValue = Math.abs(value / this._width);
|
||||
let followingPage = this.getFollowingPage();
|
||||
|
||||
if (this._followingPage != followingPage) {
|
||||
if (this._followingPanel) {
|
||||
this._followingPanel.destroy();
|
||||
this._followingPanel = null;
|
||||
}
|
||||
|
||||
if (followingPage != null) {
|
||||
this._followingPanel = this._generatePanel(followingPage);
|
||||
this._followingPanel.set_pivot_point(0.5, 0.5);
|
||||
this.actor.add_child(this._followingPanel);
|
||||
this.actor.set_child_below_sibling(this._followingPanel, this._panel);
|
||||
}
|
||||
|
||||
this._followingPage = followingPage;
|
||||
}
|
||||
|
||||
this._panel.translation_x = value;
|
||||
this._panel.opacity = 255 * (1 - Math.pow(relValue, 3));
|
||||
|
||||
if (this._followingPanel) {
|
||||
this._followingPanel.scale_x = 0.8 + (0.2 * relValue);
|
||||
this._followingPanel.scale_y = 0.8 + (0.2 * relValue);
|
||||
this._followingPanel.opacity = 255 * relValue;
|
||||
}
|
||||
}
|
||||
|
||||
_prevPage(nPage) {
|
||||
return (nPage + this._pages.length - 1) % this._pages.length;
|
||||
}
|
||||
|
||||
_nextPage(nPage) {
|
||||
return (nPage + 1) % this._pages.length;
|
||||
}
|
||||
|
||||
getFollowingPage() {
|
||||
if (this.delta == 0)
|
||||
return null;
|
||||
|
||||
if ((this.delta < 0 && global.stage.text_direction == Clutter.TextDirection.LTR) ||
|
||||
(this.delta > 0 && global.stage.text_direction == Clutter.TextDirection.RTL))
|
||||
return this._nextPage(this._curPage);
|
||||
else
|
||||
return this._prevPage(this._curPage);
|
||||
}
|
||||
|
||||
_onPan(action) {
|
||||
let [dist, dx, dy] = action.get_motion_delta(0);
|
||||
this.delta = this.delta + dx;
|
||||
|
||||
if (this._currentKey != null) {
|
||||
this._currentKey.cancel();
|
||||
this._currentKey = null;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
_onPanBegin() {
|
||||
this._width = this.actor.width;
|
||||
return true;
|
||||
}
|
||||
|
||||
_onPanEnd() {
|
||||
if (Math.abs(this._delta) < this.actor.width * PANEL_SWITCH_RELATIVE_DISTANCE) {
|
||||
this._onPanCancel()
|
||||
} else {
|
||||
let value;
|
||||
if (this._delta > 0)
|
||||
value = this._width;
|
||||
else if (this._delta < 0)
|
||||
value = -this._width;
|
||||
|
||||
let relDelta = Math.abs(this._delta - value) / this._width;
|
||||
let time = PANEL_SWITCH_ANIMATION_TIME * Math.abs(relDelta);
|
||||
|
||||
Tweener.removeTweens(this);
|
||||
Tweener.addTween(this,
|
||||
{ delta: value,
|
||||
time: time,
|
||||
transition: 'easeInOutQuad',
|
||||
onComplete() {
|
||||
this.setCurrentPage(this.getFollowingPage());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
_onPanCancel() {
|
||||
let relDelta = Math.abs(this._delta) / this.actor.width;
|
||||
let time = PANEL_SWITCH_ANIMATION_TIME * Math.abs(relDelta);
|
||||
|
||||
Tweener.removeTweens(this);
|
||||
Tweener.addTween(this,
|
||||
{ delta: 0,
|
||||
time: time,
|
||||
transition: 'easeInOutQuad',
|
||||
});
|
||||
}
|
||||
|
||||
_initPagingInfo() {
|
||||
for (let i = 0; i < this._sections.length; i++) {
|
||||
let section = this._sections[i];
|
||||
let itemsPerPage = this._nCols * this._nRows;
|
||||
let nPages = Math.ceil(section.keys.length / itemsPerPage);
|
||||
let page = -1;
|
||||
let pageKeys;
|
||||
|
||||
for (let j = 0; j < section.keys.length; j++) {
|
||||
if (j % itemsPerPage == 0) {
|
||||
page++;
|
||||
pageKeys = [];
|
||||
this._pages.push({ pageKeys, nPages, page, section: this._sections[i] });
|
||||
}
|
||||
|
||||
pageKeys.push(section.keys[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_lookupSection(section, nPage) {
|
||||
for (let i = 0; i < this._pages.length; i++) {
|
||||
let page = this._pages[i];
|
||||
|
||||
if (page.section == section && page.page == nPage)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
_generatePanel(nPage) {
|
||||
let gridLayout = new Clutter.GridLayout({ orientation: Clutter.Orientation.HORIZONTAL,
|
||||
column_homogeneous: true,
|
||||
row_homogeneous: true });
|
||||
let panel = new St.Widget({ layout_manager: gridLayout,
|
||||
style_class: 'emoji-page',
|
||||
x_expand: true,
|
||||
y_expand: true });
|
||||
|
||||
/* Set an expander actor so all proportions are right despite the panel
|
||||
* not having all rows/cols filled in.
|
||||
*/
|
||||
let expander = new Clutter.Actor();
|
||||
gridLayout.attach(expander, 0, 0, this._nCols, this._nRows);
|
||||
|
||||
let page = this._pages[nPage];
|
||||
let col = 0;
|
||||
let row = 0;
|
||||
|
||||
for (let i = 0; i < page.pageKeys.length; i++) {
|
||||
let modelKey = page.pageKeys[i];
|
||||
let key = new Key(modelKey.label, modelKey.variants);
|
||||
|
||||
key.keyButton.set_button_mask(0);
|
||||
|
||||
key.connect('activated', () => {
|
||||
this._currentKey = key;
|
||||
});
|
||||
key.connect('long-press', () => {
|
||||
this._panAction.cancel();
|
||||
});
|
||||
key.connect('released', (actor, keyval, str) => {
|
||||
if (this._currentKey != key)
|
||||
return;
|
||||
this._currentKey = null;
|
||||
this.emit('emoji', str);
|
||||
});
|
||||
|
||||
gridLayout.attach(key.actor, col, row, 1, 1);
|
||||
|
||||
col++;
|
||||
if (col >= this._nCols) {
|
||||
col = 0;
|
||||
row++;
|
||||
}
|
||||
}
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
setCurrentPage(nPage) {
|
||||
if (this._curPage == nPage)
|
||||
return;
|
||||
|
||||
this._curPage = nPage;
|
||||
|
||||
if (this._panel) {
|
||||
this._panel.destroy();
|
||||
this._panel = null;
|
||||
}
|
||||
|
||||
/* Reuse followingPage if possible */
|
||||
if (nPage == this._followingPage) {
|
||||
this._panel = this._followingPanel;
|
||||
this._followingPanel = null;
|
||||
}
|
||||
|
||||
if (this._followingPanel)
|
||||
this._followingPanel.destroy();
|
||||
|
||||
this._followingPanel = null;
|
||||
this._followingPage = null;
|
||||
this._delta = 0;
|
||||
|
||||
if (!this._panel) {
|
||||
this._panel = this._generatePanel(nPage);
|
||||
this.actor.add_child(this._panel);
|
||||
}
|
||||
|
||||
let page = this._pages[nPage];
|
||||
this.emit('page-changed', page.section, page.page, page.nPages);
|
||||
}
|
||||
|
||||
setCurrentSection(section, nPage) {
|
||||
for (let i = 0; i < this._pages.length; i++) {
|
||||
let page = this._pages[i];
|
||||
|
||||
if (page.section == section && page.page == nPage) {
|
||||
this.setCurrentPage(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
Signals.addSignalMethods(EmojiPager.prototype);
|
||||
|
||||
var EmojiSelection = class EmojiSelection {
|
||||
constructor() {
|
||||
this._sections = [
|
||||
{ first: 'grinning face', label: '🙂️' },
|
||||
{ first: 'selfie', label: '👍️' },
|
||||
{ first: 'monkey face', label: '🌷️' },
|
||||
{ first: 'grapes', label: '🍴️' },
|
||||
{ first: 'globe showing Europe-Africa', label: '✈️' },
|
||||
{ first: 'jack-o-lantern', label: '🏃️' },
|
||||
{ first: 'muted speaker', label: '🔔️' },
|
||||
{ first: 'ATM sign', label: '❤️' },
|
||||
{ first: 'chequered flag', label: '🚩️' },
|
||||
];
|
||||
|
||||
this._populateSections();
|
||||
|
||||
this.actor = new St.BoxLayout({ style_class: 'emoji-panel',
|
||||
x_expand: true,
|
||||
y_expand: true,
|
||||
vertical: true });
|
||||
this.actor.connect('notify::mapped', () => { this._emojiPager.setCurrentPage(0); });
|
||||
|
||||
this._emojiPager = new EmojiPager(this._sections, 11, 3);
|
||||
this._emojiPager.connect('page-changed', (pager, section, page, nPages) => {
|
||||
this._onPageChanged(section, page, nPages);
|
||||
});
|
||||
this._emojiPager.connect('emoji', (pager, str) => {
|
||||
this.emit('emoji-selected', str);
|
||||
});
|
||||
this.actor.add(this._emojiPager.actor, { expand: true });
|
||||
|
||||
this._pageIndicator = new PageIndicators.PageIndicators(false);
|
||||
this.actor.add(this._pageIndicator, { expand: true, x_fill: false, y_fill: false });
|
||||
this._pageIndicator.setReactive(false);
|
||||
|
||||
let bottomRow = this._createBottomRow();
|
||||
this.actor.add(bottomRow, { x_fill: true, y_fill: false });
|
||||
|
||||
this._emojiPager.setCurrentPage(0);
|
||||
}
|
||||
|
||||
_onPageChanged(section, page, nPages) {
|
||||
this._pageIndicator.setNPages(nPages);
|
||||
this._pageIndicator.setCurrentPage(page);
|
||||
|
||||
for (let i = 0; i < this._sections.length; i++) {
|
||||
let sect = this._sections[i];
|
||||
sect.button.setLatched(section == sect);
|
||||
}
|
||||
}
|
||||
|
||||
_findSection(emoji) {
|
||||
for (let i = 0; i < this._sections.length; i++) {
|
||||
if (this._sections[i].first == emoji)
|
||||
return this._sections[i];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
_populateSections() {
|
||||
let file = Gio.File.new_for_uri('resource:///org/gnome/shell/osk-layouts/emoji.json');
|
||||
let [success, contents] = file.load_contents(null);
|
||||
|
||||
if (contents instanceof Uint8Array)
|
||||
contents = imports.byteArray.toString(contents);
|
||||
let emoji = JSON.parse(contents);
|
||||
|
||||
let pages = [];
|
||||
let variants = [];
|
||||
let currentKey = 0;
|
||||
let currentSection = null;
|
||||
|
||||
for (let i = 0; i < emoji.length; i++) {
|
||||
/* Group variants of a same emoji so they appear on the key popover */
|
||||
if (emoji[i].name.startsWith(emoji[currentKey].name)) {
|
||||
variants.push(emoji[i].char);
|
||||
if (i < emoji.length - 1)
|
||||
continue;
|
||||
}
|
||||
|
||||
let newSection = this._findSection(emoji[currentKey].name);
|
||||
if (newSection != null) {
|
||||
currentSection = newSection;
|
||||
currentSection.keys = [];
|
||||
}
|
||||
|
||||
/* Create the key */
|
||||
let label = emoji[currentKey].char + String.fromCharCode(0xFE0F);
|
||||
currentSection.keys.push({ label, variants });
|
||||
currentKey = i;
|
||||
variants = [];
|
||||
}
|
||||
}
|
||||
|
||||
_createBottomRow() {
|
||||
let row = new KeyContainer();
|
||||
let key;
|
||||
|
||||
row.appendRow();
|
||||
|
||||
key = new Key('ABC', []);
|
||||
key.keyButton.add_style_class_name('default-key');
|
||||
key.connect('released', () => { this.emit('toggle'); });
|
||||
row.appendKey(key.actor, 1.5);
|
||||
|
||||
for (let i = 0; i < this._sections.length; i++) {
|
||||
let section = this._sections[i];
|
||||
|
||||
key = new Key(section.label, []);
|
||||
key.connect('released', () => { this._emojiPager.setCurrentSection(section, 0) });
|
||||
row.appendKey(key.actor);
|
||||
|
||||
section.button = key;
|
||||
}
|
||||
|
||||
key = new Key(null, []);
|
||||
key.keyButton.add_style_class_name('default-key');
|
||||
key.keyButton.add_style_class_name('hide-key');
|
||||
key.connect('released', () => {
|
||||
this.emit('hide');
|
||||
});
|
||||
row.appendKey(key.actor);
|
||||
row.layoutButtons();
|
||||
|
||||
return row;
|
||||
}
|
||||
};
|
||||
Signals.addSignalMethods(EmojiSelection.prototype);
|
||||
|
||||
var Keypad = class Keypad {
|
||||
constructor() {
|
||||
let keys = [
|
||||
{ label: '1', keyval: Clutter.KEY_1, left: 0, top: 0 },
|
||||
{ label: '2', keyval: Clutter.KEY_2, left: 1, top: 0 },
|
||||
{ label: '3', keyval: Clutter.KEY_3, left: 2, top: 0 },
|
||||
{ label: '4', keyval: Clutter.KEY_4, left: 0, top: 1 },
|
||||
{ label: '5', keyval: Clutter.KEY_5, left: 1, top: 1 },
|
||||
{ label: '6', keyval: Clutter.KEY_6, left: 2, top: 1 },
|
||||
{ label: '7', keyval: Clutter.KEY_7, left: 0, top: 2 },
|
||||
{ label: '8', keyval: Clutter.KEY_8, left: 1, top: 2 },
|
||||
{ label: '9', keyval: Clutter.KEY_9, left: 2, top: 2 },
|
||||
{ label: '0', keyval: Clutter.KEY_0, left: 1, top: 3 },
|
||||
{ label: '⌫', keyval: Clutter.KEY_BackSpace, left: 3, top: 0 },
|
||||
{ keyval: Clutter.KEY_Return, extraClassName: 'enter-key', left: 3, top: 1, height: 2 },
|
||||
];
|
||||
|
||||
this.actor = new AspectContainer({ layout_manager: new Clutter.BinLayout(),
|
||||
x_expand: true, y_expand: true });
|
||||
|
||||
let gridLayout = new Clutter.GridLayout({ orientation: Clutter.Orientation.HORIZONTAL,
|
||||
column_homogeneous: true,
|
||||
row_homogeneous: true });
|
||||
this._box = new St.Widget({ layout_manager: gridLayout, x_expand: true, y_expand: true });
|
||||
this.actor.add_child(this._box);
|
||||
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
let cur = keys[i];
|
||||
let key = new Key(cur.label || "", []);
|
||||
|
||||
if (keys[i].extraClassName)
|
||||
key.keyButton.add_style_class_name(cur.extraClassName);
|
||||
|
||||
let w, h;
|
||||
w = cur.width || 1;
|
||||
h = cur.height || 1;
|
||||
gridLayout.attach(key.actor, cur.left, cur.top, w, h);
|
||||
|
||||
key.connect('released', () => {
|
||||
this.emit('keyval', cur.keyval);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
Signals.addSignalMethods(Keypad.prototype);
|
||||
|
||||
var Keyboard = class Keyboard {
|
||||
constructor() {
|
||||
this.actor = null;
|
||||
this._focusInExtendedKeys = false;
|
||||
this._emojiActive = false;
|
||||
|
||||
this._languagePopup = null;
|
||||
this._currentFocusWindow = null;
|
||||
@@ -1047,7 +568,6 @@ var Keyboard = class Keyboard {
|
||||
this._a11yApplicationsSettings.connect('changed', this._syncEnabled.bind(this));
|
||||
this._lastDeviceId = null;
|
||||
this._suggestions = null;
|
||||
this._emojiKeyVisible = true;
|
||||
|
||||
this._focusTracker = new FocusTracker();
|
||||
this._focusTracker.connect('position-changed', this._onFocusPositionChanged.bind(this));
|
||||
@@ -1136,10 +656,6 @@ var Keyboard = class Keyboard {
|
||||
this._keyboardController.disconnect(this._keyboardGroupsChangedId);
|
||||
if (this._keyboardStateId)
|
||||
this._keyboardController.disconnect(this._keyboardStateId);
|
||||
if (this._emojiKeyVisibleId)
|
||||
this._keyboardController.disconnect(this._emojiKeyVisibleId);
|
||||
if (this._keypadVisibleId)
|
||||
this._keyboardController.disconnect(this._keypadVisibleId);
|
||||
if (this._focusNotifyId)
|
||||
global.stage.disconnect(this._focusNotifyId);
|
||||
this._keyboard = null;
|
||||
@@ -1163,32 +679,13 @@ var Keyboard = class Keyboard {
|
||||
this._current_page = null;
|
||||
|
||||
this._suggestions = new Suggestions();
|
||||
this._suggestions.connect('suggestion-clicked', (suggestions, str) => {
|
||||
this._keyboardController.commitString(str);
|
||||
});
|
||||
this.actor.add(this._suggestions.actor,
|
||||
{ x_align: St.Align.MIDDLE,
|
||||
x_fill: false });
|
||||
|
||||
this._aspectContainer = new AspectContainer({ layout_manager: new Clutter.BinLayout() });
|
||||
this.actor.add(this._aspectContainer, { expand: true });
|
||||
|
||||
this._emojiSelection = new EmojiSelection();
|
||||
this._emojiSelection.connect('toggle', this._toggleEmoji.bind(this));
|
||||
this._emojiSelection.connect('hide', (selection) => { this.hide(); });
|
||||
this._emojiSelection.connect('emoji-selected', (selection, emoji) => {
|
||||
this._keyboardController.commitString(emoji);
|
||||
});
|
||||
|
||||
this._aspectContainer.add_child(this._emojiSelection.actor);
|
||||
this._emojiSelection.actor.hide();
|
||||
|
||||
this._keypad = new Keypad();
|
||||
this._keypad.connect('keyval', (keypad, keyval) => {
|
||||
this._keyboardController.keyvalPress(keyval);
|
||||
this._keyboardController.keyvalRelease(keyval);
|
||||
});
|
||||
this._aspectContainer.add_child(this._keypad.actor);
|
||||
this._keypad.actor.hide();
|
||||
this._keypadVisible = false;
|
||||
|
||||
this._ensureKeysForGroup(this._keyboardController.getCurrentGroup());
|
||||
this._setActiveLayer(0);
|
||||
|
||||
@@ -1200,8 +697,6 @@ var Keyboard = class Keyboard {
|
||||
this._keyboardNotifyId = this._keyboardController.connect('active-group', this._onGroupChanged.bind(this));
|
||||
this._keyboardGroupsChangedId = this._keyboardController.connect('groups-changed', this._onKeyboardGroupsChanged.bind(this));
|
||||
this._keyboardStateId = this._keyboardController.connect('panel-state', this._onKeyboardStateChanged.bind(this));
|
||||
this._emojiKeyVisibleId = this._keyboardController.connect('emoji-visible', this._onEmojiKeyVisible.bind(this));
|
||||
this._keypadVisibleId = this._keyboardController.connect('keypad-visible', this._onKeypadVisible.bind(this));
|
||||
this._focusNotifyId = global.stage.connect('notify::key-focus', this._onKeyFocusChanged.bind(this));
|
||||
|
||||
this._relayout();
|
||||
@@ -1248,12 +743,11 @@ var Keyboard = class Keyboard {
|
||||
|
||||
this._loadRows(currentLevel, level, levels.length, layout);
|
||||
layers[level] = layout;
|
||||
this._aspectContainer.add_child(layout);
|
||||
layout.layoutButtons(this._aspectContainer);
|
||||
this.actor.add(layout, { expand: true });
|
||||
layout.layoutButtons();
|
||||
|
||||
layout.hide();
|
||||
}
|
||||
|
||||
return layers;
|
||||
}
|
||||
|
||||
@@ -1312,11 +806,7 @@ var Keyboard = class Keyboard {
|
||||
let switchToLevel = key.level;
|
||||
let action = key.action;
|
||||
|
||||
/* Skip emoji button if necessary */
|
||||
if (!this._emojiKeyVisible && action == 'emoji')
|
||||
continue;
|
||||
|
||||
extraButton = new Key(key.label || '', []);
|
||||
extraButton = new Key(key.label, []);
|
||||
|
||||
extraButton.keyButton.add_style_class_name('default-key');
|
||||
if (key.extraClassName != null)
|
||||
@@ -1342,8 +832,6 @@ var Keyboard = class Keyboard {
|
||||
this.hide();
|
||||
else if (action == 'languageMenu')
|
||||
this._popupLanguageMenu(actor);
|
||||
else if (action == 'emoji')
|
||||
this._toggleEmoji();
|
||||
});
|
||||
|
||||
if (switchToLevel == 0) {
|
||||
@@ -1369,31 +857,14 @@ var Keyboard = class Keyboard {
|
||||
extraButton.setWidth(2);
|
||||
} else if (keyval == Clutter.KEY_Return && numKeys > 9) {
|
||||
extraButton.setWidth(1.5);
|
||||
} else if (!this._emojiKeyVisible && (action == 'hide' || action == 'languageMenu')) {
|
||||
extraButton.setWidth(1.5);
|
||||
}
|
||||
|
||||
layout.appendKey(extraButton.actor, extraButton.keyButton.keyWidth);
|
||||
}
|
||||
}
|
||||
|
||||
_updateCurrentPageVisible() {
|
||||
if (this._current_page)
|
||||
this._current_page.visible = !this._emojiActive && !this._keypadVisible;
|
||||
}
|
||||
|
||||
_setEmojiActive(active) {
|
||||
this._emojiActive = active;
|
||||
this._emojiSelection.actor.visible = this._emojiActive;
|
||||
this._updateCurrentPageVisible();
|
||||
}
|
||||
|
||||
_toggleEmoji() {
|
||||
this._setEmojiActive(!this._emojiActive);
|
||||
}
|
||||
|
||||
_setCurrentLevelLatched(layout, latched) {
|
||||
for (let i = 0; i < layout.shiftKeys.length; i++) {
|
||||
for (let i = 0; layout.shiftKeys[i]; i++) {
|
||||
let key = layout.shiftKeys[i];
|
||||
key.setLatched(latched);
|
||||
}
|
||||
@@ -1472,24 +943,6 @@ var Keyboard = class Keyboard {
|
||||
this._onGroupChanged();
|
||||
}
|
||||
|
||||
_onKeypadVisible(controller, visible) {
|
||||
if (visible == this._keypadVisible)
|
||||
return;
|
||||
|
||||
this._keypadVisible = visible;
|
||||
this._keypad.actor.visible = this._keypadVisible;
|
||||
this._updateCurrentPageVisible();
|
||||
}
|
||||
|
||||
_onEmojiKeyVisible(controller, visible) {
|
||||
if (visible == this._emojiKeyVisible)
|
||||
return;
|
||||
|
||||
this._emojiKeyVisible = visible;
|
||||
/* Rebuild keyboard widgetry to include emoji button */
|
||||
this._onKeyboardGroupsChanged();
|
||||
}
|
||||
|
||||
_onKeyboardStateChanged(controller, state) {
|
||||
let enabled;
|
||||
if (state == Clutter.InputPanelState.OFF)
|
||||
@@ -1517,7 +970,7 @@ var Keyboard = class Keyboard {
|
||||
}
|
||||
|
||||
this._current_page = layers[activeLevel];
|
||||
this._updateCurrentPageVisible();
|
||||
this._current_page.show();
|
||||
}
|
||||
|
||||
shouldTakeEvent(event) {
|
||||
@@ -1567,8 +1020,6 @@ var Keyboard = class Keyboard {
|
||||
this._relayout();
|
||||
Main.layoutManager.showKeyboard();
|
||||
|
||||
this._setEmojiActive(false);
|
||||
|
||||
if (this._delayedAnimFocusWindow) {
|
||||
this._setAnimationWindow(this._delayedAnimFocusWindow);
|
||||
this._delayedAnimFocusWindow = null;
|
||||
@@ -1736,21 +1187,8 @@ var KeyboardController = class {
|
||||
_onContentPurposeHintsChanged(method) {
|
||||
let hints = method.content_hints;
|
||||
let purpose = method.content_purpose;
|
||||
let emojiVisible = false;
|
||||
let keypadVisible = false;
|
||||
|
||||
if (purpose == Clutter.InputContentPurpose.NORMAL ||
|
||||
purpose == Clutter.InputContentPurpose.ALPHA ||
|
||||
purpose == Clutter.InputContentPurpose.PASSWORD ||
|
||||
purpose == Clutter.InputContentPurpose.TERMINAL)
|
||||
emojiVisible = true;
|
||||
if (purpose == Clutter.InputContentPurpose.DIGITS ||
|
||||
purpose == Clutter.InputContentPurpose.NUMBER ||
|
||||
purpose == Clutter.InputContentPurpose.PHONE)
|
||||
keypadVisible = true;
|
||||
|
||||
this.emit('emoji-visible', emojiVisible)
|
||||
this.emit('keypad-visible', keypadVisible);
|
||||
// XXX: hook numeric/emoji/etc special keyboards
|
||||
}
|
||||
|
||||
getGroups() {
|
||||
|
@@ -5,6 +5,7 @@ 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;
|
||||
@@ -186,7 +187,7 @@ var Notebook = class Notebook {
|
||||
|
||||
// Focus the new tab before unmapping the old one
|
||||
let tabData = this._tabs[index];
|
||||
if (!tabData.scrollView.navigate_focus(null, St.DirectionType.TAB_FORWARD, false))
|
||||
if (!tabData.scrollView.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false))
|
||||
this.actor.grab_key_focus();
|
||||
|
||||
this._unselect();
|
||||
|
@@ -2,11 +2,9 @@
|
||||
|
||||
const Atspi = imports.gi.Atspi;
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Cogl = imports.gi.Cogl;
|
||||
const GDesktopEnums = imports.gi.GDesktopEnums;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const GObject = imports.gi.GObject;
|
||||
const Shell = imports.gi.Shell;
|
||||
const St = imports.gi.St;
|
||||
const Mainloop = imports.mainloop;
|
||||
@@ -54,51 +52,6 @@ const CROSS_HAIRS_CLIP_KEY = 'cross-hairs-clip';
|
||||
|
||||
let magDBusService = null;
|
||||
|
||||
var MouseSpriteContent = GObject.registerClass({
|
||||
Implements: [ Clutter.Content ],
|
||||
}, class MouseSpriteContent extends GObject.Object {
|
||||
_init() {
|
||||
super._init();
|
||||
this._texture = null;
|
||||
}
|
||||
|
||||
vfunc_get_preferred_size() {
|
||||
if (!this._texture)
|
||||
return [0, 0];
|
||||
|
||||
return [this._texture.get_width(), this._texture.get_height()];
|
||||
}
|
||||
|
||||
vfunc_paint_content(actor, node) {
|
||||
if (!this._texture)
|
||||
return;
|
||||
|
||||
let color = new Cogl.Color();
|
||||
color.init_from_4ub(0, 0, 0, 0);
|
||||
|
||||
let textureNode = new Clutter.TextureNode(this._texture,
|
||||
color,
|
||||
Clutter.ScalingFilter.NEAREST,
|
||||
Clutter.ScalingFilter.NEAREST);
|
||||
textureNode.set_name('MouseSpriteContent');
|
||||
node.add_child(textureNode);
|
||||
|
||||
textureNode.add_rectangle(actor.get_content_box());
|
||||
}
|
||||
|
||||
get texture() {
|
||||
return this._texture;
|
||||
}
|
||||
|
||||
set texture(coglTexture) {
|
||||
if (this._texture == coglTexture)
|
||||
return;
|
||||
|
||||
this._texture = coglTexture;
|
||||
this.invalidate();
|
||||
}
|
||||
});
|
||||
|
||||
var Magnifier = class Magnifier {
|
||||
constructor() {
|
||||
// Magnifier is a manager of ZoomRegions.
|
||||
@@ -106,12 +59,8 @@ var Magnifier = class Magnifier {
|
||||
|
||||
// Create small clutter tree for the magnified mouse.
|
||||
let cursorTracker = Meta.CursorTracker.get_for_display(global.display);
|
||||
this._cursorTracker = cursorTracker;
|
||||
|
||||
this._mouseSprite = new Clutter.Actor({ request_mode: Clutter.RequestMode.CONTENT_SIZE });
|
||||
this._mouseSprite.content = new MouseSpriteContent();
|
||||
this._updateSpriteTexture();
|
||||
|
||||
this._mouseSprite = new Clutter.Texture();
|
||||
Shell.util_cursor_tracker_to_clutter(cursorTracker, this._mouseSprite);
|
||||
this._cursorRoot = new Clutter.Actor();
|
||||
this._cursorRoot.add_actor(this._mouseSprite);
|
||||
|
||||
@@ -127,6 +76,7 @@ var Magnifier = class Magnifier {
|
||||
aZoomRegion.scrollContentsTo(this.xMouse, this.yMouse);
|
||||
|
||||
cursorTracker.connect('cursor-changed', this._updateMouseSprite.bind(this));
|
||||
this._cursorTracker = cursorTracker;
|
||||
|
||||
// Export to dbus.
|
||||
magDBusService = new MagnifierDBus.ShellMagnifier();
|
||||
@@ -486,22 +436,11 @@ var Magnifier = class Magnifier {
|
||||
//// Private methods ////
|
||||
|
||||
_updateMouseSprite() {
|
||||
this._updateSpriteTexture();
|
||||
Shell.util_cursor_tracker_to_clutter(this._cursorTracker, this._mouseSprite);
|
||||
let [xHot, yHot] = this._cursorTracker.get_hot();
|
||||
this._mouseSprite.set_anchor_point(xHot, yHot);
|
||||
}
|
||||
|
||||
_updateSpriteTexture() {
|
||||
let sprite = this._cursorTracker.get_sprite();
|
||||
|
||||
if (sprite) {
|
||||
this._mouseSprite.content.texture = sprite;
|
||||
this._mouseSprite.show();
|
||||
} else {
|
||||
this._mouseSprite.hide();
|
||||
}
|
||||
}
|
||||
|
||||
_settingsInit(zoomRegion) {
|
||||
this._appSettings = new Gio.Settings({ schema_id: APPLICATIONS_SCHEMA });
|
||||
this._settings = new Gio.Settings({ schema_id: MAGNIFIER_SCHEMA });
|
||||
|
@@ -1,8 +1,10 @@
|
||||
// -*- 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 Mainloop = imports.mainloop;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Shell = imports.gi.Shell;
|
||||
@@ -126,8 +128,9 @@ function start() {
|
||||
|
||||
sessionMode = new SessionMode.SessionMode();
|
||||
sessionMode.connect('updated', _sessionUpdated);
|
||||
|
||||
St.Settings.get().connect('notify::gtk-theme', _loadDefaultStylesheet);
|
||||
Gtk.Settings.get_default().connect('notify::gtk-theme-name',
|
||||
_loadDefaultStylesheet);
|
||||
Gtk.IconTheme.get_default().add_resource_path('/org/gnome/shell/theme/icons');
|
||||
_initializeUI();
|
||||
|
||||
shellAccessDialogDBusService = new AccessDialog.AccessDialogDBus();
|
||||
@@ -277,7 +280,7 @@ function _getDefaultStylesheet() {
|
||||
|
||||
// Look for a high-contrast variant first when using GTK+'s HighContrast
|
||||
// theme
|
||||
if (St.Settings.get().gtk_theme == 'HighContrast')
|
||||
if (Gtk.Settings.get_default().gtk_theme_name == 'HighContrast')
|
||||
stylesheet = _getStylesheet(name.replace('.css', '-high-contrast.css'));
|
||||
|
||||
if (stylesheet == null)
|
||||
|
@@ -159,7 +159,7 @@ var URLHighlighter = class URLHighlighter {
|
||||
}
|
||||
};
|
||||
|
||||
var ScaleLayout = GObject.registerClass(
|
||||
var ScaleLayout = new GObject.registerClass(
|
||||
class ScaleLayout extends Clutter.BinLayout {
|
||||
_init(params) {
|
||||
this._container = null;
|
||||
|
@@ -4,6 +4,7 @@ const Clutter = imports.gi.Clutter;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GObject = imports.gi.GObject;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Atk = imports.gi.Atk;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Meta = imports.gi.Meta;
|
||||
@@ -70,17 +71,6 @@ var Urgency = {
|
||||
CRITICAL: 3
|
||||
};
|
||||
|
||||
// The privacy of the details of a notification. USER is for notifications which
|
||||
// contain private information to the originating user account (for example,
|
||||
// details of an e-mail they’ve received). SYSTEM is for notifications which
|
||||
// contain information private to the physical system (for example, battery
|
||||
// status) and hence the same for every user. This affects whether the content
|
||||
// of a notification is shown on the lock screen.
|
||||
var PrivacyScope = {
|
||||
USER: 0,
|
||||
SYSTEM: 1,
|
||||
};
|
||||
|
||||
var FocusGrabber = class FocusGrabber {
|
||||
constructor(actor) {
|
||||
this._actor = actor;
|
||||
@@ -97,7 +87,7 @@ var FocusGrabber = class FocusGrabber {
|
||||
|
||||
this._focusActorChangedId = global.stage.connect('notify::key-focus', this._focusActorChanged.bind(this));
|
||||
|
||||
if (!this._actor.navigate_focus(null, St.DirectionType.TAB_FORWARD, false))
|
||||
if (!this._actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false))
|
||||
this._actor.grab_key_focus();
|
||||
|
||||
this._focused = true;
|
||||
@@ -350,7 +340,6 @@ var Notification = class Notification {
|
||||
this.resident = false;
|
||||
// 'transient' is a reserved keyword in JS, so we have to use an alternate variable name
|
||||
this.isTransient = false;
|
||||
this.privacyScope = PrivacyScope.USER;
|
||||
this.forFeedback = false;
|
||||
this._acknowledged = false;
|
||||
this.bannerBodyText = null;
|
||||
@@ -447,10 +436,6 @@ var Notification = class Notification {
|
||||
this.forFeedback = forFeedback;
|
||||
}
|
||||
|
||||
setPrivacyScope(privacyScope) {
|
||||
this.privacyScope = privacyScope;
|
||||
}
|
||||
|
||||
playSound() {
|
||||
if (this._soundPlayed)
|
||||
return;
|
||||
@@ -512,12 +497,9 @@ class NotificationBanner extends Calendar.NotificationMessage {
|
||||
});
|
||||
}
|
||||
|
||||
_disconnectNotificationSignals() {
|
||||
super._disconnectNotificationSignals();
|
||||
|
||||
if (this._activatedId)
|
||||
this.notification.disconnect(this._activatedId);
|
||||
this._activatedId = 0;
|
||||
_onDestroy() {
|
||||
super._onDestroy();
|
||||
this.notification.disconnect(this._activatedId);
|
||||
}
|
||||
|
||||
_onUpdated(n, clear) {
|
||||
@@ -737,11 +719,6 @@ var Source = class Source {
|
||||
return new NotificationPolicy();
|
||||
}
|
||||
|
||||
get narrowestPrivacyScope() {
|
||||
return this.notifications.every(n => n.privacyScope == PrivacyScope.SYSTEM) ? PrivacyScope.SYSTEM
|
||||
: PrivacyScope.USER;
|
||||
}
|
||||
|
||||
setTitle(newTitle) {
|
||||
this.title = newTitle;
|
||||
this.emit('title-changed');
|
||||
|
@@ -1,6 +1,7 @@
|
||||
// -*- 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 Meta = imports.gi.Meta;
|
||||
@@ -196,6 +197,7 @@ var ModalDialog = class {
|
||||
else
|
||||
this._savedKeyFocus = null;
|
||||
Main.popModal(this._group, timestamp);
|
||||
Gdk.Display.get_default().sync();
|
||||
this._hasModal = false;
|
||||
|
||||
if (!this._shellReactive)
|
||||
|
@@ -4,6 +4,7 @@ const Clutter = imports.gi.Clutter;
|
||||
const GdkPixbuf = imports.gi.GdkPixbuf;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Mainloop = imports.mainloop;
|
||||
const St = imports.gi.St;
|
||||
@@ -351,10 +352,6 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
|
||||
// of the 'transient' hint with hints['transient'] rather than hints.transient
|
||||
notification.setTransient(!!hints['transient']);
|
||||
|
||||
let privacyScope = (hints['x-gnome-privacy-scope'] || 'user');
|
||||
notification.setPrivacyScope(privacyScope == 'system' ? MessageTray.PrivacyScope.SYSTEM
|
||||
: MessageTray.PrivacyScope.USER);
|
||||
|
||||
let sourceGIcon = source.useNotificationIcon ? gicon : null;
|
||||
source.processNotification(notification, sourceGIcon);
|
||||
}
|
||||
|
@@ -2,11 +2,13 @@
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Signals = imports.signals;
|
||||
const St = imports.gi.St;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Gdk = imports.gi.Gdk;
|
||||
|
||||
const Background = imports.ui.background;
|
||||
const DND = imports.ui.dnd;
|
||||
@@ -156,6 +158,7 @@ var Overview = class {
|
||||
this._windowSwitchTimestamp = 0;
|
||||
this._lastActiveWorkspaceIndex = -1;
|
||||
this._lastHoveredWindow = null;
|
||||
this._needsFakePointerEvent = false;
|
||||
|
||||
if (this._initCalled)
|
||||
this.init();
|
||||
@@ -303,9 +306,19 @@ var Overview = class {
|
||||
if (this._windowSwitchTimeoutId != 0) {
|
||||
Mainloop.source_remove(this._windowSwitchTimeoutId);
|
||||
this._windowSwitchTimeoutId = 0;
|
||||
this._needsFakePointerEvent = false;
|
||||
}
|
||||
}
|
||||
|
||||
_fakePointerEvent() {
|
||||
let display = Gdk.Display.get_default();
|
||||
let deviceManager = display.get_device_manager();
|
||||
let pointer = deviceManager.get_client_pointer();
|
||||
let [gdkScreen, pointerX, pointerY] = pointer.get_position();
|
||||
|
||||
pointer.warp(gdkScreen, pointerX, pointerY);
|
||||
}
|
||||
|
||||
_onDragMotion(dragEvent) {
|
||||
let targetIsWindow = dragEvent.targetActor &&
|
||||
dragEvent.targetActor._delegate &&
|
||||
@@ -327,6 +340,7 @@ var Overview = class {
|
||||
this._windowSwitchTimeoutId = Mainloop.timeout_add(DND_WINDOW_SWITCH_TIMEOUT,
|
||||
() => {
|
||||
this._windowSwitchTimeoutId = 0;
|
||||
this._needsFakePointerEvent = true;
|
||||
Main.activateWindow(dragEvent.targetActor._delegate.metaWindow,
|
||||
this._windowSwitchTimestamp);
|
||||
this.hide();
|
||||
@@ -373,6 +387,9 @@ var Overview = class {
|
||||
// when it is next shown.
|
||||
this.hide();
|
||||
|
||||
if (!Main.layoutManager.primaryMonitor)
|
||||
return;
|
||||
|
||||
this._coverPane.set_position(0, 0);
|
||||
this._coverPane.set_size(global.screen_width, global.screen_height);
|
||||
|
||||
@@ -629,6 +646,12 @@ var Overview = class {
|
||||
Main.layoutManager.hideOverview();
|
||||
|
||||
this._syncGrab();
|
||||
|
||||
// Fake a pointer event if requested
|
||||
if (this._needsFakePointerEvent) {
|
||||
this._fakePointerEvent();
|
||||
this._needsFakePointerEvent = false;
|
||||
}
|
||||
}
|
||||
|
||||
toggle() {
|
||||
|
@@ -1,142 +0,0 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const GObject = imports.gi.GObject;
|
||||
const St = imports.gi.St;
|
||||
|
||||
const Tweener = imports.ui.tweener;
|
||||
const { ANIMATION_TIME_OUT, ANIMATION_MAX_DELAY_OUT_FOR_ITEM, AnimationDirection } = imports.ui.iconGrid;
|
||||
|
||||
var INDICATORS_BASE_TIME = 0.25;
|
||||
var INDICATORS_BASE_TIME_OUT = 0.125;
|
||||
var INDICATORS_ANIMATION_DELAY = 0.125;
|
||||
var INDICATORS_ANIMATION_DELAY_OUT = 0.0625;
|
||||
var INDICATORS_ANIMATION_MAX_TIME = 0.75;
|
||||
var SWITCH_TIME = 0.4;
|
||||
var INDICATORS_ANIMATION_MAX_TIME_OUT =
|
||||
Math.min (SWITCH_TIME,
|
||||
ANIMATION_TIME_OUT + ANIMATION_MAX_DELAY_OUT_FOR_ITEM);
|
||||
|
||||
var ANIMATION_DELAY = 0.1;
|
||||
|
||||
var PageIndicators = GObject.registerClass({
|
||||
Signals: { 'page-activated': { param_types: [GObject.TYPE_INT] } }
|
||||
}, class PageIndicators extends St.BoxLayout {
|
||||
_init(vertical = true) {
|
||||
super._init({ style_class: 'page-indicators',
|
||||
vertical,
|
||||
x_expand: true, y_expand: true,
|
||||
x_align: vertical ? Clutter.ActorAlign.END : Clutter.ActorAlign.CENTER,
|
||||
y_align: vertical ? Clutter.ActorAlign.CENTER : Clutter.ActorAlign.END,
|
||||
reactive: true,
|
||||
clip_to_allocation: true });
|
||||
this._nPages = 0;
|
||||
this._currentPage = undefined;
|
||||
this._reactive = true;
|
||||
this._reactive = true;
|
||||
}
|
||||
|
||||
vfunc_get_preferred_height(forWidth) {
|
||||
// We want to request the natural height of all our children as our
|
||||
// natural height, so we chain up to St.BoxLayout, but we only request 0
|
||||
// as minimum height, since it's not that important if some indicators
|
||||
// are not shown
|
||||
let [, natHeight] = super.vfunc_get_preferred_height(forWidth);
|
||||
return [0, natHeight];
|
||||
}
|
||||
|
||||
setReactive(reactive) {
|
||||
let children = this.get_children();
|
||||
for (let i = 0; i < children.length; i++)
|
||||
children[i].reactive = reactive;
|
||||
|
||||
this._reactive = reactive;
|
||||
}
|
||||
|
||||
setNPages(nPages) {
|
||||
if (this._nPages == nPages)
|
||||
return;
|
||||
|
||||
let diff = nPages - this._nPages;
|
||||
if (diff > 0) {
|
||||
for (let i = 0; i < diff; i++) {
|
||||
let pageIndex = this._nPages + i;
|
||||
let indicator = new St.Button({ style_class: 'page-indicator',
|
||||
button_mask: St.ButtonMask.ONE |
|
||||
St.ButtonMask.TWO |
|
||||
St.ButtonMask.THREE,
|
||||
toggle_mode: true,
|
||||
reactive: this._reactive,
|
||||
checked: pageIndex == this._currentPage });
|
||||
indicator.child = new St.Widget({ style_class: 'page-indicator-icon' });
|
||||
indicator.connect('clicked', () => {
|
||||
this.emit('page-activated', pageIndex);
|
||||
});
|
||||
this.add_actor(indicator);
|
||||
}
|
||||
} else {
|
||||
let children = this.get_children().splice(diff);
|
||||
for (let i = 0; i < children.length; i++)
|
||||
children[i].destroy();
|
||||
}
|
||||
this._nPages = nPages;
|
||||
this.visible = (this._nPages > 1);
|
||||
}
|
||||
|
||||
setCurrentPage(currentPage) {
|
||||
this._currentPage = currentPage;
|
||||
|
||||
let children = this.get_children();
|
||||
for (let i = 0; i < children.length; i++)
|
||||
children[i].set_checked(i == this._currentPage);
|
||||
}
|
||||
});
|
||||
|
||||
var AnimatedPageIndicators = GObject.registerClass(
|
||||
class AnimatedPageIndicators extends PageIndicators {
|
||||
_init() {
|
||||
super._init(true);
|
||||
|
||||
this.connect('notify::mapped', () => {
|
||||
this.animateIndicators(AnimationDirection.IN);
|
||||
});
|
||||
}
|
||||
|
||||
animateIndicators(animationDirection) {
|
||||
if (!this.mapped)
|
||||
return;
|
||||
|
||||
let children = this.get_children();
|
||||
if (children.length == 0)
|
||||
return;
|
||||
|
||||
for (let i = 0; i < this._nPages; i++)
|
||||
Tweener.removeTweens(children[i]);
|
||||
|
||||
let offset;
|
||||
if (this.get_text_direction() == Clutter.TextDirection.RTL)
|
||||
offset = -children[0].width;
|
||||
else
|
||||
offset = children[0].width;
|
||||
|
||||
let isAnimationIn = animationDirection == AnimationDirection.IN;
|
||||
let delay = isAnimationIn ? INDICATORS_ANIMATION_DELAY :
|
||||
INDICATORS_ANIMATION_DELAY_OUT;
|
||||
let baseTime = isAnimationIn ? INDICATORS_BASE_TIME : INDICATORS_BASE_TIME_OUT;
|
||||
let totalAnimationTime = baseTime + delay * this._nPages;
|
||||
let maxTime = isAnimationIn ? INDICATORS_ANIMATION_MAX_TIME :
|
||||
INDICATORS_ANIMATION_MAX_TIME_OUT;
|
||||
if (totalAnimationTime > maxTime)
|
||||
delay -= (totalAnimationTime - maxTime) / this._nPages;
|
||||
|
||||
for (let i = 0; i < this._nPages; i++) {
|
||||
children[i].translation_x = isAnimationIn ? offset : 0;
|
||||
Tweener.addTween(children[i], {
|
||||
translation_x: isAnimationIn ? 0 : offset,
|
||||
time: baseTime + delay * i,
|
||||
transition: 'easeInOutQuad',
|
||||
delay: isAnimationIn ? ANIMATION_DELAY : 0
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
474
js/ui/panel.js
474
js/ui/panel.js
@@ -2,19 +2,15 @@
|
||||
|
||||
const Cairo = imports.cairo;
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const GObject = imports.gi.GObject;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Pango = imports.gi.Pango;
|
||||
const Shell = imports.gi.Shell;
|
||||
const St = imports.gi.St;
|
||||
const Signals = imports.signals;
|
||||
const Atk = imports.gi.Atk;
|
||||
|
||||
const Animation = imports.ui.animation;
|
||||
const Config = imports.misc.config;
|
||||
const CtrlAltTab = imports.ui.ctrlAltTab;
|
||||
const DND = imports.ui.dnd;
|
||||
@@ -22,15 +18,9 @@ const Overview = imports.ui.overview;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
const PanelMenu = imports.ui.panelMenu;
|
||||
const Main = imports.ui.main;
|
||||
const Tweener = imports.ui.tweener;
|
||||
|
||||
var PANEL_ICON_SIZE = 16;
|
||||
var APP_MENU_ICON_MARGIN = 0;
|
||||
|
||||
var BUTTON_DND_ACTIVATION_TIMEOUT = 250;
|
||||
|
||||
var SPINNER_ANIMATION_TIME = 1.0;
|
||||
|
||||
// To make sure the panel corners blend nicely with the panel,
|
||||
// we draw background and borders the same way, e.g. drawing
|
||||
// them as filled shapes from the outside inwards instead of
|
||||
@@ -74,395 +64,6 @@ function _unpremultiply(color) {
|
||||
blue: blue, alpha: color.alpha });
|
||||
};
|
||||
|
||||
class AppMenu extends PopupMenu.PopupMenu {
|
||||
constructor(sourceActor) {
|
||||
super(sourceActor, 0.0, St.Side.TOP);
|
||||
|
||||
this.actor.add_style_class_name('app-menu');
|
||||
|
||||
this._app = null;
|
||||
this._appSystem = Shell.AppSystem.get_default();
|
||||
|
||||
this._windowsChangedId = 0;
|
||||
|
||||
this._windowSection = new PopupMenu.PopupMenuSection();
|
||||
this.addMenuItem(this._windowSection);
|
||||
|
||||
this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
||||
|
||||
this._newWindowItem = this.addAction(_("New Window"), () => {
|
||||
this._app.open_new_window(-1);
|
||||
});
|
||||
|
||||
this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
||||
|
||||
this._actionSection = new PopupMenu.PopupMenuSection();
|
||||
this.addMenuItem(this._actionSection);
|
||||
|
||||
this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
||||
|
||||
this._detailsItem = this.addAction(_("Show Details"), () => {
|
||||
let id = this._app.get_id();
|
||||
let args = GLib.Variant.new('(ss)', [id, '']);
|
||||
Gio.DBus.get(Gio.BusType.SESSION, null, (o, res) => {
|
||||
let bus = Gio.DBus.get_finish(res);
|
||||
bus.call('org.gnome.Software',
|
||||
'/org/gnome/Software',
|
||||
'org.gtk.Actions', 'Activate',
|
||||
GLib.Variant.new('(sava{sv})',
|
||||
['details', [args], null]),
|
||||
null, 0, -1, null, null);
|
||||
});
|
||||
});
|
||||
|
||||
this.addAction(_("Quit"), () => {
|
||||
this._app.request_quit();
|
||||
});
|
||||
|
||||
this._appSystem.connect('installed-changed', () => {
|
||||
let sw = this._appSystem.lookup_app('org.gnome.Software.desktop');
|
||||
this._detailsItem.actor.visible = (sw != null);
|
||||
});
|
||||
}
|
||||
|
||||
isEmpty() {
|
||||
if (!this._app)
|
||||
return true;
|
||||
return super.isEmpty();
|
||||
}
|
||||
|
||||
setApp(app) {
|
||||
if (this._app == app)
|
||||
return;
|
||||
|
||||
if (this._windowsChangedId)
|
||||
this._app.disconnect(this._windowsChangedId);
|
||||
this._windowsChangedId = 0;
|
||||
|
||||
this._app = app;
|
||||
|
||||
if (app) {
|
||||
this._windowsChangedId = app.connect('windows-changed', () => {
|
||||
this._updateWindowsSection();
|
||||
});
|
||||
}
|
||||
|
||||
this._updateWindowsSection();
|
||||
|
||||
let appInfo = app ? app.app_info : null;
|
||||
let actions = appInfo ? appInfo.list_actions() : [];
|
||||
|
||||
this._actionSection.removeAll();
|
||||
actions.forEach(action => {
|
||||
let label = appInfo.get_action_name(action);
|
||||
this._actionSection.addAction(label, event => {
|
||||
this._app.launch_action(action, event.get_time(), -1);
|
||||
});
|
||||
});
|
||||
|
||||
this._newWindowItem.actor.visible =
|
||||
app && app.can_open_new_window() && !actions.includes('new-window');
|
||||
}
|
||||
|
||||
_updateWindowsSection() {
|
||||
this._windowSection.removeAll();
|
||||
|
||||
if (!this._app)
|
||||
return;
|
||||
|
||||
let windows = this._app.get_windows();
|
||||
windows.forEach(window => {
|
||||
let title = window.title || this._app.get_name();
|
||||
this._windowSection.addAction(title, event => {
|
||||
Main.activateWindow(window, event.get_time());
|
||||
});
|
||||
});
|
||||
|
||||
// Add separator between windows of the current desktop and other windows.
|
||||
let workspaceManager = global.workspace_manager;
|
||||
let activeWorkspace = workspaceManager.get_active_workspace();
|
||||
let pos = windows.findIndex(w => w.get_workspace() != activeWorkspace);
|
||||
if (pos >= 0)
|
||||
this._windowSection.addMenuItem(new PopupMenu.PopupSeparatorMenuItem(), pos);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* AppMenuButton:
|
||||
*
|
||||
* This class manages the "application menu" component. It tracks the
|
||||
* currently focused application. However, when an app is launched,
|
||||
* this menu also handles startup notification for it. So when we
|
||||
* have an active startup notification, we switch modes to display that.
|
||||
*/
|
||||
var AppMenuButton = GObject.registerClass({
|
||||
Signals: {'changed': {}},
|
||||
}, class AppMenuButton extends PanelMenu.Button {
|
||||
_init(panel) {
|
||||
super._init(0.0, null, true);
|
||||
|
||||
this.actor.accessible_role = Atk.Role.MENU;
|
||||
|
||||
this._startingApps = [];
|
||||
|
||||
this._menuManager = panel.menuManager;
|
||||
this._gtkSettings = Gtk.Settings.get_default();
|
||||
this._targetApp = null;
|
||||
this._busyNotifyId = 0;
|
||||
|
||||
let bin = new St.Bin({ name: 'appMenu' });
|
||||
bin.connect('style-changed', this._onStyleChanged.bind(this));
|
||||
this.actor.add_actor(bin);
|
||||
|
||||
this.actor.bind_property("reactive", this.actor, "can-focus", 0);
|
||||
this.actor.reactive = false;
|
||||
|
||||
this._container = new St.BoxLayout({ style_class: 'panel-status-menu-box' });
|
||||
bin.set_child(this._container);
|
||||
|
||||
let textureCache = St.TextureCache.get_default();
|
||||
textureCache.connect('icon-theme-changed',
|
||||
this._onIconThemeChanged.bind(this));
|
||||
|
||||
let iconEffect = new Clutter.DesaturateEffect();
|
||||
this._iconBox = new St.Bin({ style_class: 'app-menu-icon' });
|
||||
this._iconBox.add_effect(iconEffect);
|
||||
this._container.add_actor(this._iconBox);
|
||||
|
||||
this._iconBox.connect('style-changed', () => {
|
||||
let themeNode = this._iconBox.get_theme_node();
|
||||
iconEffect.enabled = themeNode.get_icon_style() == St.IconStyle.SYMBOLIC;
|
||||
});
|
||||
|
||||
this._label = new St.Label({ y_expand: true,
|
||||
y_align: Clutter.ActorAlign.CENTER });
|
||||
this._container.add_actor(this._label);
|
||||
this._arrow = PopupMenu.arrowIcon(St.Side.BOTTOM);
|
||||
this._container.add_actor(this._arrow);
|
||||
|
||||
this._visible = !Main.overview.visible;
|
||||
if (!this._visible)
|
||||
this.hide();
|
||||
this._overviewHidingId = Main.overview.connect('hiding', this._sync.bind(this));
|
||||
this._overviewShowingId = Main.overview.connect('showing', this._sync.bind(this));
|
||||
|
||||
this._stop = true;
|
||||
|
||||
this._spinner = null;
|
||||
|
||||
let menu = new AppMenu(this);
|
||||
this.setMenu(menu);
|
||||
this._menuManager.addMenu(menu);
|
||||
|
||||
let tracker = Shell.WindowTracker.get_default();
|
||||
let appSys = Shell.AppSystem.get_default();
|
||||
this._focusAppNotifyId =
|
||||
tracker.connect('notify::focus-app', this._focusAppChanged.bind(this));
|
||||
this._appStateChangedSignalId =
|
||||
appSys.connect('app-state-changed', this._onAppStateChanged.bind(this));
|
||||
this._switchWorkspaceNotifyId =
|
||||
global.window_manager.connect('switch-workspace', this._sync.bind(this));
|
||||
|
||||
this._sync();
|
||||
}
|
||||
|
||||
fadeIn() {
|
||||
if (this._visible)
|
||||
return;
|
||||
|
||||
this._visible = true;
|
||||
this.actor.reactive = true;
|
||||
this.show();
|
||||
Tweener.removeTweens(this.actor);
|
||||
Tweener.addTween(this.actor,
|
||||
{ opacity: 255,
|
||||
time: Overview.ANIMATION_TIME,
|
||||
transition: 'easeOutQuad' });
|
||||
}
|
||||
|
||||
fadeOut() {
|
||||
if (!this._visible)
|
||||
return;
|
||||
|
||||
this._visible = false;
|
||||
this.actor.reactive = false;
|
||||
Tweener.removeTweens(this.actor);
|
||||
Tweener.addTween(this.actor,
|
||||
{ opacity: 0,
|
||||
time: Overview.ANIMATION_TIME,
|
||||
transition: 'easeOutQuad',
|
||||
onComplete() {
|
||||
this.hide();
|
||||
},
|
||||
onCompleteScope: this });
|
||||
}
|
||||
|
||||
_onStyleChanged(actor) {
|
||||
let node = actor.get_theme_node();
|
||||
let [success, icon] = node.lookup_url('spinner-image', false);
|
||||
if (!success || (this._spinnerIcon && this._spinnerIcon.equal(icon)))
|
||||
return;
|
||||
this._spinnerIcon = icon;
|
||||
this._spinner = new Animation.AnimatedIcon(this._spinnerIcon, PANEL_ICON_SIZE);
|
||||
this._container.add_actor(this._spinner.actor);
|
||||
this._spinner.actor.hide();
|
||||
}
|
||||
|
||||
_syncIcon() {
|
||||
if (!this._targetApp)
|
||||
return;
|
||||
|
||||
let icon = this._targetApp.create_icon_texture(PANEL_ICON_SIZE - APP_MENU_ICON_MARGIN);
|
||||
this._iconBox.set_child(icon);
|
||||
}
|
||||
|
||||
_onIconThemeChanged() {
|
||||
if (this._iconBox.child == null)
|
||||
return;
|
||||
|
||||
this._syncIcon();
|
||||
}
|
||||
|
||||
stopAnimation() {
|
||||
if (this._stop)
|
||||
return;
|
||||
|
||||
this._stop = true;
|
||||
|
||||
if (this._spinner == null)
|
||||
return;
|
||||
|
||||
Tweener.addTween(this._spinner.actor,
|
||||
{ opacity: 0,
|
||||
time: SPINNER_ANIMATION_TIME,
|
||||
transition: "easeOutQuad",
|
||||
onCompleteScope: this,
|
||||
onComplete() {
|
||||
this._spinner.stop();
|
||||
this._spinner.actor.opacity = 255;
|
||||
this._spinner.actor.hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
startAnimation() {
|
||||
this._stop = false;
|
||||
|
||||
if (this._spinner == null)
|
||||
return;
|
||||
|
||||
this._spinner.play();
|
||||
this._spinner.actor.show();
|
||||
}
|
||||
|
||||
_onAppStateChanged(appSys, app) {
|
||||
let state = app.state;
|
||||
if (state != Shell.AppState.STARTING)
|
||||
this._startingApps = this._startingApps.filter(a => a != app);
|
||||
else if (state == Shell.AppState.STARTING)
|
||||
this._startingApps.push(app);
|
||||
// For now just resync on all running state changes; this is mainly to handle
|
||||
// cases where the focused window's application changes without the focus
|
||||
// changing. An example case is how we map OpenOffice.org based on the window
|
||||
// title which is a dynamic property.
|
||||
this._sync();
|
||||
}
|
||||
|
||||
_focusAppChanged() {
|
||||
let tracker = Shell.WindowTracker.get_default();
|
||||
let focusedApp = tracker.focus_app;
|
||||
if (!focusedApp) {
|
||||
// If the app has just lost focus to the panel, pretend
|
||||
// nothing happened; otherwise you can't keynav to the
|
||||
// app menu.
|
||||
if (global.stage.key_focus != null)
|
||||
return;
|
||||
}
|
||||
this._sync();
|
||||
}
|
||||
|
||||
_findTargetApp() {
|
||||
let workspaceManager = global.workspace_manager;
|
||||
let workspace = workspaceManager.get_active_workspace();
|
||||
let tracker = Shell.WindowTracker.get_default();
|
||||
let focusedApp = tracker.focus_app;
|
||||
if (focusedApp && focusedApp.is_on_workspace(workspace))
|
||||
return focusedApp;
|
||||
|
||||
for (let i = 0; i < this._startingApps.length; i++)
|
||||
if (this._startingApps[i].is_on_workspace(workspace))
|
||||
return this._startingApps[i];
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
_sync() {
|
||||
let targetApp = this._findTargetApp();
|
||||
|
||||
if (this._targetApp != targetApp) {
|
||||
if (this._busyNotifyId) {
|
||||
this._targetApp.disconnect(this._busyNotifyId);
|
||||
this._busyNotifyId = 0;
|
||||
}
|
||||
|
||||
this._targetApp = targetApp;
|
||||
|
||||
if (this._targetApp) {
|
||||
this._busyNotifyId = this._targetApp.connect('notify::busy', this._sync.bind(this));
|
||||
this._label.set_text(this._targetApp.get_name());
|
||||
this.actor.set_accessible_name(this._targetApp.get_name());
|
||||
}
|
||||
}
|
||||
|
||||
let visible = (this._targetApp != null && !Main.overview.visibleTarget);
|
||||
if (visible)
|
||||
this.fadeIn();
|
||||
else
|
||||
this.fadeOut();
|
||||
|
||||
let isBusy = (this._targetApp != null &&
|
||||
(this._targetApp.get_state() == Shell.AppState.STARTING ||
|
||||
this._targetApp.get_busy()));
|
||||
if (isBusy)
|
||||
this.startAnimation();
|
||||
else
|
||||
this.stopAnimation();
|
||||
|
||||
this.actor.reactive = (visible && !isBusy);
|
||||
|
||||
this._syncIcon();
|
||||
this.menu.setApp(this._targetApp);
|
||||
this.emit('changed');
|
||||
}
|
||||
|
||||
_onDestroy() {
|
||||
if (this._appStateChangedSignalId > 0) {
|
||||
let appSys = Shell.AppSystem.get_default();
|
||||
appSys.disconnect(this._appStateChangedSignalId);
|
||||
this._appStateChangedSignalId = 0;
|
||||
}
|
||||
if (this._focusAppNotifyId > 0) {
|
||||
let tracker = Shell.WindowTracker.get_default();
|
||||
tracker.disconnect(this._focusAppNotifyId);
|
||||
this._focusAppNotifyId = 0;
|
||||
}
|
||||
if (this._overviewHidingId > 0) {
|
||||
Main.overview.disconnect(this._overviewHidingId);
|
||||
this._overviewHidingId = 0;
|
||||
}
|
||||
if (this._overviewShowingId > 0) {
|
||||
Main.overview.disconnect(this._overviewShowingId);
|
||||
this._overviewShowingId = 0;
|
||||
}
|
||||
if (this._switchWorkspaceNotifyId > 0) {
|
||||
global.window_manager.disconnect(this._switchWorkspaceNotifyId);
|
||||
this._switchWorkspaceNotifyId = 0;
|
||||
}
|
||||
|
||||
super._onDestroy();
|
||||
}
|
||||
});
|
||||
|
||||
var ActivitiesButton = GObject.registerClass(
|
||||
class ActivitiesButton extends PanelMenu.Button {
|
||||
_init() {
|
||||
@@ -821,7 +422,6 @@ class AggregateMenu extends PanelMenu.Button {
|
||||
const PANEL_ITEM_IMPLEMENTATIONS = {
|
||||
'activities': ActivitiesButton,
|
||||
'aggregateMenu': AggregateMenu,
|
||||
'appMenu': AppMenuButton,
|
||||
'dateMenu': imports.ui.dateMenu.DateMenuButton,
|
||||
'a11y': imports.ui.status.accessibility.ATIndicator,
|
||||
'keyboard': imports.ui.status.keyboard.InputSourceIndicator,
|
||||
@@ -840,6 +440,8 @@ class Panel extends St.Widget {
|
||||
|
||||
this._sessionStyle = null;
|
||||
|
||||
Meta.prefs_set_show_fallback_app_menu(true);
|
||||
|
||||
this.statusArea = {};
|
||||
|
||||
this.menuManager = new PopupMenu.PopupMenuManager(this);
|
||||
@@ -863,9 +465,11 @@ class Panel extends St.Widget {
|
||||
|
||||
Main.overview.connect('showing', () => {
|
||||
this.add_style_pseudo_class('overview');
|
||||
this._updateSolidStyle();
|
||||
});
|
||||
Main.overview.connect('hiding', () => {
|
||||
this.remove_style_pseudo_class('overview');
|
||||
this._updateSolidStyle();
|
||||
});
|
||||
|
||||
Main.layoutManager.panelBox.add(this);
|
||||
@@ -874,11 +478,32 @@ class Panel extends St.Widget {
|
||||
|
||||
Main.sessionMode.connect('updated', this._updatePanel.bind(this));
|
||||
|
||||
this._trackedWindows = new Map();
|
||||
global.window_group.connect('actor-added', this._onWindowActorAdded.bind(this));
|
||||
global.window_group.connect('actor-removed', this._onWindowActorRemoved.bind(this));
|
||||
global.window_manager.connect('switch-workspace', this._updateSolidStyle.bind(this));
|
||||
|
||||
global.display.connect('workareas-changed', () => { this.queue_relayout(); });
|
||||
this._updatePanel();
|
||||
}
|
||||
|
||||
vfunc_get_preferred_width(forHeight) {
|
||||
_onWindowActorAdded(container, metaWindowActor) {
|
||||
let signalIds = [];
|
||||
['allocation-changed', 'notify::visible'].forEach(s => {
|
||||
signalIds.push(metaWindowActor.connect(s, this._updateSolidStyle.bind(this)));
|
||||
});
|
||||
this._trackedWindows.set(metaWindowActor, signalIds);
|
||||
}
|
||||
|
||||
_onWindowActorRemoved(container, metaWindowActor) {
|
||||
this._trackedWindows.get(metaWindowActor).forEach(id => {
|
||||
metaWindowActor.disconnect(id);
|
||||
});
|
||||
this._trackedWindows.delete(metaWindowActor);
|
||||
this._updateSolidStyle();
|
||||
}
|
||||
|
||||
vfunc_get_preferred_width(actor, forHeight) {
|
||||
let primaryMonitor = Main.layoutManager.primaryMonitor;
|
||||
|
||||
if (primaryMonitor)
|
||||
@@ -1023,8 +648,8 @@ class Panel extends St.Widget {
|
||||
}
|
||||
|
||||
_toggleMenu(indicator) {
|
||||
if (!indicator || !indicator.container.visible)
|
||||
return; // menu not supported by current session mode
|
||||
if (!indicator) // menu not supported by current session mode
|
||||
return;
|
||||
|
||||
let menu = indicator.menu;
|
||||
if (!indicator.actor.reactive)
|
||||
@@ -1032,11 +657,7 @@ class Panel extends St.Widget {
|
||||
|
||||
menu.toggle();
|
||||
if (menu.isOpen)
|
||||
menu.actor.navigate_focus(null, St.DirectionType.TAB_FORWARD, false);
|
||||
}
|
||||
|
||||
toggleAppMenu() {
|
||||
this._toggleMenu(this.statusArea.appMenu);
|
||||
menu.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
|
||||
}
|
||||
|
||||
toggleCalendar() {
|
||||
@@ -1085,6 +706,8 @@ class Panel extends St.Widget {
|
||||
else
|
||||
Main.messageTray.bannerAlignment = Clutter.ActorAlign.CENTER;
|
||||
|
||||
this._updateSolidStyle();
|
||||
|
||||
if (this._sessionStyle)
|
||||
this._removeStyleClassName(this._sessionStyle);
|
||||
|
||||
@@ -1101,6 +724,41 @@ class Panel extends St.Widget {
|
||||
}
|
||||
}
|
||||
|
||||
_updateSolidStyle() {
|
||||
if (this.has_style_pseudo_class('overview') || !Main.sessionMode.hasWindows) {
|
||||
this._removeStyleClassName('solid');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Main.layoutManager.primaryMonitor)
|
||||
return;
|
||||
|
||||
/* Get all the windows in the active workspace that are in the primary monitor and visible */
|
||||
let workspaceManager = global.workspace_manager;
|
||||
let activeWorkspace = workspaceManager.get_active_workspace();
|
||||
let windows = activeWorkspace.list_windows().filter(metaWindow => {
|
||||
return metaWindow.is_on_primary_monitor() &&
|
||||
metaWindow.showing_on_its_workspace() &&
|
||||
!metaWindow.is_hidden() &&
|
||||
metaWindow.get_window_type() != Meta.WindowType.DESKTOP;
|
||||
});
|
||||
|
||||
/* Check if at least one window is near enough to the panel */
|
||||
let [, panelTop] = this.get_transformed_position();
|
||||
let panelBottom = panelTop + this.get_height();
|
||||
let scale = St.ThemeContext.get_for_stage(global.stage).scale_factor;
|
||||
let isNearEnough = windows.some(metaWindow => {
|
||||
let verticalPosition = metaWindow.get_frame_rect().y;
|
||||
return verticalPosition < panelBottom + 5 * scale;
|
||||
});
|
||||
|
||||
if (isNearEnough)
|
||||
this._addStyleClassName('solid');
|
||||
else
|
||||
this._removeStyleClassName('solid');
|
||||
|
||||
}
|
||||
|
||||
_hideIndicators() {
|
||||
for (let role in PANEL_ITEM_IMPLEMENTATIONS) {
|
||||
let indicator = this.statusArea[role];
|
||||
|
@@ -3,6 +3,7 @@
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GObject = imports.gi.GObject;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Signals = imports.signals;
|
||||
const St = imports.gi.St;
|
||||
@@ -162,7 +163,7 @@ var Button = GObject.registerClass({
|
||||
if (symbol == Clutter.KEY_Left || symbol == Clutter.KEY_Right) {
|
||||
let group = global.focus_manager.get_group(this.actor);
|
||||
if (group) {
|
||||
let direction = (symbol == Clutter.KEY_Left) ? St.DirectionType.LEFT : St.DirectionType.RIGHT;
|
||||
let direction = (symbol == Clutter.KEY_Left) ? Gtk.DirectionType.LEFT : Gtk.DirectionType.RIGHT;
|
||||
group.navigate_focus(this.actor, direction, false);
|
||||
return Clutter.EVENT_STOP;
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GObject = imports.gi.GObject;
|
||||
const Shell = imports.gi.Shell;
|
||||
@@ -542,7 +543,7 @@ var PopupMenuBase = class {
|
||||
let sensitive = menuItem.getSensitive();
|
||||
if (!sensitive && this._activeMenuItem == menuItem) {
|
||||
if (!this.actor.navigate_focus(menuItem.actor,
|
||||
St.DirectionType.TAB_FORWARD,
|
||||
Gtk.DirectionType.TAB_FORWARD,
|
||||
true))
|
||||
this.actor.grab_key_focus();
|
||||
} else if (sensitive && this._activeMenuItem == null) {
|
||||
@@ -828,7 +829,7 @@ var PopupMenu = class extends PopupMenuBase {
|
||||
} else if (symbol == navKey) {
|
||||
if (!this.isOpen)
|
||||
this.toggle();
|
||||
this.actor.navigate_focus(null, St.DirectionType.TAB_FORWARD, false);
|
||||
this.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
|
||||
return Clutter.EVENT_STOP;
|
||||
} else
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
@@ -913,8 +914,8 @@ var PopupSubMenu = class extends PopupMenuBase {
|
||||
// with long content, we make it scrollable - the scrollbar will only take
|
||||
// effect if a CSS max-height is set on the top menu.
|
||||
this.actor = new St.ScrollView({ style_class: 'popup-sub-menu',
|
||||
hscrollbar_policy: St.PolicyType.NEVER,
|
||||
vscrollbar_policy: St.PolicyType.NEVER });
|
||||
hscrollbar_policy: Gtk.PolicyType.NEVER,
|
||||
vscrollbar_policy: Gtk.PolicyType.NEVER });
|
||||
|
||||
this.actor.add_actor(this.box);
|
||||
this.actor._delegate = this;
|
||||
@@ -956,7 +957,7 @@ var PopupSubMenu = class extends PopupMenuBase {
|
||||
// when we *don't* need it, so turn off the scrollbar when that's true.
|
||||
// Dynamic changes in whether we need it aren't handled properly.
|
||||
this.actor.vscrollbar_policy =
|
||||
needsScrollbar ? St.PolicyType.AUTOMATIC : St.PolicyType.NEVER;
|
||||
needsScrollbar ? Gtk.PolicyType.AUTOMATIC : Gtk.PolicyType.NEVER;
|
||||
|
||||
if (needsScrollbar)
|
||||
this.actor.add_style_pseudo_class('scrolled');
|
||||
@@ -1149,7 +1150,7 @@ var PopupSubMenuMenuItem = class extends PopupBaseMenuItem {
|
||||
|
||||
if (symbol == Clutter.KEY_Right) {
|
||||
this._setOpenState(true);
|
||||
this.menu.actor.navigate_focus(null, St.DirectionType.DOWN, false);
|
||||
this.menu.actor.navigate_focus(null, Gtk.DirectionType.DOWN, false);
|
||||
return Clutter.EVENT_STOP;
|
||||
} else if (symbol == Clutter.KEY_Left && this._getOpenState()) {
|
||||
this._setOpenState(false);
|
||||
|
@@ -2,12 +2,12 @@
|
||||
|
||||
const AccountsService = imports.gi.AccountsService;
|
||||
const Cairo = imports.cairo;
|
||||
const Cogl = imports.gi.Cogl;
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const GnomeDesktop = imports.gi.GnomeDesktop;
|
||||
const GObject = imports.gi.GObject;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Shell = imports.gi.Shell;
|
||||
@@ -100,7 +100,7 @@ var NotificationsBox = class {
|
||||
style_class: 'screen-shield-notifications-container' });
|
||||
|
||||
this._scrollView = new St.ScrollView({ x_fill: false, x_align: St.Align.START,
|
||||
hscrollbar_policy: St.PolicyType.NEVER });
|
||||
hscrollbar_policy: Gtk.PolicyType.NEVER });
|
||||
this._notificationBox = new St.BoxLayout({ vertical: true,
|
||||
style_class: 'screen-shield-notifications-container' });
|
||||
this._scrollView.add_actor(this._notificationBox);
|
||||
@@ -202,11 +202,6 @@ var NotificationsBox = class {
|
||||
return [title, null];
|
||||
}
|
||||
|
||||
_shouldShowDetails(source) {
|
||||
return source.policy.detailsInLockScreen ||
|
||||
source.narrowestPrivacyScope == MessageTray.PrivacyScope.SYSTEM;
|
||||
}
|
||||
|
||||
_showSource(source, obj, box) {
|
||||
if (obj.detailed) {
|
||||
[obj.titleLabel, obj.countLabel] = this._makeNotificationDetailedSource(source, box);
|
||||
@@ -220,7 +215,7 @@ var NotificationsBox = class {
|
||||
_sourceAdded(tray, source, initial) {
|
||||
let obj = {
|
||||
visible: source.policy.showInLockScreen,
|
||||
detailed: this._shouldShowDetails(source),
|
||||
detailed: source.policy.detailsInLockScreen,
|
||||
sourceDestroyId: 0,
|
||||
sourceCountChangedId: 0,
|
||||
sourceTitleChangedId: 0,
|
||||
@@ -257,7 +252,7 @@ var NotificationsBox = class {
|
||||
// block scrollbars while animating, if they're not needed now
|
||||
let boxHeight = this._notificationBox.height;
|
||||
if (this._scrollView.height >= boxHeight)
|
||||
this._scrollView.vscrollbar_policy = St.PolicyType.NEVER;
|
||||
this._scrollView.vscrollbar_policy = Gtk.PolicyType.NEVER;
|
||||
|
||||
let widget = obj.sourceBox;
|
||||
let [, natHeight] = widget.get_preferred_height(-1);
|
||||
@@ -267,7 +262,7 @@ var NotificationsBox = class {
|
||||
transition: 'easeOutQuad',
|
||||
time: 0.25,
|
||||
onComplete() {
|
||||
this._scrollView.vscrollbar_policy = St.PolicyType.AUTOMATIC;
|
||||
this._scrollView.vscrollbar_policy = Gtk.PolicyType.AUTOMATIC;
|
||||
widget.set_height(-1);
|
||||
},
|
||||
onCompleteScope: this
|
||||
@@ -284,14 +279,7 @@ var NotificationsBox = class {
|
||||
}
|
||||
|
||||
_countChanged(source, obj) {
|
||||
// A change in the number of notifications may change whether we show
|
||||
// details.
|
||||
let newDetailed = this._shouldShowDetails(source);
|
||||
let oldDetailed = obj.detailed;
|
||||
|
||||
obj.detailed = newDetailed;
|
||||
|
||||
if (obj.detailed || oldDetailed != newDetailed) {
|
||||
if (obj.detailed) {
|
||||
// A new notification was pushed, or a previous notification was destroyed.
|
||||
// Give up, and build the list again.
|
||||
|
||||
@@ -323,11 +311,10 @@ var NotificationsBox = class {
|
||||
}
|
||||
|
||||
_detailedChanged(source, obj) {
|
||||
let newDetailed = this._shouldShowDetails(source);
|
||||
if (obj.detailed == newDetailed)
|
||||
if (obj.detailed == source.policy.detailsInLockScreen)
|
||||
return;
|
||||
|
||||
obj.detailed = newDetailed;
|
||||
obj.detailed = source.policy.detailsInLockScreen;
|
||||
|
||||
obj.sourceBox.destroy_all_children();
|
||||
obj.titleLabel = obj.countLabel = null;
|
||||
@@ -418,9 +405,7 @@ class ScreenShieldArrow extends St.Bin {
|
||||
|
||||
let allocation = this._drawingArea.get_allocation_box();
|
||||
let paintOpacity = this._drawingArea.get_paint_opacity();
|
||||
let framebuffer = Cogl.get_draw_framebuffer();
|
||||
|
||||
this._shadowHelper.paint(framebuffer, allocation, paintOpacity);
|
||||
this._shadowHelper.paint(allocation, paintOpacity);
|
||||
}
|
||||
|
||||
this._drawingArea.paint();
|
||||
@@ -933,7 +918,7 @@ var ScreenShield = class {
|
||||
|
||||
if (this._dialog) {
|
||||
this._dialog.actor.grab_key_focus();
|
||||
this._dialog.actor.navigate_focus(null, St.DirectionType.TAB_FORWARD, false);
|
||||
this._dialog.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,6 +1,7 @@
|
||||
// -*- 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;
|
||||
@@ -106,7 +107,7 @@ var ScreenshotService = class {
|
||||
}
|
||||
|
||||
ScreenshotAreaAsync(params, invocation) {
|
||||
let [x, y, width, height, flash, filename] = params;
|
||||
let [x, y, width, height, flash, filename, callback] = params;
|
||||
[x, y, width, height] = this._scaleArea(x, y, width, height);
|
||||
if (!this._checkArea(x, y, width, height)) {
|
||||
invocation.return_error_literal(Gio.IOErrorEnum,
|
||||
|
@@ -4,6 +4,7 @@ const Clutter = imports.gi.Clutter;
|
||||
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 Signals = imports.signals;
|
||||
const Shell = imports.gi.Shell;
|
||||
@@ -401,7 +402,7 @@ var SearchResults = class {
|
||||
y_fill: false,
|
||||
overlay_scrollbars: true,
|
||||
style_class: 'search-display vfade' });
|
||||
this._scrollView.set_policy(St.PolicyType.NEVER, St.PolicyType.AUTOMATIC);
|
||||
this._scrollView.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
|
||||
this._scrollView.add_actor(scrollChild);
|
||||
let action = new Clutter.PanAction({ interpolate: true });
|
||||
action.connect('pan', this._onPan.bind(this));
|
||||
@@ -685,10 +686,10 @@ var SearchResults = class {
|
||||
|
||||
navigateFocus(direction) {
|
||||
let rtl = this.actor.get_text_direction() == Clutter.TextDirection.RTL;
|
||||
if (direction == St.DirectionType.TAB_BACKWARD ||
|
||||
direction == (rtl ? St.DirectionType.RIGHT
|
||||
: St.DirectionType.LEFT) ||
|
||||
direction == St.DirectionType.UP) {
|
||||
if (direction == Gtk.DirectionType.TAB_BACKWARD ||
|
||||
direction == (rtl ? Gtk.DirectionType.RIGHT
|
||||
: Gtk.DirectionType.LEFT) ||
|
||||
direction == Gtk.DirectionType.UP) {
|
||||
this.actor.navigate_focus(null, direction, false);
|
||||
return;
|
||||
}
|
||||
|
@@ -98,7 +98,7 @@ const _modes = {
|
||||
'keyring', 'autorunManager', 'automountManager'],
|
||||
|
||||
panel: {
|
||||
left: ['activities', 'appMenu'],
|
||||
left: ['activities'],
|
||||
center: ['dateMenu'],
|
||||
right: ['a11y', 'keyboard', 'aggregateMenu']
|
||||
}
|
||||
|
@@ -1,13 +1,13 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const St = imports.gi.St;
|
||||
|
||||
const BoxPointer = imports.ui.boxpointer;
|
||||
const Main = imports.ui.main;
|
||||
const Params = imports.misc.params;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
const Shell = imports.gi.Shell;
|
||||
|
||||
var EntryMenu = class extends PopupMenu.PopupMenu {
|
||||
constructor(entry) {
|
||||
@@ -68,7 +68,7 @@ var EntryMenu = class extends PopupMenu.PopupMenu {
|
||||
super.open(animate);
|
||||
this._entry.add_style_pseudo_class('focus');
|
||||
|
||||
let direction = St.DirectionType.TAB_FORWARD;
|
||||
let direction = Gtk.DirectionType.TAB_FORWARD;
|
||||
if (!this.actor.navigate_focus(null, direction, false))
|
||||
this.actor.grab_key_focus();
|
||||
}
|
||||
@@ -146,12 +146,11 @@ function addContextMenu(entry, params) {
|
||||
if (entry.menu)
|
||||
return;
|
||||
|
||||
params = Params.parse (params, { isPassword: false, actionMode: Shell.ActionMode.POPUP });
|
||||
params = Params.parse (params, { isPassword: false });
|
||||
|
||||
entry.menu = new EntryMenu(entry);
|
||||
entry.menu.isPassword = params.isPassword;
|
||||
entry._menuManager = new PopupMenu.PopupMenuManager({ actor: entry },
|
||||
{ actionMode: params.actionMode });
|
||||
entry._menuManager = new PopupMenu.PopupMenuManager({ actor: entry });
|
||||
entry._menuManager.addMenu(entry.menu);
|
||||
|
||||
// Add an event handler to both the entry and its clutter_text; the former
|
||||
|
@@ -4,6 +4,7 @@ const Clutter = imports.gi.Clutter;
|
||||
const Signals = imports.signals;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Pango = imports.gi.Pango;
|
||||
const St = imports.gi.St;
|
||||
const Shell = imports.gi.Shell;
|
||||
@@ -370,8 +371,8 @@ var ShellProcessesDialog = class extends ModalDialog.ModalDialog {
|
||||
this.contentLayout.add(this._content, { x_fill: true, y_fill: false });
|
||||
|
||||
let scrollView = new St.ScrollView({ style_class: 'mount-dialog-app-list'});
|
||||
scrollView.set_policy(St.PolicyType.NEVER,
|
||||
St.PolicyType.AUTOMATIC);
|
||||
scrollView.set_policy(Gtk.PolicyType.NEVER,
|
||||
Gtk.PolicyType.AUTOMATIC);
|
||||
this.contentLayout.add(scrollView,
|
||||
{ x_fill: true,
|
||||
y_fill: true });
|
||||
|
@@ -29,6 +29,7 @@ const KEY_VISUAL_BELL = 'visual-bell';
|
||||
const DESKTOP_INTERFACE_SCHEMA = 'org.gnome.desktop.interface';
|
||||
const KEY_GTK_THEME = 'gtk-theme';
|
||||
const KEY_ICON_THEME = 'icon-theme';
|
||||
const KEY_WM_THEME = 'theme';
|
||||
const KEY_TEXT_SCALING_FACTOR = 'text-scaling-factor';
|
||||
|
||||
const HIGH_CONTRAST_THEME = 'HighContrast';
|
||||
@@ -131,6 +132,7 @@ class ATIndicator extends PanelMenu.Button {
|
||||
|
||||
_buildHCItem() {
|
||||
let interfaceSettings = new Gio.Settings({ schema_id: DESKTOP_INTERFACE_SCHEMA });
|
||||
let wmSettings = new Gio.Settings({ schema_id: WM_SCHEMA });
|
||||
interfaceSettings.connect('changed::' + KEY_GTK_THEME, () => {
|
||||
let value = interfaceSettings.get_string(KEY_GTK_THEME);
|
||||
if (value == HIGH_CONTRAST_THEME) {
|
||||
@@ -147,25 +149,35 @@ class ATIndicator extends PanelMenu.Button {
|
||||
if (value != HIGH_CONTRAST_THEME)
|
||||
iconTheme = value;
|
||||
});
|
||||
wmSettings.connect('changed::' + KEY_WM_THEME, () => {
|
||||
let value = wmSettings.get_string(KEY_WM_THEME);
|
||||
if (value != HIGH_CONTRAST_THEME)
|
||||
wmTheme = value;
|
||||
});
|
||||
|
||||
let gtkTheme = interfaceSettings.get_string(KEY_GTK_THEME);
|
||||
let iconTheme = interfaceSettings.get_string(KEY_ICON_THEME);
|
||||
let wmTheme = wmSettings.get_string(KEY_WM_THEME);
|
||||
let hasHC = (gtkTheme == HIGH_CONTRAST_THEME);
|
||||
let highContrast = this._buildItemExtended(
|
||||
_("High Contrast"),
|
||||
hasHC,
|
||||
interfaceSettings.is_writable(KEY_GTK_THEME) &&
|
||||
interfaceSettings.is_writable(KEY_ICON_THEME),
|
||||
interfaceSettings.is_writable(KEY_ICON_THEME) &&
|
||||
wmSettings.is_writable(KEY_WM_THEME),
|
||||
enabled => {
|
||||
if (enabled) {
|
||||
interfaceSettings.set_string(KEY_GTK_THEME, HIGH_CONTRAST_THEME);
|
||||
interfaceSettings.set_string(KEY_ICON_THEME, HIGH_CONTRAST_THEME);
|
||||
wmSettings.set_string(KEY_WM_THEME, HIGH_CONTRAST_THEME);
|
||||
} else if(!hasHC) {
|
||||
interfaceSettings.set_string(KEY_GTK_THEME, gtkTheme);
|
||||
interfaceSettings.set_string(KEY_ICON_THEME, iconTheme);
|
||||
wmSettings.set_string(KEY_WM_THEME, wmTheme);
|
||||
} else {
|
||||
interfaceSettings.reset(KEY_GTK_THEME);
|
||||
interfaceSettings.reset(KEY_ICON_THEME);
|
||||
wmSettings.reset(KEY_WM_THEME);
|
||||
}
|
||||
});
|
||||
return highContrast;
|
||||
|
@@ -969,8 +969,7 @@ class InputSourceIndicator extends PanelMenu.Button {
|
||||
}
|
||||
|
||||
let item;
|
||||
let type = prop.get_prop_type();
|
||||
switch (type) {
|
||||
switch (prop.get_prop_type()) {
|
||||
case IBus.PropType.MENU:
|
||||
item = new PopupMenu.PopupSubMenuMenuItem(prop.get_label().get_text());
|
||||
this._buildPropSubMenu(item.menu, prop.get_sub_props());
|
||||
|
@@ -3,6 +3,7 @@ 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 NM = imports.gi.NM;
|
||||
const Signals = imports.signals;
|
||||
@@ -845,8 +846,8 @@ var NMWirelessDialog = class extends ModalDialog.ModalDialog {
|
||||
this._scrollView = new St.ScrollView({ style_class: 'nm-dialog-scroll-view' });
|
||||
this._scrollView.set_x_expand(true);
|
||||
this._scrollView.set_y_expand(true);
|
||||
this._scrollView.set_policy(St.PolicyType.NEVER,
|
||||
St.PolicyType.AUTOMATIC);
|
||||
this._scrollView.set_policy(Gtk.PolicyType.NEVER,
|
||||
Gtk.PolicyType.AUTOMATIC);
|
||||
this._scrollView.add_actor(this._itemBox);
|
||||
this._stack.add_child(this._scrollView);
|
||||
|
||||
|
@@ -4,7 +4,6 @@ const AccountsService = imports.gi.AccountsService;
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Pango = imports.gi.Pango;
|
||||
const Shell = imports.gi.Shell;
|
||||
const St = imports.gi.St;
|
||||
const GObject = imports.gi.GObject;
|
||||
@@ -164,15 +163,18 @@ var Indicator = class extends PanelMenu.SystemIndicator {
|
||||
}
|
||||
|
||||
_updateSwitchUserSubMenu() {
|
||||
let realName = this._user.get_real_name();
|
||||
this._switchUserSubMenu.label.text = this._user.get_real_name();
|
||||
let clutterText = this._switchUserSubMenu.label.clutter_text;
|
||||
|
||||
// In theory, GNOME allows creating users with names up to 255
|
||||
// characters, but such long names look terribly bad, so limit
|
||||
// to 100 and it should fit the vast majority of screen sizes.
|
||||
if (realName.length > 100)
|
||||
// XXX -- for some reason, the ClutterText's width changes
|
||||
// rapidly unless we force a relayout of the actor. Probably
|
||||
// a size cache issue or something. Moving this to be a layout
|
||||
// manager would be a much better idea.
|
||||
clutterText.get_allocation_box();
|
||||
|
||||
let layout = clutterText.get_layout();
|
||||
if (layout.is_ellipsized())
|
||||
this._switchUserSubMenu.label.text = this._user.get_user_name();
|
||||
else
|
||||
this._switchUserSubMenu.label.text = realName;
|
||||
|
||||
let iconFile = this._user.get_icon_file();
|
||||
if (iconFile && !GLib.file_test(iconFile, GLib.FileTest.EXISTS))
|
||||
@@ -209,7 +211,6 @@ var Indicator = class extends PanelMenu.SystemIndicator {
|
||||
|
||||
this._switchUserSubMenu = new PopupMenu.PopupSubMenuMenuItem('', true);
|
||||
this._switchUserSubMenu.icon.style_class = 'system-switch-user-submenu-icon';
|
||||
this._switchUserSubMenu.label.clutter_text.ellipsize = Pango.EllipsizeMode.END;
|
||||
|
||||
// Since the label of the switch user submenu depends on the width of
|
||||
// the popup menu, and we can't easily connect on allocation-changed
|
||||
|
@@ -334,7 +334,7 @@ var Indicator = class extends PanelMenu.SystemIndicator {
|
||||
|
||||
_onEnrollFailed(obj, device, error) {
|
||||
const title = _("Thunderbolt authorization error");
|
||||
const body = _("Could not authorize the Thunderbolt device: %s").format(error.message);
|
||||
const body = _("Could not authorize the Thunderbolt device: %s".format(error.message));
|
||||
this._notify(title, body);
|
||||
}
|
||||
};
|
||||
|
@@ -3,6 +3,7 @@
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const GLib = imports.gi.GLib;
|
||||
const GObject = imports.gi.GObject;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Shell = imports.gi.Shell;
|
||||
@@ -364,7 +365,7 @@ var SwitcherList = GObject.registerClass({
|
||||
|
||||
this._scrollView = new St.ScrollView({ style_class: 'hfade',
|
||||
enable_mouse_scrolling: false });
|
||||
this._scrollView.set_policy(St.PolicyType.NEVER, St.PolicyType.NEVER);
|
||||
this._scrollView.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.NEVER);
|
||||
|
||||
this._scrollView.add_actor(this._list);
|
||||
this.add_actor(this._scrollView);
|
||||
|
@@ -2,6 +2,7 @@
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Shell = imports.gi.Shell;
|
||||
const St = imports.gi.St;
|
||||
@@ -51,7 +52,7 @@ function _wrapTweening(target, tweeningParameters) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!St.Settings.get().enable_animations) {
|
||||
if (!Gtk.Settings.get_default().gtk_enable_animations) {
|
||||
tweeningParameters['time'] = 0.000001;
|
||||
tweeningParameters['delay'] = 0.000001;
|
||||
}
|
||||
|
@@ -7,6 +7,7 @@ const Gdm = imports.gi.Gdm;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const GnomeDesktop = imports.gi.GnomeDesktop;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Signals = imports.signals;
|
||||
const Shell = imports.gi.Shell;
|
||||
|
@@ -7,7 +7,6 @@ const AccountsService = imports.gi.AccountsService;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GObject = imports.gi.GObject;
|
||||
const Pango = imports.gi.Pango;
|
||||
const St = imports.gi.St;
|
||||
|
||||
const Params = imports.misc.params;
|
||||
@@ -73,7 +72,6 @@ class UserWidgetLabel extends St.Widget {
|
||||
|
||||
this._realNameLabel = new St.Label({ style_class: 'user-widget-label',
|
||||
y_align: Clutter.ActorAlign.CENTER });
|
||||
this._realNameLabel.clutter_text.ellipsize = Pango.EllipsizeMode.END;
|
||||
this.add_child(this._realNameLabel);
|
||||
|
||||
this._userNameLabel = new St.Label({ style_class: 'user-widget-label',
|
||||
|
@@ -3,6 +3,7 @@
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Signals = imports.signals;
|
||||
@@ -33,8 +34,8 @@ var ViewPage = {
|
||||
var FocusTrap = GObject.registerClass(
|
||||
class FocusTrap extends St.Widget {
|
||||
vfunc_navigate_focus(from, direction) {
|
||||
if (direction == St.DirectionType.TAB_FORWARD ||
|
||||
direction == St.DirectionType.TAB_BACKWARD)
|
||||
if (direction == Gtk.DirectionType.TAB_FORWARD ||
|
||||
direction == Gtk.DirectionType.TAB_BACKWARD)
|
||||
return super.vfunc_navigate_focus(from, direction);
|
||||
return false;
|
||||
}
|
||||
@@ -81,7 +82,7 @@ var ShowOverviewAction = GObject.registerClass({
|
||||
});
|
||||
}
|
||||
|
||||
vfunc_gesture_prepare(actor) {
|
||||
vfunc_gesture_prepare(action, actor) {
|
||||
return Main.actionMode == Shell.ActionMode.NORMAL &&
|
||||
this.get_n_current_points() == this.get_n_touch_points();
|
||||
}
|
||||
@@ -115,12 +116,12 @@ var ShowOverviewAction = GObject.registerClass({
|
||||
height: maxY - minY });
|
||||
}
|
||||
|
||||
vfunc_gesture_begin(actor) {
|
||||
vfunc_gesture_begin(action, actor) {
|
||||
this._initialRect = this._getBoundingRect(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
vfunc_gesture_end(actor) {
|
||||
vfunc_gesture_end(action, actor) {
|
||||
let rect = this._getBoundingRect(true);
|
||||
let oldArea = this._initialRect.width * this._initialRect.height;
|
||||
let newArea = rect.width * rect.height;
|
||||
@@ -396,7 +397,7 @@ var ViewSelector = class {
|
||||
|
||||
_a11yFocusPage(page) {
|
||||
this._showAppsButton.checked = page == this._appsPage;
|
||||
page.navigate_focus(null, St.DirectionType.TAB_FORWARD, false);
|
||||
page.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
|
||||
}
|
||||
|
||||
_onShowAppsButtonToggled() {
|
||||
@@ -425,10 +426,10 @@ var ViewSelector = class {
|
||||
this.startSearch(event);
|
||||
} else if (!this._searchActive && !global.stage.key_focus) {
|
||||
if (symbol == Clutter.Tab || symbol == Clutter.Down) {
|
||||
this._activePage.navigate_focus(null, St.DirectionType.TAB_FORWARD, false);
|
||||
this._activePage.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
|
||||
return Clutter.EVENT_STOP;
|
||||
} else if (symbol == Clutter.ISO_Left_Tab) {
|
||||
this._activePage.navigate_focus(null, St.DirectionType.TAB_BACKWARD, false);
|
||||
this._activePage.navigate_focus(null, Gtk.DirectionType.TAB_BACKWARD, false);
|
||||
return Clutter.EVENT_STOP;
|
||||
}
|
||||
}
|
||||
@@ -556,22 +557,22 @@ var ViewSelector = class {
|
||||
let arrowNext, nextDirection;
|
||||
if (entry.get_text_direction() == Clutter.TextDirection.RTL) {
|
||||
arrowNext = Clutter.Left;
|
||||
nextDirection = St.DirectionType.LEFT;
|
||||
nextDirection = Gtk.DirectionType.LEFT;
|
||||
} else {
|
||||
arrowNext = Clutter.Right;
|
||||
nextDirection = St.DirectionType.RIGHT;
|
||||
nextDirection = Gtk.DirectionType.RIGHT;
|
||||
}
|
||||
|
||||
if (symbol == Clutter.Tab) {
|
||||
this._searchResults.navigateFocus(St.DirectionType.TAB_FORWARD);
|
||||
this._searchResults.navigateFocus(Gtk.DirectionType.TAB_FORWARD);
|
||||
return Clutter.EVENT_STOP;
|
||||
} else if (symbol == Clutter.ISO_Left_Tab) {
|
||||
this._focusTrap.can_focus = false;
|
||||
this._searchResults.navigateFocus(St.DirectionType.TAB_BACKWARD);
|
||||
this._searchResults.navigateFocus(Gtk.DirectionType.TAB_BACKWARD);
|
||||
this._focusTrap.can_focus = true;
|
||||
return Clutter.EVENT_STOP;
|
||||
} else if (symbol == Clutter.Down) {
|
||||
this._searchResults.navigateFocus(St.DirectionType.DOWN);
|
||||
this._searchResults.navigateFocus(Gtk.DirectionType.DOWN);
|
||||
return Clutter.EVENT_STOP;
|
||||
} else if (symbol == arrowNext && this._text.position == -1) {
|
||||
this._searchResults.navigateFocus(nextDirection);
|
||||
|
@@ -12,7 +12,6 @@ const Shell = imports.gi.Shell;
|
||||
const Signals = imports.signals;
|
||||
|
||||
const AltTab = imports.ui.altTab;
|
||||
const AppFavorites = imports.ui.appFavorites;
|
||||
const Dialog = imports.ui.dialog;
|
||||
const WorkspaceSwitcherPopup = imports.ui.workspaceSwitcherPopup;
|
||||
const InhibitShortcutsDialog = imports.ui.inhibitShortcutsDialog;
|
||||
@@ -600,7 +599,7 @@ var AppSwitchAction = GObject.registerClass({
|
||||
});
|
||||
}
|
||||
|
||||
vfunc_gesture_prepare(actor) {
|
||||
vfunc_gesture_prepare(action, actor) {
|
||||
if (Main.actionMode != Shell.ActionMode.NORMAL) {
|
||||
this.cancel();
|
||||
return false;
|
||||
@@ -609,7 +608,7 @@ var AppSwitchAction = GObject.registerClass({
|
||||
return this.get_n_current_points() <= 4;
|
||||
}
|
||||
|
||||
vfunc_gesture_begin(actor) {
|
||||
vfunc_gesture_begin(action, actor) {
|
||||
// in milliseconds
|
||||
const LONG_PRESS_TIMEOUT = 250;
|
||||
|
||||
@@ -633,7 +632,7 @@ var AppSwitchAction = GObject.registerClass({
|
||||
return this.get_n_current_points() <= 4;
|
||||
}
|
||||
|
||||
vfunc_gesture_progress(actor) {
|
||||
vfunc_gesture_progress(action, actor) {
|
||||
const MOTION_THRESHOLD = 30;
|
||||
|
||||
if (this.get_n_current_points() == 3) {
|
||||
@@ -924,13 +923,6 @@ var WindowManager = class {
|
||||
Shell.ActionMode.ALL,
|
||||
this._toggleTweens.bind(this));
|
||||
|
||||
this.addKeybinding('open-application-menu',
|
||||
new Gio.Settings({ schema_id: SHELL_KEYBINDINGS_SCHEMA }),
|
||||
Meta.KeyBindingFlags.IGNORE_AUTOREPEAT,
|
||||
Shell.ActionMode.NORMAL |
|
||||
Shell.ActionMode.POPUP,
|
||||
this._toggleAppMenu.bind(this));
|
||||
|
||||
this.addKeybinding('toggle-message-tray',
|
||||
new Gio.Settings({ schema_id: SHELL_KEYBINDINGS_SCHEMA }),
|
||||
Meta.KeyBindingFlags.IGNORE_AUTOREPEAT,
|
||||
@@ -939,69 +931,6 @@ var WindowManager = class {
|
||||
Shell.ActionMode.POPUP,
|
||||
this._toggleCalendar.bind(this));
|
||||
|
||||
this.addKeybinding('switch-to-application-1',
|
||||
new Gio.Settings({ schema_id: SHELL_KEYBINDINGS_SCHEMA }),
|
||||
Meta.KeyBindingFlags.IGNORE_AUTOREPEAT,
|
||||
Shell.ActionMode.NORMAL |
|
||||
Shell.ActionMode.OVERVIEW,
|
||||
this._switchToApplication.bind(this));
|
||||
|
||||
this.addKeybinding('switch-to-application-2',
|
||||
new Gio.Settings({ schema_id: SHELL_KEYBINDINGS_SCHEMA }),
|
||||
Meta.KeyBindingFlags.IGNORE_AUTOREPEAT,
|
||||
Shell.ActionMode.NORMAL |
|
||||
Shell.ActionMode.OVERVIEW,
|
||||
this._switchToApplication.bind(this));
|
||||
|
||||
this.addKeybinding('switch-to-application-3',
|
||||
new Gio.Settings({ schema_id: SHELL_KEYBINDINGS_SCHEMA }),
|
||||
Meta.KeyBindingFlags.IGNORE_AUTOREPEAT,
|
||||
Shell.ActionMode.NORMAL |
|
||||
Shell.ActionMode.OVERVIEW,
|
||||
this._switchToApplication.bind(this));
|
||||
|
||||
this.addKeybinding('switch-to-application-4',
|
||||
new Gio.Settings({ schema_id: SHELL_KEYBINDINGS_SCHEMA }),
|
||||
Meta.KeyBindingFlags.IGNORE_AUTOREPEAT,
|
||||
Shell.ActionMode.NORMAL |
|
||||
Shell.ActionMode.OVERVIEW,
|
||||
this._switchToApplication.bind(this));
|
||||
|
||||
this.addKeybinding('switch-to-application-5',
|
||||
new Gio.Settings({ schema_id: SHELL_KEYBINDINGS_SCHEMA }),
|
||||
Meta.KeyBindingFlags.IGNORE_AUTOREPEAT,
|
||||
Shell.ActionMode.NORMAL |
|
||||
Shell.ActionMode.OVERVIEW,
|
||||
this._switchToApplication.bind(this));
|
||||
|
||||
this.addKeybinding('switch-to-application-6',
|
||||
new Gio.Settings({ schema_id: SHELL_KEYBINDINGS_SCHEMA }),
|
||||
Meta.KeyBindingFlags.IGNORE_AUTOREPEAT,
|
||||
Shell.ActionMode.NORMAL |
|
||||
Shell.ActionMode.OVERVIEW,
|
||||
this._switchToApplication.bind(this));
|
||||
|
||||
this.addKeybinding('switch-to-application-7',
|
||||
new Gio.Settings({ schema_id: SHELL_KEYBINDINGS_SCHEMA }),
|
||||
Meta.KeyBindingFlags.IGNORE_AUTOREPEAT,
|
||||
Shell.ActionMode.NORMAL |
|
||||
Shell.ActionMode.OVERVIEW,
|
||||
this._switchToApplication.bind(this));
|
||||
|
||||
this.addKeybinding('switch-to-application-8',
|
||||
new Gio.Settings({ schema_id: SHELL_KEYBINDINGS_SCHEMA }),
|
||||
Meta.KeyBindingFlags.IGNORE_AUTOREPEAT,
|
||||
Shell.ActionMode.NORMAL |
|
||||
Shell.ActionMode.OVERVIEW,
|
||||
this._switchToApplication.bind(this));
|
||||
|
||||
this.addKeybinding('switch-to-application-9',
|
||||
new Gio.Settings({ schema_id: SHELL_KEYBINDINGS_SCHEMA }),
|
||||
Meta.KeyBindingFlags.IGNORE_AUTOREPEAT,
|
||||
Shell.ActionMode.NORMAL |
|
||||
Shell.ActionMode.OVERVIEW,
|
||||
this._switchToApplication.bind(this));
|
||||
|
||||
global.display.connect('show-resize-popup', this._showResizePopup.bind(this));
|
||||
global.display.connect('show-pad-osd', this._showPadOsd.bind(this));
|
||||
global.display.connect('show-osd', (display, monitorIndex, iconName, label) => {
|
||||
@@ -1071,10 +1000,6 @@ var WindowManager = class {
|
||||
gesture.connect('activated', () => {
|
||||
Main.keyboard.show(Main.layoutManager.bottomIndex);
|
||||
});
|
||||
Main.layoutManager.connect('keyboard-visible-changed', (manager, visible) => {
|
||||
gesture.cancel();
|
||||
gesture.set_enabled(!visible);
|
||||
});
|
||||
global.stage.add_action(gesture);
|
||||
|
||||
gesture = new EdgeDragAction.EdgeDragAction(St.Side.TOP, mode);
|
||||
@@ -2080,18 +2005,6 @@ var WindowManager = class {
|
||||
Main.ctrlAltTabManager.popup(binding.is_reversed(), binding.get_name(), binding.get_mask());
|
||||
}
|
||||
|
||||
_switchToApplication(display, window, binding) {
|
||||
let [,,,target] = binding.get_name().split('-');
|
||||
let apps = AppFavorites.getAppFavorites().getFavorites();
|
||||
let app = apps[target - 1];
|
||||
if (app)
|
||||
app.activate();
|
||||
}
|
||||
|
||||
_toggleAppMenu(display, window, event, binding) {
|
||||
Main.panel.toggleAppMenu();
|
||||
}
|
||||
|
||||
_toggleCalendar(display, window, event, binding) {
|
||||
Main.panel.toggleCalendar();
|
||||
}
|
||||
|
@@ -1,5 +1,6 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*
|
||||
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Meta = imports.gi.Meta;
|
||||
const St = imports.gi.St;
|
||||
|
||||
@@ -202,7 +203,7 @@ var WindowMenuManager = class {
|
||||
this._sourceActor.show();
|
||||
|
||||
menu.open(BoxPointer.PopupAnimation.NONE);
|
||||
menu.actor.navigate_focus(null, St.DirectionType.TAB_FORWARD, false);
|
||||
menu.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
|
||||
menu.connect('open-state-changed', (menu_, isOpen) => {
|
||||
if (isOpen)
|
||||
return;
|
||||
|
@@ -1,6 +1,5 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Atk = imports.gi.Atk;
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const GLib = imports.gi.GLib;
|
||||
const GObject = imports.gi.GObject;
|
||||
@@ -8,8 +7,10 @@ const Mainloop = imports.mainloop;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Pango = imports.gi.Pango;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Signals = imports.signals;
|
||||
const St = imports.gi.St;
|
||||
const Atk = imports.gi.Atk;
|
||||
|
||||
const Signals = imports.signals;
|
||||
|
||||
const DND = imports.ui.dnd;
|
||||
const Main = imports.ui.main;
|
||||
@@ -21,10 +22,7 @@ var WINDOW_DND_SIZE = 256;
|
||||
|
||||
var WINDOW_CLONE_MAXIMUM_SCALE = 1.0;
|
||||
|
||||
var WINDOW_OVERLAY_IDLE_HIDE_TIMEOUT = 750;
|
||||
var WINDOW_OVERLAY_FADE_TIME = 0.1;
|
||||
|
||||
var WINDOW_REPOSITIONING_DELAY = 750;
|
||||
var CLOSE_BUTTON_FADE_TIME = 0.1;
|
||||
|
||||
var DRAGGING_WINDOW_OPACITY = 100;
|
||||
|
||||
@@ -291,7 +289,8 @@ var WindowClone = class {
|
||||
this.actor.layout_manager.boundingBox = rect;
|
||||
}
|
||||
|
||||
// Find the actor just below us, respecting reparenting done by DND code
|
||||
// Find the actor just below us, respecting reparenting done
|
||||
// by DND code
|
||||
getActualStackAbove() {
|
||||
if (this._stackAbove == null)
|
||||
return null;
|
||||
@@ -442,7 +441,7 @@ Signals.addSignalMethods(WindowClone.prototype);
|
||||
/**
|
||||
* @windowClone: Corresponding window clone
|
||||
* @parentActor: The actor which will be the parent of all overlay items
|
||||
* such as the close button and window caption
|
||||
* such as app icon and window caption
|
||||
*/
|
||||
var WindowOverlay = class {
|
||||
constructor(windowClone, parentActor) {
|
||||
@@ -452,15 +451,13 @@ var WindowOverlay = class {
|
||||
this._parentActor = parentActor;
|
||||
this._hidden = false;
|
||||
|
||||
this._idleHideOverlayId = 0;
|
||||
|
||||
this.borderSize = 0;
|
||||
this.border = new St.Bin({ style_class: 'window-clone-border' });
|
||||
|
||||
this.title = new St.Label({ style_class: 'window-caption',
|
||||
text: this._getCaption() });
|
||||
this.title.clutter_text.ellipsize = Pango.EllipsizeMode.END;
|
||||
windowClone.actor.label_actor = this.title;
|
||||
let title = new St.Label({ style_class: 'window-caption',
|
||||
text: this._getCaption() });
|
||||
title.clutter_text.ellipsize = Pango.EllipsizeMode.END;
|
||||
windowClone.actor.label_actor = title;
|
||||
|
||||
this._maxTitleWidth = -1;
|
||||
|
||||
@@ -469,18 +466,22 @@ var WindowOverlay = class {
|
||||
this.relayout(false);
|
||||
});
|
||||
|
||||
this.closeButton = new St.Button({ style_class: 'window-close' });
|
||||
this.closeButton.add_actor(new St.Icon({ icon_name: 'window-close-symbolic' }));
|
||||
this.closeButton._overlap = 0;
|
||||
let button = new St.Button({ style_class: 'window-close' });
|
||||
button.add_actor(new St.Icon({ icon_name: 'window-close-symbolic' }));
|
||||
button._overlap = 0;
|
||||
|
||||
this.closeButton.connect('clicked', () => this._windowClone.deleteAll());
|
||||
this._idleToggleCloseId = 0;
|
||||
button.connect('clicked', () => this._windowClone.deleteAll());
|
||||
|
||||
windowClone.actor.connect('destroy', this._onDestroy.bind(this));
|
||||
windowClone.connect('show-chrome', this._onShowChrome.bind(this));
|
||||
windowClone.connect('hide-chrome', this._onHideChrome.bind(this));
|
||||
|
||||
this.title.hide();
|
||||
this.closeButton.hide();
|
||||
button.hide();
|
||||
title.hide();
|
||||
|
||||
this.title = title;
|
||||
this.closeButton = button;
|
||||
|
||||
// Don't block drop targets
|
||||
Shell.util_set_hidden_from_pick(this.title, true);
|
||||
@@ -489,14 +490,12 @@ var WindowOverlay = class {
|
||||
parentActor.add_actor(this.border);
|
||||
parentActor.add_actor(this.title);
|
||||
parentActor.add_actor(this.closeButton);
|
||||
this.title.connect('style-changed',
|
||||
this._onStyleChanged.bind(this));
|
||||
this.closeButton.connect('style-changed',
|
||||
this._onStyleChanged.bind(this));
|
||||
this.border.connect('style-changed',
|
||||
this._onStyleChanged.bind(this));
|
||||
|
||||
// Force a style change if we are already on a stage - otherwise
|
||||
title.connect('style-changed',
|
||||
this._onStyleChanged.bind(this));
|
||||
button.connect('style-changed',
|
||||
this._onStyleChanged.bind(this));
|
||||
this.border.connect('style-changed', this._onStyleChanged.bind(this));
|
||||
// force a style change if we are already on a stage - otherwise
|
||||
// the signal will be emitted normally when we are added
|
||||
if (parentActor.get_stage())
|
||||
this._onStyleChanged();
|
||||
@@ -505,7 +504,7 @@ var WindowOverlay = class {
|
||||
hide() {
|
||||
this._hidden = true;
|
||||
|
||||
this.hideOverlay();
|
||||
this.hideCloseButton();
|
||||
}
|
||||
|
||||
show() {
|
||||
@@ -624,9 +623,9 @@ var WindowOverlay = class {
|
||||
}
|
||||
|
||||
_onDestroy() {
|
||||
if (this._idleHideOverlayId > 0) {
|
||||
Mainloop.source_remove(this._idleHideOverlayId);
|
||||
this._idleHideOverlayId = 0;
|
||||
if (this._idleToggleCloseId > 0) {
|
||||
Mainloop.source_remove(this._idleToggleCloseId);
|
||||
this._idleToggleCloseId = 0;
|
||||
}
|
||||
this._windowClone.metaWindow.disconnect(this._updateCaptionId);
|
||||
this.title.destroy();
|
||||
@@ -646,7 +645,7 @@ var WindowOverlay = class {
|
||||
a.opacity = 0;
|
||||
Tweener.addTween(a,
|
||||
{ opacity: 255,
|
||||
time: WINDOW_OVERLAY_FADE_TIME,
|
||||
time: CLOSE_BUTTON_FADE_TIME,
|
||||
transition: 'easeOutQuad' });
|
||||
});
|
||||
}
|
||||
@@ -656,7 +655,7 @@ var WindowOverlay = class {
|
||||
a.opacity = 255;
|
||||
Tweener.addTween(a,
|
||||
{ opacity: 0,
|
||||
time: WINDOW_OVERLAY_FADE_TIME,
|
||||
time: CLOSE_BUTTON_FADE_TIME,
|
||||
transition: 'easeInQuad' });
|
||||
});
|
||||
}
|
||||
@@ -670,18 +669,18 @@ var WindowOverlay = class {
|
||||
return;
|
||||
|
||||
this._animateVisible();
|
||||
this.emit('chrome-visible');
|
||||
this.emit('show-close-button');
|
||||
}
|
||||
|
||||
_onHideChrome() {
|
||||
if (this._idleHideOverlayId == 0) {
|
||||
this._idleHideOverlayId = Mainloop.timeout_add(WINDOW_OVERLAY_IDLE_HIDE_TIMEOUT, this._idleHideOverlay.bind(this));
|
||||
GLib.Source.set_name_by_id(this._idleHideOverlayId, '[gnome-shell] this._idleHideOverlay');
|
||||
if (this._idleToggleCloseId == 0) {
|
||||
this._idleToggleCloseId = Mainloop.timeout_add(750, this._idleToggleCloseButton.bind(this));
|
||||
GLib.Source.set_name_by_id(this._idleToggleCloseId, '[gnome-shell] this._idleToggleCloseButton');
|
||||
}
|
||||
}
|
||||
|
||||
_idleHideOverlay() {
|
||||
this._idleHideOverlayId = 0;
|
||||
_idleToggleCloseButton() {
|
||||
this._idleToggleCloseId = 0;
|
||||
|
||||
if (!this._windowClone.actor['has-pointer'] &&
|
||||
!this.closeButton['has-pointer'])
|
||||
@@ -690,10 +689,10 @@ var WindowOverlay = class {
|
||||
return GLib.SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
hideOverlay() {
|
||||
if (this._idleHideOverlayId > 0) {
|
||||
Mainloop.source_remove(this._idleHideOverlayId);
|
||||
this._idleHideOverlayId = 0;
|
||||
hideCloseButton() {
|
||||
if (this._idleToggleCloseId > 0) {
|
||||
Mainloop.source_remove(this._idleToggleCloseId);
|
||||
this._idleToggleCloseId = 0;
|
||||
}
|
||||
this.closeButton.hide();
|
||||
this.border.hide();
|
||||
@@ -1135,8 +1134,9 @@ var Workspace = class {
|
||||
this._windows = [];
|
||||
this._windowOverlays = [];
|
||||
for (let i = 0; i < windows.length; i++) {
|
||||
if (this._isOverviewWindow(windows[i]))
|
||||
if (this._isOverviewWindow(windows[i])) {
|
||||
this._addWindowClone(windows[i], true);
|
||||
}
|
||||
}
|
||||
|
||||
// Track window changes
|
||||
@@ -1206,7 +1206,12 @@ var Workspace = class {
|
||||
}
|
||||
|
||||
_lookupIndex(metaWindow) {
|
||||
return this._windows.findIndex(w => w.metaWindow == metaWindow);
|
||||
for (let i = 0; i < this._windows.length; i++) {
|
||||
if (this._windows[i].metaWindow == metaWindow) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
containsMetaWindow(metaWindow) {
|
||||
@@ -1297,7 +1302,8 @@ var Workspace = class {
|
||||
for (let i = 0; i < slots.length; i++) {
|
||||
let slot = slots[i];
|
||||
let [x, y, scale, clone] = slot;
|
||||
|
||||
let metaWindow = clone.metaWindow;
|
||||
let overlay = clone.overlay;
|
||||
clone.slotId = i;
|
||||
|
||||
// Positioning a window currently being dragged must be avoided;
|
||||
@@ -1313,10 +1319,10 @@ var Workspace = class {
|
||||
let maxChromeWidth = 2 * Math.min(
|
||||
cloneCenter - area.x,
|
||||
area.x + area.width - cloneCenter);
|
||||
clone.overlay.setMaxChromeWidth(Math.round(maxChromeWidth));
|
||||
overlay.setMaxChromeWidth(Math.round(maxChromeWidth));
|
||||
|
||||
if (clone.overlay && (initialPositioning || !clone.positioned))
|
||||
clone.overlay.hide();
|
||||
if (overlay && (initialPositioning || !clone.positioned))
|
||||
overlay.hide();
|
||||
|
||||
if (!clone.positioned) {
|
||||
// This window appeared after the overview was already up
|
||||
@@ -1329,7 +1335,7 @@ var Workspace = class {
|
||||
}
|
||||
|
||||
if (animate && isOnCurrentWorkspace) {
|
||||
if (!clone.metaWindow.showing_on_its_workspace()) {
|
||||
if (!metaWindow.showing_on_its_workspace()) {
|
||||
/* Hidden windows should fade in and grow
|
||||
* therefore we need to resize them now so they
|
||||
* can be scaled up later */
|
||||
@@ -1348,7 +1354,7 @@ var Workspace = class {
|
||||
});
|
||||
}
|
||||
|
||||
this._animateClone(clone, clone.overlay, x, y, scale);
|
||||
this._animateClone(clone, overlay, x, y, scale);
|
||||
} else {
|
||||
// cancel any active tweens (otherwise they might override our changes)
|
||||
Tweener.removeTweens(clone.actor);
|
||||
@@ -1356,7 +1362,7 @@ var Workspace = class {
|
||||
clone.actor.set_scale(scale, scale);
|
||||
clone.actor.set_opacity(255);
|
||||
clone.overlay.relayout(false);
|
||||
this._showWindowOverlay(clone, clone.overlay);
|
||||
this._showWindowOverlay(clone, overlay);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1471,7 +1477,7 @@ var Workspace = class {
|
||||
this._cursorY = y;
|
||||
|
||||
this._currentLayout = null;
|
||||
this._repositionWindowsId = Mainloop.timeout_add(WINDOW_REPOSITIONING_DELAY,
|
||||
this._repositionWindowsId = Mainloop.timeout_add(750,
|
||||
this._delayedWindowRepositioning.bind(this));
|
||||
GLib.Source.set_name_by_id(this._repositionWindowsId, '[gnome-shell] this._delayedWindowRepositioning');
|
||||
}
|
||||
@@ -1498,7 +1504,7 @@ var Workspace = class {
|
||||
|
||||
// We might have the window in our list already if it was on all workspaces and
|
||||
// now was moved to this workspace
|
||||
if (this._lookupIndex(metaWin) != -1)
|
||||
if (this._lookupIndex (metaWin) != -1)
|
||||
return;
|
||||
|
||||
if (!this._isMyWindow(win))
|
||||
@@ -1530,9 +1536,8 @@ var Workspace = class {
|
||||
|
||||
clone.slot = [x, y, clone.actor.width * scale, clone.actor.height * scale];
|
||||
clone.positioned = true;
|
||||
|
||||
clone.actor.set_position(x, y);
|
||||
clone.actor.set_scale(scale, scale);
|
||||
clone.actor.set_position (x, y);
|
||||
clone.actor.set_scale (scale, scale);
|
||||
clone.overlay.relayout(false);
|
||||
}
|
||||
|
||||
@@ -1850,15 +1855,11 @@ var Workspace = class {
|
||||
|
||||
this.actor.add_actor(clone.actor);
|
||||
|
||||
overlay.connect('chrome-visible', () => {
|
||||
overlay.connect('show-close-button', () => {
|
||||
let focus = global.stage.key_focus;
|
||||
if (focus == null || this.actor.contains(focus))
|
||||
clone.actor.grab_key_focus();
|
||||
|
||||
this._windowOverlays.forEach(o => {
|
||||
if (o != overlay)
|
||||
o.hideOverlay();
|
||||
});
|
||||
this._onShowOverlayClose(overlay);
|
||||
});
|
||||
|
||||
if (this._windows.length == 0)
|
||||
@@ -1874,7 +1875,7 @@ var Workspace = class {
|
||||
|
||||
_removeWindowClone(metaWin) {
|
||||
// find the position of the window in our list
|
||||
let index = this._lookupIndex(metaWin);
|
||||
let index = this._lookupIndex (metaWin);
|
||||
|
||||
if (index == -1)
|
||||
return null;
|
||||
@@ -1883,6 +1884,15 @@ var Workspace = class {
|
||||
return this._windows.splice(index, 1).pop();
|
||||
}
|
||||
|
||||
_onShowOverlayClose(windowOverlay) {
|
||||
for (let i = 0; i < this._windowOverlays.length; i++) {
|
||||
let overlay = this._windowOverlays[i];
|
||||
if (overlay == windowOverlay)
|
||||
continue;
|
||||
overlay.hideCloseButton();
|
||||
}
|
||||
}
|
||||
|
||||
_isBetterLayout(oldLayout, newLayout) {
|
||||
if (oldLayout.scale === undefined)
|
||||
return true;
|
||||
|
@@ -319,7 +319,12 @@ var WorkspaceThumbnail = class {
|
||||
}
|
||||
|
||||
_lookupIndex(metaWindow) {
|
||||
return this._windows.findIndex(w => w.metaWindow == metaWindow);
|
||||
for (let i = 0; i < this._windows.length; i++) {
|
||||
if (this._windows[i].metaWindow == metaWindow) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
syncStacking(stackIndices) {
|
||||
@@ -394,7 +399,7 @@ var WorkspaceThumbnail = class {
|
||||
|
||||
// We might have the window in our list already if it was on all workspaces and
|
||||
// now was moved to this workspace
|
||||
if (this._lookupIndex(metaWin) != -1)
|
||||
if (this._lookupIndex (metaWin) != -1)
|
||||
return;
|
||||
|
||||
if (!this._isMyWindow(win))
|
||||
@@ -407,7 +412,7 @@ var WorkspaceThumbnail = class {
|
||||
while (parent.is_attached_dialog())
|
||||
parent = parent.get_transient_for();
|
||||
|
||||
let idx = this._lookupIndex(parent);
|
||||
let idx = this._lookupIndex (parent);
|
||||
if (idx < 0) {
|
||||
// parent was not created yet, it will take care
|
||||
// of the dialog when created
|
||||
@@ -531,7 +536,7 @@ var WorkspaceThumbnail = class {
|
||||
|
||||
_removeWindowClone(metaWin) {
|
||||
// find the position of the window in our list
|
||||
let index = this._lookupIndex(metaWin);
|
||||
let index = this._lookupIndex (metaWin);
|
||||
|
||||
if (index == -1)
|
||||
return null;
|
||||
@@ -619,10 +624,6 @@ class ThumbnailsBox extends St.Widget {
|
||||
this._indicator = indicator;
|
||||
this.add_actor(indicator);
|
||||
|
||||
// The porthole is the part of the screen we're showing in the thumbnails
|
||||
this._porthole = { width: global.stage.width, height: global.stage.height,
|
||||
x: global.stage.x, y: global.stage.y };
|
||||
|
||||
this._dropWorkspace = -1;
|
||||
this._dropPlaceholderPos = -1;
|
||||
this._dropPlaceholder = new St.Bin({ style_class: 'placeholder' });
|
||||
@@ -674,9 +675,6 @@ class ThumbnailsBox extends St.Widget {
|
||||
this._createThumbnails();
|
||||
});
|
||||
|
||||
global.display.connect('workareas-changed',
|
||||
this._updatePorthole.bind(this));
|
||||
|
||||
this._switchWorkspaceNotifyId = 0;
|
||||
this._nWorkspacesNotifyId = 0;
|
||||
this._syncStackingId = 0;
|
||||
@@ -914,6 +912,7 @@ class ThumbnailsBox extends St.Widget {
|
||||
for (let w = 0; w < this._thumbnails.length; w++)
|
||||
this._thumbnails[w].destroy();
|
||||
this._thumbnails = [];
|
||||
this._porthole = null;
|
||||
}
|
||||
|
||||
_workspacesChanged() {
|
||||
@@ -946,6 +945,8 @@ class ThumbnailsBox extends St.Widget {
|
||||
addThumbnails(start, count) {
|
||||
let workspaceManager = global.workspace_manager;
|
||||
|
||||
if (!this._ensurePorthole())
|
||||
return;
|
||||
for (let k = start; k < start + count; k++) {
|
||||
let metaWorkspace = workspaceManager.get_workspace_by_index(k);
|
||||
let thumbnail = new WorkspaceThumbnail(metaWorkspace);
|
||||
@@ -1125,6 +1126,10 @@ class ThumbnailsBox extends St.Widget {
|
||||
// Note that for getPreferredWidth/Height we cheat a bit and skip propagating
|
||||
// the size request to our children because we know how big they are and know
|
||||
// that the actors aren't depending on the virtual functions being called.
|
||||
|
||||
if (!this._ensurePorthole())
|
||||
return [0, 0];
|
||||
|
||||
let workspaceManager = global.workspace_manager;
|
||||
let themeNode = this.get_theme_node();
|
||||
|
||||
@@ -1138,6 +1143,9 @@ class ThumbnailsBox extends St.Widget {
|
||||
}
|
||||
|
||||
vfunc_get_preferred_width(forHeight) {
|
||||
if (!this._ensurePorthole())
|
||||
return [0, 0];
|
||||
|
||||
let workspaceManager = global.workspace_manager;
|
||||
let themeNode = this.get_theme_node();
|
||||
|
||||
@@ -1157,14 +1165,16 @@ class ThumbnailsBox extends St.Widget {
|
||||
return themeNode.adjust_preferred_width(width, width);
|
||||
}
|
||||
|
||||
_updatePorthole() {
|
||||
if (!Main.layoutManager.primaryMonitor)
|
||||
this._porthole = { width: global.stage.width, height: global.stage.height,
|
||||
x: global.stage.x, y: global.stage.y };
|
||||
else
|
||||
// The "porthole" is the portion of the screen that we show in the
|
||||
// workspaces
|
||||
_ensurePorthole() {
|
||||
if (!Main.layoutManager.primaryMonitor || !Main.overview.visible)
|
||||
return false;
|
||||
|
||||
if (!this._porthole)
|
||||
this._porthole = Main.layoutManager.getWorkAreaForMonitor(Main.layoutManager.primaryIndex);
|
||||
|
||||
this.queue_relayout();
|
||||
return true;
|
||||
}
|
||||
|
||||
vfunc_allocate(box, flags) {
|
||||
|
@@ -1,5 +1,5 @@
|
||||
project('gnome-shell', 'c',
|
||||
version: '3.31.90',
|
||||
version: '3.31.4',
|
||||
meson_version: '>= 0.47.0',
|
||||
license: 'GPLv2+'
|
||||
)
|
||||
@@ -23,7 +23,7 @@ gi_req = '>= 1.49.1'
|
||||
gjs_req = '>= 1.47.0'
|
||||
gtk_req = '>= 3.15.0'
|
||||
json_glib_req = '>= 0.13.2'
|
||||
mutter_req = '>= 3.31.90'
|
||||
mutter_req = '>= 3.31.4'
|
||||
polkit_req = '>= 0.100'
|
||||
schemas_req = '>= 3.27.90'
|
||||
startup_req = '>= 0.11'
|
||||
|
@@ -11,6 +11,8 @@
|
||||
#include <cogl-pango/cogl-pango.h>
|
||||
#include <clutter/clutter.h>
|
||||
#include <clutter/x11/clutter-x11.h>
|
||||
#include <gdk/gdk.h>
|
||||
#include <gdk/gdkx.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <glib/gi18n-lib.h>
|
||||
#include <girepository.h>
|
||||
|
@@ -50,7 +50,6 @@ struct _ShellAppSystemPrivate {
|
||||
GHashTable *running_apps;
|
||||
GHashTable *id_to_app;
|
||||
GHashTable *startup_wm_class_to_id;
|
||||
GList *installed_apps;
|
||||
};
|
||||
|
||||
static void shell_app_system_finalize (GObject *object);
|
||||
@@ -83,14 +82,12 @@ static void
|
||||
scan_startup_wm_class_to_id (ShellAppSystem *self)
|
||||
{
|
||||
ShellAppSystemPrivate *priv = self->priv;
|
||||
GList *l;
|
||||
GList *apps, *l;
|
||||
|
||||
g_hash_table_remove_all (priv->startup_wm_class_to_id);
|
||||
|
||||
g_list_free_full (priv->installed_apps, g_object_unref);
|
||||
priv->installed_apps = g_app_info_get_all ();
|
||||
|
||||
for (l = priv->installed_apps; l != NULL; l = l->next)
|
||||
apps = g_app_info_get_all ();
|
||||
for (l = apps; l != NULL; l = l->next)
|
||||
{
|
||||
GAppInfo *info = l->data;
|
||||
const char *startup_wm_class, *id, *old_id;
|
||||
@@ -108,6 +105,8 @@ scan_startup_wm_class_to_id (ShellAppSystem *self)
|
||||
g_hash_table_insert (priv->startup_wm_class_to_id,
|
||||
g_strdup (startup_wm_class), g_strdup (id));
|
||||
}
|
||||
|
||||
g_list_free_full (apps, g_object_unref);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -199,7 +198,6 @@ shell_app_system_finalize (GObject *object)
|
||||
g_hash_table_destroy (priv->running_apps);
|
||||
g_hash_table_destroy (priv->id_to_app);
|
||||
g_hash_table_destroy (priv->startup_wm_class_to_id);
|
||||
g_list_free_full (priv->installed_apps, g_object_unref);
|
||||
|
||||
G_OBJECT_CLASS (shell_app_system_parent_class)->finalize (object);
|
||||
}
|
||||
@@ -438,21 +436,3 @@ shell_app_system_search (const char *search_string)
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* shell_app_system_get_installed:
|
||||
* @self: the #ShellAppSystem
|
||||
*
|
||||
* Returns all installed apps, as a list of #GAppInfo
|
||||
*
|
||||
* Returns: (transfer none) (element-type GAppInfo): a list of #GAppInfo
|
||||
* describing all known applications. This memory is owned by the
|
||||
* #ShellAppSystem and should not be freed.
|
||||
**/
|
||||
GList *
|
||||
shell_app_system_get_installed (ShellAppSystem *self)
|
||||
{
|
||||
ShellAppSystemPrivate *priv = self->priv;
|
||||
|
||||
return priv->installed_apps;
|
||||
}
|
||||
|
@@ -27,6 +27,4 @@ ShellApp *shell_app_system_lookup_desktop_wmclass (ShellAppSystem *s
|
||||
GSList *shell_app_system_get_running (ShellAppSystem *self);
|
||||
char ***shell_app_system_search (const char *search_string);
|
||||
|
||||
GList *shell_app_system_get_installed (ShellAppSystem *self);
|
||||
|
||||
#endif /* __SHELL_APP_SYSTEM_H__ */
|
||||
|
@@ -26,6 +26,12 @@
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
MATCH_NONE,
|
||||
MATCH_SUBSTRING, /* Not prefix, substring */
|
||||
MATCH_PREFIX, /* Strict prefix */
|
||||
} ShellAppSearchMatch;
|
||||
|
||||
/* This is mainly a memory usage optimization - the user is going to
|
||||
* be running far fewer of the applications at one time than they have
|
||||
* installed. But it also just helps keep the code more logically
|
||||
@@ -204,7 +210,7 @@ window_backed_app_get_icon (ShellApp *app,
|
||||
|
||||
if (window == NULL)
|
||||
{
|
||||
actor = clutter_actor_new ();
|
||||
actor = clutter_texture_new ();
|
||||
g_object_set (actor, "opacity", 0, "width", (float) size, "height", (float) size, NULL);
|
||||
return actor;
|
||||
}
|
||||
@@ -631,7 +637,7 @@ shell_app_can_open_new_window (ShellApp *app)
|
||||
new window.
|
||||
*/
|
||||
|
||||
window = state->windows->data;
|
||||
window = g_slist_nth_data (state->windows, 0);
|
||||
|
||||
if (state->unique_bus_name != NULL &&
|
||||
meta_window_get_gtk_application_object_path (window) != NULL)
|
||||
|
@@ -85,8 +85,6 @@ struct _ShellGlobal {
|
||||
GSList *leisure_closures;
|
||||
guint leisure_function_id;
|
||||
|
||||
GHashTable *save_ops;
|
||||
|
||||
gboolean has_modal;
|
||||
gboolean frame_timestamps;
|
||||
gboolean frame_finish_timestamp;
|
||||
@@ -313,10 +311,6 @@ shell_global_init (ShellGlobal *global)
|
||||
NULL);
|
||||
|
||||
g_strfreev (search_path);
|
||||
|
||||
global->save_ops = g_hash_table_new_full (g_file_hash,
|
||||
(GEqualFunc) g_file_equal,
|
||||
g_object_unref, g_object_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -336,8 +330,6 @@ shell_global_finalize (GObject *object)
|
||||
g_free (global->imagedir);
|
||||
g_free (global->userdatadir);
|
||||
|
||||
g_hash_table_unref (global->save_ops);
|
||||
|
||||
G_OBJECT_CLASS(shell_global_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
@@ -1382,26 +1374,24 @@ shell_global_create_app_launch_context (ShellGlobal *global,
|
||||
guint32 timestamp,
|
||||
int workspace)
|
||||
{
|
||||
MetaWorkspaceManager *workspace_manager = global->workspace_manager;
|
||||
MetaStartupNotification *sn;
|
||||
MetaLaunchContext *context;
|
||||
MetaWorkspace *ws = NULL;
|
||||
GdkAppLaunchContext *context;
|
||||
|
||||
sn = meta_display_get_startup_notification (global->meta_display);
|
||||
context = meta_startup_notification_create_launcher (sn);
|
||||
context = gdk_display_get_app_launch_context (global->gdk_display);
|
||||
|
||||
if (timestamp == 0)
|
||||
timestamp = shell_global_get_current_time (global);
|
||||
meta_launch_context_set_timestamp (context, timestamp);
|
||||
gdk_app_launch_context_set_timestamp (context, timestamp);
|
||||
|
||||
if (workspace < 0)
|
||||
ws = meta_workspace_manager_get_active_workspace (workspace_manager);
|
||||
else
|
||||
ws = meta_workspace_manager_get_workspace_by_index (workspace_manager, workspace);
|
||||
{
|
||||
MetaWorkspaceManager *workspace_manager = global->workspace_manager;
|
||||
|
||||
meta_launch_context_set_workspace (context, ws);
|
||||
workspace =
|
||||
meta_workspace_manager_get_active_workspace_index (workspace_manager);
|
||||
}
|
||||
gdk_app_launch_context_set_desktop (context, workspace);
|
||||
|
||||
return (GAppLaunchContext *) context;
|
||||
return (GAppLaunchContext *)context;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
@@ -1551,77 +1541,20 @@ shell_global_get_session_mode (ShellGlobal *global)
|
||||
}
|
||||
|
||||
static void
|
||||
delete_variant_cb (GObject *object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
ShellGlobal *global = user_data;
|
||||
GError *error = NULL;
|
||||
|
||||
if (!g_file_delete_finish (G_FILE (object), result, &error))
|
||||
{
|
||||
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
{
|
||||
g_warning ("Could not delete runtime/persistent state file: %s\n",
|
||||
error->message);
|
||||
}
|
||||
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
g_hash_table_remove (global->save_ops, object);
|
||||
}
|
||||
|
||||
static void
|
||||
replace_variant_cb (GObject *object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
ShellGlobal *global = user_data;
|
||||
GError *error = NULL;
|
||||
|
||||
if (!g_file_replace_contents_finish (G_FILE (object), result, NULL, &error))
|
||||
{
|
||||
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
{
|
||||
g_warning ("Could not replace runtime/persistent state file: %s\n",
|
||||
error->message);
|
||||
}
|
||||
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
g_hash_table_remove (global->save_ops, object);
|
||||
}
|
||||
|
||||
static void
|
||||
save_variant (ShellGlobal *global,
|
||||
GFile *dir,
|
||||
const char *property_name,
|
||||
GVariant *variant)
|
||||
save_variant (GFile *dir,
|
||||
const char *property_name,
|
||||
GVariant *variant)
|
||||
{
|
||||
GFile *path = g_file_get_child (dir, property_name);
|
||||
GCancellable *cancellable;
|
||||
|
||||
cancellable = g_hash_table_lookup (global->save_ops, path);
|
||||
g_cancellable_cancel (cancellable);
|
||||
|
||||
cancellable = g_cancellable_new ();
|
||||
g_hash_table_insert (global->save_ops, g_object_ref (path), cancellable);
|
||||
|
||||
if (variant == NULL || g_variant_get_data (variant) == NULL)
|
||||
{
|
||||
g_file_delete_async (path, G_PRIORITY_DEFAULT, cancellable,
|
||||
delete_variant_cb, global);
|
||||
}
|
||||
(void) g_file_delete (path, NULL, NULL);
|
||||
else
|
||||
{
|
||||
g_file_replace_contents_async (path,
|
||||
g_variant_get_data (variant),
|
||||
g_variant_get_size (variant),
|
||||
NULL, FALSE,
|
||||
G_FILE_CREATE_REPLACE_DESTINATION,
|
||||
cancellable, replace_variant_cb, global);
|
||||
gsize size = g_variant_get_size (variant);
|
||||
g_file_replace_contents (path, g_variant_get_data (variant), size,
|
||||
NULL, FALSE, G_FILE_CREATE_REPLACE_DESTINATION,
|
||||
NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
g_object_unref (path);
|
||||
@@ -1675,7 +1608,7 @@ shell_global_set_runtime_state (ShellGlobal *global,
|
||||
const char *property_name,
|
||||
GVariant *variant)
|
||||
{
|
||||
save_variant (global, global->runtime_state_path, property_name, variant);
|
||||
save_variant (global->runtime_state_path, property_name, variant);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1710,7 +1643,7 @@ shell_global_set_persistent_state (ShellGlobal *global,
|
||||
const char *property_name,
|
||||
GVariant *variant)
|
||||
{
|
||||
save_variant (global, global->userdatadir_path, property_name, variant);
|
||||
save_variant (global->userdatadir_path, property_name, variant);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -12,6 +12,7 @@
|
||||
#include <gst/gst.h>
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk/gdk.h>
|
||||
|
||||
#include <cogl/cogl.h>
|
||||
#include <meta/meta-cursor-tracker.h>
|
||||
@@ -51,6 +52,8 @@ struct _ShellRecorder {
|
||||
int stage_width;
|
||||
int stage_height;
|
||||
|
||||
GdkScreen *gdk_screen;
|
||||
|
||||
int pointer_x;
|
||||
int pointer_y;
|
||||
|
||||
@@ -207,6 +210,8 @@ shell_recorder_init (ShellRecorder *recorder)
|
||||
|
||||
shell_recorder_src_register ();
|
||||
|
||||
recorder->gdk_screen = gdk_screen_get_default ();
|
||||
|
||||
recorder->memory_target = get_memory_target();
|
||||
|
||||
recorder->a11y_settings = g_settings_new (A11Y_APPS_SCHEMA);
|
||||
|
@@ -146,7 +146,7 @@ shell_stack_get_preferred_width (ClutterActor *actor,
|
||||
static gboolean
|
||||
shell_stack_navigate_focus (StWidget *widget,
|
||||
ClutterActor *from,
|
||||
StDirectionType direction)
|
||||
GtkDirectionType direction)
|
||||
{
|
||||
ClutterActor *top_actor;
|
||||
|
||||
|
@@ -19,6 +19,7 @@
|
||||
#include <glib/gi18n-lib.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <gdk/gdkx.h>
|
||||
#include <meta/meta-shaped-texture.h>
|
||||
|
||||
#include <locale.h>
|
||||
@@ -234,21 +235,14 @@ shell_util_translate_time_string (const char *str)
|
||||
const char *locale = g_getenv ("LC_TIME");
|
||||
const char *res;
|
||||
char *sep;
|
||||
locale_t old_loc;
|
||||
locale_t loc = (locale_t) 0;
|
||||
|
||||
if (locale)
|
||||
loc = newlocale (LC_MESSAGES_MASK, locale, (locale_t) 0);
|
||||
|
||||
old_loc = uselocale (loc);
|
||||
setlocale (LC_MESSAGES, locale);
|
||||
|
||||
sep = strchr (str, '\004');
|
||||
res = g_dpgettext (NULL, str, sep ? sep - str + 1 : 0);
|
||||
|
||||
uselocale (old_loc);
|
||||
|
||||
if (loc != (locale_t) 0)
|
||||
freelocale (loc);
|
||||
setlocale (LC_MESSAGES, "");
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -373,6 +367,24 @@ shell_util_create_pixbuf_from_data (const guchar *data,
|
||||
(GdkPixbufDestroyNotify) g_free, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
shell_util_cursor_tracker_to_clutter (MetaCursorTracker *tracker,
|
||||
ClutterTexture *texture)
|
||||
{
|
||||
CoglTexture *sprite;
|
||||
|
||||
sprite = meta_cursor_tracker_get_sprite (tracker);
|
||||
if (sprite)
|
||||
{
|
||||
clutter_actor_show (CLUTTER_ACTOR (texture));
|
||||
clutter_texture_set_cogl_texture (texture, sprite);
|
||||
}
|
||||
else
|
||||
{
|
||||
clutter_actor_hide (CLUTTER_ACTOR (texture));
|
||||
}
|
||||
}
|
||||
|
||||
typedef const gchar *(*ShellGLGetString) (GLenum);
|
||||
|
||||
static const gchar *
|
||||
|
@@ -44,6 +44,9 @@ GdkPixbuf *shell_util_create_pixbuf_from_data (const guchar *data,
|
||||
int height,
|
||||
int rowstride);
|
||||
|
||||
void shell_util_cursor_tracker_to_clutter (MetaCursorTracker *tracker,
|
||||
ClutterTexture *texture);
|
||||
|
||||
gboolean shell_util_need_background_refresh (void);
|
||||
|
||||
ClutterContent * shell_util_get_content_for_window_actor (MetaWindowActor *window_actor,
|
||||
|
@@ -5,6 +5,10 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <gdk/gdk.h>
|
||||
#include <gdk/gdkx.h>
|
||||
#include <meta/display.h>
|
||||
#include <meta/group.h>
|
||||
#include <meta/util.h>
|
||||
|
@@ -17,7 +17,6 @@ st_headers = [
|
||||
'st-scrollable.h',
|
||||
'st-scroll-bar.h',
|
||||
'st-scroll-view.h',
|
||||
'st-settings.h',
|
||||
'st-shadow.h',
|
||||
'st-texture-cache.h',
|
||||
'st-theme.h',
|
||||
@@ -71,7 +70,6 @@ st_sources = [
|
||||
'st-scrollable.c',
|
||||
'st-scroll-bar.c',
|
||||
'st-scroll-view.c',
|
||||
'st-settings.c',
|
||||
'st-shadow.c',
|
||||
'st-texture-cache.c',
|
||||
'st-theme.c',
|
||||
|
@@ -200,7 +200,7 @@ st_bin_popup_menu (StWidget *widget)
|
||||
static gboolean
|
||||
st_bin_navigate_focus (StWidget *widget,
|
||||
ClutterActor *from,
|
||||
StDirectionType direction)
|
||||
GtkDirectionType direction)
|
||||
{
|
||||
StBinPrivate *priv = st_bin_get_instance_private (ST_BIN (widget));
|
||||
ClutterActor *bin_actor = CLUTTER_ACTOR (widget);
|
||||
|
@@ -241,8 +241,6 @@ st_button_touch_event (ClutterActor *actor,
|
||||
|
||||
if (priv->pressed != 0)
|
||||
return CLUTTER_EVENT_PROPAGATE;
|
||||
if ((priv->button_mask & mask) == 0)
|
||||
return CLUTTER_EVENT_PROPAGATE;
|
||||
|
||||
device = clutter_event_get_device ((ClutterEvent*) event);
|
||||
sequence = clutter_event_get_event_sequence ((ClutterEvent*) event);
|
||||
|
@@ -56,7 +56,6 @@
|
||||
|
||||
#include "st-icon.h"
|
||||
#include "st-label.h"
|
||||
#include "st-settings.h"
|
||||
#include "st-widget.h"
|
||||
#include "st-texture-cache.h"
|
||||
#include "st-clipboard.h"
|
||||
@@ -240,15 +239,15 @@ remove_capslock_feedback (StEntry *entry)
|
||||
}
|
||||
|
||||
static void
|
||||
keymap_state_changed (ClutterKeymap *keymap,
|
||||
gpointer user_data)
|
||||
keymap_state_changed (GdkKeymap *keymap,
|
||||
gpointer user_data)
|
||||
{
|
||||
StEntry *entry = ST_ENTRY (user_data);
|
||||
StEntryPrivate *priv = ST_ENTRY_PRIV (entry);
|
||||
|
||||
if (clutter_text_get_password_char (CLUTTER_TEXT (priv->entry)) != 0)
|
||||
{
|
||||
if (clutter_keymap_get_caps_lock_state (keymap))
|
||||
if (gdk_keymap_get_caps_lock_state (keymap))
|
||||
show_capslock_feedback (entry);
|
||||
else
|
||||
remove_capslock_feedback (entry);
|
||||
@@ -260,11 +259,11 @@ st_entry_dispose (GObject *object)
|
||||
{
|
||||
StEntry *entry = ST_ENTRY (object);
|
||||
StEntryPrivate *priv = ST_ENTRY_PRIV (entry);
|
||||
ClutterKeymap *keymap;
|
||||
GdkKeymap *keymap;
|
||||
|
||||
cogl_clear_object (&priv->text_shadow_material);
|
||||
|
||||
keymap = clutter_backend_get_keymap (clutter_get_default_backend ());
|
||||
keymap = gdk_keymap_get_for_display (gdk_display_get_default ());
|
||||
g_signal_handlers_disconnect_by_func (keymap, keymap_state_changed, entry);
|
||||
|
||||
G_OBJECT_CLASS (st_entry_parent_class)->dispose (object);
|
||||
@@ -331,7 +330,7 @@ st_entry_style_changed (StWidget *self)
|
||||
static gboolean
|
||||
st_entry_navigate_focus (StWidget *widget,
|
||||
ClutterActor *from,
|
||||
StDirectionType direction)
|
||||
GtkDirectionType direction)
|
||||
{
|
||||
StEntryPrivate *priv = ST_ENTRY_PRIV (widget);
|
||||
|
||||
@@ -564,11 +563,11 @@ clutter_text_focus_in_cb (ClutterText *text,
|
||||
ClutterActor *actor)
|
||||
{
|
||||
StEntry *entry = ST_ENTRY (actor);
|
||||
ClutterKeymap *keymap;
|
||||
GdkKeymap *keymap;
|
||||
|
||||
st_entry_update_hint_visibility (entry);
|
||||
|
||||
keymap = clutter_backend_get_keymap (clutter_get_default_backend ());
|
||||
keymap = gdk_keymap_get_for_display (gdk_display_get_default ());
|
||||
keymap_state_changed (keymap, entry);
|
||||
g_signal_connect (keymap, "state-changed",
|
||||
G_CALLBACK (keymap_state_changed), entry);
|
||||
@@ -582,7 +581,7 @@ clutter_text_focus_out_cb (ClutterText *text,
|
||||
ClutterActor *actor)
|
||||
{
|
||||
StEntry *entry = ST_ENTRY (actor);
|
||||
ClutterKeymap *keymap;
|
||||
GdkKeymap *keymap;
|
||||
|
||||
st_widget_remove_style_pseudo_class (ST_WIDGET (actor), "focus");
|
||||
|
||||
@@ -591,7 +590,7 @@ clutter_text_focus_out_cb (ClutterText *text,
|
||||
clutter_text_set_cursor_visible (text, FALSE);
|
||||
remove_capslock_feedback (entry);
|
||||
|
||||
keymap = clutter_backend_get_keymap (clutter_get_default_backend ());
|
||||
keymap = gdk_keymap_get_for_display (gdk_display_get_default ());
|
||||
g_signal_handlers_disconnect_by_func (keymap, keymap_state_changed, entry);
|
||||
}
|
||||
|
||||
@@ -645,32 +644,29 @@ clutter_text_button_press_event (ClutterActor *actor,
|
||||
gpointer user_data)
|
||||
{
|
||||
StEntryPrivate *priv = ST_ENTRY_PRIV (user_data);
|
||||
GtkSettings *settings = gtk_settings_get_default ();
|
||||
gboolean primary_paste_enabled;
|
||||
|
||||
if (event->button == 2 &&
|
||||
clutter_text_get_editable (CLUTTER_TEXT (priv->entry)))
|
||||
g_object_get (settings,
|
||||
"gtk-enable-primary-paste", &primary_paste_enabled,
|
||||
NULL);
|
||||
|
||||
if (primary_paste_enabled && event->button == 2
|
||||
&& clutter_text_get_editable (CLUTTER_TEXT (priv->entry)))
|
||||
{
|
||||
StSettings *settings;
|
||||
gboolean primary_paste_enabled;
|
||||
StClipboard *clipboard;
|
||||
|
||||
settings = st_settings_get ();
|
||||
g_object_get (settings, "primary-paste", &primary_paste_enabled, NULL);
|
||||
clipboard = st_clipboard_get_default ();
|
||||
|
||||
if (primary_paste_enabled)
|
||||
{
|
||||
StClipboard *clipboard;
|
||||
|
||||
clipboard = st_clipboard_get_default ();
|
||||
|
||||
/* By the time the clipboard callback is called,
|
||||
* the rest of the signal handlers will have
|
||||
* run, making the text cursor to be in the correct
|
||||
* place.
|
||||
*/
|
||||
st_clipboard_get_text (clipboard,
|
||||
ST_CLIPBOARD_TYPE_PRIMARY,
|
||||
st_entry_clipboard_callback,
|
||||
user_data);
|
||||
}
|
||||
/* By the time the clipboard callback is called,
|
||||
* the rest of the signal handlers will have
|
||||
* run, making the text cursor to be in the correct
|
||||
* place.
|
||||
*/
|
||||
st_clipboard_get_text (clipboard,
|
||||
ST_CLIPBOARD_TYPE_PRIMARY,
|
||||
st_entry_clipboard_callback,
|
||||
user_data);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
@@ -873,7 +869,6 @@ st_entry_paint (ClutterActor *actor)
|
||||
|
||||
if (priv->text_shadow_material != NULL)
|
||||
_st_paint_shadow_with_opacity (shadow_spec,
|
||||
cogl_get_draw_framebuffer (),
|
||||
priv->text_shadow_material,
|
||||
&allocation,
|
||||
clutter_actor_get_paint_opacity (priv->entry));
|
||||
|
@@ -75,7 +75,7 @@ st_focus_manager_stage_event (ClutterActor *stage,
|
||||
gpointer user_data)
|
||||
{
|
||||
StFocusManager *manager = user_data;
|
||||
StDirectionType direction;
|
||||
GtkDirectionType direction;
|
||||
gboolean wrap_around = FALSE;
|
||||
ClutterActor *focused, *group;
|
||||
|
||||
@@ -85,26 +85,26 @@ st_focus_manager_stage_event (ClutterActor *stage,
|
||||
switch (event->key.keyval)
|
||||
{
|
||||
case CLUTTER_KEY_Up:
|
||||
direction = ST_DIR_UP;
|
||||
direction = GTK_DIR_UP;
|
||||
break;
|
||||
case CLUTTER_KEY_Down:
|
||||
direction = ST_DIR_DOWN;
|
||||
direction = GTK_DIR_DOWN;
|
||||
break;
|
||||
case CLUTTER_KEY_Left:
|
||||
direction = ST_DIR_LEFT;
|
||||
direction = GTK_DIR_LEFT;
|
||||
break;
|
||||
case CLUTTER_KEY_Right:
|
||||
direction = ST_DIR_RIGHT;
|
||||
direction = GTK_DIR_RIGHT;
|
||||
break;
|
||||
case CLUTTER_KEY_Tab:
|
||||
if (event->key.modifier_state & CLUTTER_SHIFT_MASK)
|
||||
direction = ST_DIR_TAB_BACKWARD;
|
||||
direction = GTK_DIR_TAB_BACKWARD;
|
||||
else
|
||||
direction = ST_DIR_TAB_FORWARD;
|
||||
direction = GTK_DIR_TAB_FORWARD;
|
||||
wrap_around = TRUE;
|
||||
break;
|
||||
case CLUTTER_KEY_ISO_Left_Tab:
|
||||
direction = ST_DIR_TAB_BACKWARD;
|
||||
direction = GTK_DIR_TAB_BACKWARD;
|
||||
wrap_around = TRUE;
|
||||
break;
|
||||
|
||||
|
@@ -176,7 +176,6 @@ st_icon_paint (ClutterActor *actor)
|
||||
|
||||
clutter_actor_get_allocation_box (priv->icon_texture, &allocation);
|
||||
_st_paint_shadow_with_opacity (priv->shadow_spec,
|
||||
cogl_get_draw_framebuffer (),
|
||||
priv->shadow_pipeline,
|
||||
&allocation,
|
||||
clutter_actor_get_paint_opacity (priv->icon_texture));
|
||||
|
@@ -216,7 +216,6 @@ st_label_paint (ClutterActor *actor)
|
||||
|
||||
if (priv->text_shadow_pipeline != NULL)
|
||||
_st_paint_shadow_with_opacity (shadow_spec,
|
||||
cogl_get_draw_framebuffer (),
|
||||
priv->text_shadow_pipeline,
|
||||
&allocation,
|
||||
clutter_actor_get_paint_opacity (priv->label));
|
||||
|
@@ -429,7 +429,6 @@ CoglPipeline *
|
||||
_st_create_shadow_pipeline_from_actor (StShadow *shadow_spec,
|
||||
ClutterActor *actor)
|
||||
{
|
||||
ClutterContent *image = NULL;
|
||||
CoglPipeline *shadow_pipeline = NULL;
|
||||
float width, height;
|
||||
|
||||
@@ -440,12 +439,11 @@ _st_create_shadow_pipeline_from_actor (StShadow *shadow_spec,
|
||||
if (width == 0 || height == 0)
|
||||
return NULL;
|
||||
|
||||
image = clutter_actor_get_content (actor);
|
||||
if (image && CLUTTER_IS_IMAGE (image))
|
||||
if (CLUTTER_IS_TEXTURE (actor))
|
||||
{
|
||||
CoglTexture *texture;
|
||||
|
||||
texture = clutter_image_get_texture (CLUTTER_IMAGE (image));
|
||||
texture = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (actor));
|
||||
if (texture &&
|
||||
cogl_texture_get_width (texture) == width &&
|
||||
cogl_texture_get_height (texture) == height)
|
||||
@@ -660,11 +658,11 @@ _st_create_shadow_cairo_pattern (StShadow *shadow_spec,
|
||||
|
||||
void
|
||||
_st_paint_shadow_with_opacity (StShadow *shadow_spec,
|
||||
CoglFramebuffer *framebuffer,
|
||||
CoglPipeline *shadow_pipeline,
|
||||
ClutterActorBox *box,
|
||||
guint8 paint_opacity)
|
||||
{
|
||||
CoglFramebuffer *fb = cogl_get_draw_framebuffer ();
|
||||
ClutterActorBox shadow_box;
|
||||
CoglColor color;
|
||||
|
||||
@@ -680,8 +678,7 @@ _st_paint_shadow_with_opacity (StShadow *shadow_spec,
|
||||
shadow_spec->color.alpha * paint_opacity / 255);
|
||||
cogl_color_premultiply (&color);
|
||||
cogl_pipeline_set_layer_combine_constant (shadow_pipeline, 0, &color);
|
||||
cogl_framebuffer_draw_rectangle (framebuffer,
|
||||
shadow_pipeline,
|
||||
cogl_framebuffer_draw_rectangle (fb, shadow_pipeline,
|
||||
shadow_box.x1, shadow_box.y1,
|
||||
shadow_box.x2, shadow_box.y2);
|
||||
}
|
||||
|
@@ -70,7 +70,6 @@ cairo_pattern_t *_st_create_shadow_cairo_pattern (StShadow *shadow_spec,
|
||||
cairo_pattern_t *src_pattern);
|
||||
|
||||
void _st_paint_shadow_with_opacity (StShadow *shadow_spec,
|
||||
CoglFramebuffer *framebuffer,
|
||||
CoglPipeline *shadow_pipeline,
|
||||
ClutterActorBox *box,
|
||||
guint8 paint_opacity);
|
||||
|
@@ -58,7 +58,6 @@
|
||||
* detailed description of the considerations involved.
|
||||
*/
|
||||
|
||||
#include "st-enum-types.h"
|
||||
#include "st-scroll-view.h"
|
||||
#include "st-scroll-bar.h"
|
||||
#include "st-scrollable.h"
|
||||
@@ -83,8 +82,8 @@ struct _StScrollViewPrivate
|
||||
StAdjustment *vadjustment;
|
||||
ClutterActor *vscroll;
|
||||
|
||||
StPolicyType hscrollbar_policy;
|
||||
StPolicyType vscrollbar_policy;
|
||||
GtkPolicyType hscrollbar_policy;
|
||||
GtkPolicyType vscrollbar_policy;
|
||||
|
||||
gfloat row_size;
|
||||
gfloat column_size;
|
||||
@@ -373,12 +372,12 @@ st_scroll_view_get_preferred_width (ClutterActor *actor,
|
||||
|
||||
switch (priv->hscrollbar_policy)
|
||||
{
|
||||
case ST_POLICY_NEVER:
|
||||
case GTK_POLICY_NEVER:
|
||||
min_width = child_min_width;
|
||||
break;
|
||||
case ST_POLICY_ALWAYS:
|
||||
case ST_POLICY_AUTOMATIC:
|
||||
case ST_POLICY_EXTERNAL:
|
||||
case GTK_POLICY_ALWAYS:
|
||||
case GTK_POLICY_AUTOMATIC:
|
||||
case GTK_POLICY_EXTERNAL:
|
||||
/* Should theoretically use the min width of the hscrollbar,
|
||||
* but that's not cleanly defined at the moment */
|
||||
min_width = 0;
|
||||
@@ -390,14 +389,14 @@ st_scroll_view_get_preferred_width (ClutterActor *actor,
|
||||
|
||||
switch (priv->vscrollbar_policy)
|
||||
{
|
||||
case ST_POLICY_NEVER:
|
||||
case ST_POLICY_EXTERNAL:
|
||||
case GTK_POLICY_NEVER:
|
||||
case GTK_POLICY_EXTERNAL:
|
||||
account_for_vscrollbar = FALSE;
|
||||
break;
|
||||
case ST_POLICY_ALWAYS:
|
||||
case GTK_POLICY_ALWAYS:
|
||||
account_for_vscrollbar = !priv->overlay_scrollbars;
|
||||
break;
|
||||
case ST_POLICY_AUTOMATIC:
|
||||
case GTK_POLICY_AUTOMATIC:
|
||||
/* For automatic scrollbars, we always request space for the vertical
|
||||
* scrollbar; we won't know whether we actually need one until our
|
||||
* height is assigned in allocate().
|
||||
@@ -455,11 +454,11 @@ st_scroll_view_get_preferred_height (ClutterActor *actor,
|
||||
|
||||
switch (priv->vscrollbar_policy)
|
||||
{
|
||||
case ST_POLICY_NEVER:
|
||||
case ST_POLICY_EXTERNAL:
|
||||
case GTK_POLICY_NEVER:
|
||||
case GTK_POLICY_EXTERNAL:
|
||||
break;
|
||||
case ST_POLICY_ALWAYS:
|
||||
case ST_POLICY_AUTOMATIC:
|
||||
case GTK_POLICY_ALWAYS:
|
||||
case GTK_POLICY_AUTOMATIC:
|
||||
/* We've requested space for the scrollbar, subtract it back out */
|
||||
for_width -= sb_width;
|
||||
break;
|
||||
@@ -470,14 +469,14 @@ st_scroll_view_get_preferred_height (ClutterActor *actor,
|
||||
|
||||
switch (priv->hscrollbar_policy)
|
||||
{
|
||||
case ST_POLICY_NEVER:
|
||||
case ST_POLICY_EXTERNAL:
|
||||
case GTK_POLICY_NEVER:
|
||||
case GTK_POLICY_EXTERNAL:
|
||||
account_for_hscrollbar = FALSE;
|
||||
break;
|
||||
case ST_POLICY_ALWAYS:
|
||||
case GTK_POLICY_ALWAYS:
|
||||
account_for_hscrollbar = !priv->overlay_scrollbars;
|
||||
break;
|
||||
case ST_POLICY_AUTOMATIC:
|
||||
case GTK_POLICY_AUTOMATIC:
|
||||
/* For automatic scrollbars, we always request space for the horizontal
|
||||
* scrollbar; we won't know whether we actually need one until our
|
||||
* width is assigned in allocate().
|
||||
@@ -496,12 +495,12 @@ st_scroll_view_get_preferred_height (ClutterActor *actor,
|
||||
|
||||
switch (priv->vscrollbar_policy)
|
||||
{
|
||||
case ST_POLICY_NEVER:
|
||||
case GTK_POLICY_NEVER:
|
||||
min_height = child_min_height;
|
||||
break;
|
||||
case ST_POLICY_ALWAYS:
|
||||
case ST_POLICY_AUTOMATIC:
|
||||
case ST_POLICY_EXTERNAL:
|
||||
case GTK_POLICY_ALWAYS:
|
||||
case GTK_POLICY_AUTOMATIC:
|
||||
case GTK_POLICY_EXTERNAL:
|
||||
/* Should theoretically use the min height of the vscrollbar,
|
||||
* but that's not cleanly defined at the moment */
|
||||
min_height = 0;
|
||||
@@ -572,9 +571,9 @@ st_scroll_view_allocate (ClutterActor *actor,
|
||||
clutter_actor_get_preferred_width (priv->child, -1,
|
||||
&child_min_width, NULL);
|
||||
|
||||
if (priv->vscrollbar_policy == ST_POLICY_AUTOMATIC)
|
||||
if (priv->vscrollbar_policy == GTK_POLICY_AUTOMATIC)
|
||||
{
|
||||
if (priv->hscrollbar_policy == ST_POLICY_AUTOMATIC)
|
||||
if (priv->hscrollbar_policy == GTK_POLICY_AUTOMATIC)
|
||||
{
|
||||
/* Pass one, try without a vertical scrollbar */
|
||||
clutter_actor_get_preferred_height (priv->child, avail_width, &child_min_height, NULL);
|
||||
@@ -592,7 +591,7 @@ st_scroll_view_allocate (ClutterActor *actor,
|
||||
}
|
||||
else
|
||||
{
|
||||
hscrollbar_visible = priv->hscrollbar_policy == ST_POLICY_ALWAYS;
|
||||
hscrollbar_visible = priv->hscrollbar_policy == GTK_POLICY_ALWAYS;
|
||||
|
||||
/* try without a vertical scrollbar */
|
||||
clutter_actor_get_preferred_height (priv->child, avail_width, &child_min_height, NULL);
|
||||
@@ -601,20 +600,20 @@ st_scroll_view_allocate (ClutterActor *actor,
|
||||
}
|
||||
else
|
||||
{
|
||||
vscrollbar_visible = priv->vscrollbar_policy == ST_POLICY_ALWAYS;
|
||||
vscrollbar_visible = priv->vscrollbar_policy == GTK_POLICY_ALWAYS;
|
||||
|
||||
if (priv->hscrollbar_policy == ST_POLICY_AUTOMATIC)
|
||||
if (priv->hscrollbar_policy == GTK_POLICY_AUTOMATIC)
|
||||
hscrollbar_visible = child_min_width > avail_height - (vscrollbar_visible ? 0 : sb_width);
|
||||
else
|
||||
hscrollbar_visible = priv->hscrollbar_policy == ST_POLICY_ALWAYS;
|
||||
hscrollbar_visible = priv->hscrollbar_policy == GTK_POLICY_ALWAYS;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hscrollbar_visible = priv->hscrollbar_policy != ST_POLICY_NEVER &&
|
||||
priv->hscrollbar_policy != ST_POLICY_EXTERNAL;
|
||||
vscrollbar_visible = priv->vscrollbar_policy != ST_POLICY_NEVER &&
|
||||
priv->vscrollbar_policy != ST_POLICY_EXTERNAL;
|
||||
hscrollbar_visible = priv->hscrollbar_policy != GTK_POLICY_NEVER &&
|
||||
priv->hscrollbar_policy != GTK_POLICY_EXTERNAL;
|
||||
vscrollbar_visible = priv->vscrollbar_policy != GTK_POLICY_NEVER &&
|
||||
priv->vscrollbar_policy != GTK_POLICY_EXTERNAL;
|
||||
}
|
||||
|
||||
/* Whether or not we show the scrollbars, if the scrollbars are visible
|
||||
@@ -662,12 +661,12 @@ st_scroll_view_allocate (ClutterActor *actor,
|
||||
* Fold this into the scrollbar sizes to simplify the rest of the
|
||||
* computations.
|
||||
*/
|
||||
if (priv->hscrollbar_policy == ST_POLICY_NEVER ||
|
||||
priv->hscrollbar_policy == ST_POLICY_EXTERNAL ||
|
||||
if (priv->hscrollbar_policy == GTK_POLICY_NEVER ||
|
||||
priv->hscrollbar_policy == GTK_POLICY_EXTERNAL ||
|
||||
priv->overlay_scrollbars)
|
||||
sb_height = 0;
|
||||
if (priv->vscrollbar_policy == ST_POLICY_NEVER ||
|
||||
priv->vscrollbar_policy == ST_POLICY_EXTERNAL ||
|
||||
if (priv->vscrollbar_policy == GTK_POLICY_NEVER ||
|
||||
priv->vscrollbar_policy == GTK_POLICY_EXTERNAL ||
|
||||
priv->overlay_scrollbars)
|
||||
sb_width = 0;
|
||||
|
||||
@@ -829,16 +828,16 @@ st_scroll_view_class_init (StScrollViewClass *klass)
|
||||
pspec = g_param_spec_enum ("vscrollbar-policy",
|
||||
"Vertical Scrollbar Policy",
|
||||
"When the vertical scrollbar is displayed",
|
||||
ST_TYPE_POLICY_TYPE,
|
||||
ST_POLICY_AUTOMATIC,
|
||||
GTK_TYPE_POLICY_TYPE,
|
||||
GTK_POLICY_AUTOMATIC,
|
||||
G_PARAM_READWRITE);
|
||||
g_object_class_install_property (object_class, PROP_VSCROLLBAR_POLICY, pspec);
|
||||
|
||||
pspec = g_param_spec_enum ("hscrollbar-policy",
|
||||
"Horizontal Scrollbar Policy",
|
||||
"When the horizontal scrollbar is displayed",
|
||||
ST_TYPE_POLICY_TYPE,
|
||||
ST_POLICY_AUTOMATIC,
|
||||
GTK_TYPE_POLICY_TYPE,
|
||||
GTK_POLICY_AUTOMATIC,
|
||||
G_PARAM_READWRITE);
|
||||
g_object_class_install_property (object_class, PROP_HSCROLLBAR_POLICY, pspec);
|
||||
|
||||
@@ -880,8 +879,8 @@ st_scroll_view_init (StScrollView *self)
|
||||
{
|
||||
StScrollViewPrivate *priv = self->priv = st_scroll_view_get_instance_private (self);
|
||||
|
||||
priv->hscrollbar_policy = ST_POLICY_AUTOMATIC;
|
||||
priv->vscrollbar_policy = ST_POLICY_AUTOMATIC;
|
||||
priv->hscrollbar_policy = GTK_POLICY_AUTOMATIC;
|
||||
priv->vscrollbar_policy = GTK_POLICY_AUTOMATIC;
|
||||
|
||||
priv->hadjustment = g_object_new (ST_TYPE_ADJUSTMENT, NULL);
|
||||
priv->hscroll = g_object_new (ST_TYPE_SCROLL_BAR,
|
||||
@@ -1188,8 +1187,8 @@ st_scroll_view_get_overlay_scrollbars (StScrollView *scroll)
|
||||
*/
|
||||
void
|
||||
st_scroll_view_set_policy (StScrollView *scroll,
|
||||
StPolicyType hscroll,
|
||||
StPolicyType vscroll)
|
||||
GtkPolicyType hscroll,
|
||||
GtkPolicyType vscroll)
|
||||
{
|
||||
StScrollViewPrivate *priv;
|
||||
|
||||
|
@@ -34,14 +34,6 @@ G_BEGIN_DECLS
|
||||
#define ST_TYPE_SCROLL_VIEW (st_scroll_view_get_type())
|
||||
G_DECLARE_FINAL_TYPE (StScrollView, st_scroll_view, ST, SCROLL_VIEW, StBin)
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ST_POLICY_ALWAYS,
|
||||
ST_POLICY_AUTOMATIC,
|
||||
ST_POLICY_NEVER,
|
||||
ST_POLICY_EXTERNAL,
|
||||
} StPolicyType;
|
||||
|
||||
typedef struct _StScrollViewPrivate StScrollViewPrivate;
|
||||
|
||||
/**
|
||||
@@ -80,8 +72,8 @@ void st_scroll_view_set_overlay_scrollbars (StScrollView *scroll,
|
||||
gboolean st_scroll_view_get_overlay_scrollbars (StScrollView *scroll);
|
||||
|
||||
void st_scroll_view_set_policy (StScrollView *scroll,
|
||||
StPolicyType hscroll,
|
||||
StPolicyType vscroll);
|
||||
GtkPolicyType hscroll,
|
||||
GtkPolicyType vscroll);
|
||||
void st_scroll_view_update_fade_effect (StScrollView *scroll,
|
||||
float vfade_offset,
|
||||
float hfade_offset);
|
||||
|
@@ -1,232 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* st-settings.c: Global settings
|
||||
*
|
||||
* Copyright 2019 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU Lesser General Public License,
|
||||
* version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope 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/>.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <gio/gio.h>
|
||||
|
||||
#include "st-settings.h"
|
||||
|
||||
#define KEY_ENABLE_ANIMATIONS "enable-animations"
|
||||
#define KEY_PRIMARY_PASTE "gtk-enable-primary-paste"
|
||||
#define KEY_DRAG_THRESHOLD "drag-threshold"
|
||||
#define KEY_GTK_THEME "gtk-theme"
|
||||
#define KEY_GTK_ICON_THEME "icon-theme"
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_ENABLE_ANIMATIONS,
|
||||
PROP_PRIMARY_PASTE,
|
||||
PROP_DRAG_THRESHOLD,
|
||||
PROP_GTK_THEME,
|
||||
PROP_GTK_ICON_THEME,
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
GParamSpec *props[N_PROPS] = { 0 };
|
||||
|
||||
struct _StSettings
|
||||
{
|
||||
GObject parent_object;
|
||||
GSettings *interface_settings;
|
||||
GSettings *mouse_settings;
|
||||
|
||||
gchar *gtk_theme;
|
||||
gchar *gtk_icon_theme;
|
||||
gboolean enable_animations;
|
||||
gboolean primary_paste;
|
||||
gint drag_threshold;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (StSettings, st_settings, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
st_settings_finalize (GObject *object)
|
||||
{
|
||||
StSettings *settings = ST_SETTINGS (object);
|
||||
|
||||
g_object_unref (settings->interface_settings);
|
||||
g_object_unref (settings->mouse_settings);
|
||||
g_free (settings->gtk_theme);
|
||||
g_free (settings->gtk_icon_theme);
|
||||
|
||||
G_OBJECT_CLASS (st_settings_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
st_settings_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
|
||||
static void
|
||||
st_settings_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
StSettings *settings = ST_SETTINGS (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_ENABLE_ANIMATIONS:
|
||||
g_value_set_boolean (value, settings->enable_animations);
|
||||
break;
|
||||
case PROP_PRIMARY_PASTE:
|
||||
g_value_set_boolean (value, settings->primary_paste);
|
||||
break;
|
||||
case PROP_DRAG_THRESHOLD:
|
||||
g_value_set_int (value, settings->drag_threshold);
|
||||
break;
|
||||
case PROP_GTK_THEME:
|
||||
g_value_set_string (value, settings->gtk_theme);
|
||||
break;
|
||||
case PROP_GTK_ICON_THEME:
|
||||
g_value_set_string (value, settings->gtk_icon_theme);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
st_settings_class_init (StSettingsClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = st_settings_finalize;
|
||||
object_class->set_property = st_settings_set_property;
|
||||
object_class->get_property = st_settings_get_property;
|
||||
|
||||
props[PROP_ENABLE_ANIMATIONS] = g_param_spec_boolean ("enable-animations",
|
||||
"Enable animations",
|
||||
"Enable animations",
|
||||
TRUE,
|
||||
G_PARAM_READABLE);
|
||||
props[PROP_PRIMARY_PASTE] = g_param_spec_boolean ("primary-paste",
|
||||
"Primary paste",
|
||||
"Primary paste",
|
||||
TRUE,
|
||||
G_PARAM_READABLE);
|
||||
props[PROP_DRAG_THRESHOLD] = g_param_spec_int ("drag-threshold",
|
||||
"Drag threshold",
|
||||
"Drag threshold",
|
||||
0, G_MAXINT, 8,
|
||||
G_PARAM_READABLE);
|
||||
props[PROP_GTK_THEME] = g_param_spec_string ("gtk-theme",
|
||||
"GTK+ Theme",
|
||||
"GTK+ Theme",
|
||||
"",
|
||||
G_PARAM_READABLE);
|
||||
props[PROP_GTK_ICON_THEME] = g_param_spec_string ("gtk-icon-theme",
|
||||
"GTK+ Icon Theme",
|
||||
"GTK+ Icon Theme",
|
||||
"",
|
||||
G_PARAM_READABLE);
|
||||
|
||||
g_object_class_install_properties (object_class, N_PROPS, props);
|
||||
}
|
||||
|
||||
static void
|
||||
on_interface_settings_changed (GSettings *g_settings,
|
||||
const gchar *key,
|
||||
StSettings *settings)
|
||||
{
|
||||
if (g_str_equal (key, KEY_ENABLE_ANIMATIONS))
|
||||
{
|
||||
settings->enable_animations = g_settings_get_boolean (g_settings, key);
|
||||
g_object_notify_by_pspec (G_OBJECT (settings), props[PROP_ENABLE_ANIMATIONS]);
|
||||
}
|
||||
else if (g_str_equal (key, KEY_PRIMARY_PASTE))
|
||||
{
|
||||
settings->primary_paste = g_settings_get_boolean (g_settings, key);
|
||||
g_object_notify_by_pspec (G_OBJECT (settings), props[PROP_PRIMARY_PASTE]);
|
||||
}
|
||||
else if (g_str_equal (key, KEY_GTK_THEME))
|
||||
{
|
||||
g_free (settings->gtk_theme);
|
||||
settings->gtk_theme = g_settings_get_string (g_settings, key);
|
||||
g_object_notify_by_pspec (G_OBJECT (settings), props[PROP_GTK_THEME]);
|
||||
}
|
||||
else if (g_str_equal (key, KEY_GTK_ICON_THEME))
|
||||
{
|
||||
g_free (settings->gtk_icon_theme);
|
||||
settings->gtk_icon_theme = g_settings_get_string (g_settings, key);
|
||||
g_object_notify_by_pspec (G_OBJECT (settings),
|
||||
props[PROP_GTK_ICON_THEME]);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_mouse_settings_changed (GSettings *g_settings,
|
||||
const gchar *key,
|
||||
StSettings *settings)
|
||||
{
|
||||
if (g_str_equal (key, KEY_DRAG_THRESHOLD))
|
||||
{
|
||||
settings->drag_threshold = g_settings_get_int (g_settings, key);
|
||||
g_object_notify_by_pspec (G_OBJECT (settings), props[PROP_DRAG_THRESHOLD]);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
st_settings_init (StSettings *settings)
|
||||
{
|
||||
settings->interface_settings = g_settings_new ("org.gnome.desktop.interface");
|
||||
g_signal_connect (settings->interface_settings, "changed",
|
||||
G_CALLBACK (on_interface_settings_changed), settings);
|
||||
|
||||
settings->mouse_settings = g_settings_new ("org.gnome.settings-daemon.peripherals.mouse");
|
||||
g_signal_connect (settings->interface_settings, "changed",
|
||||
G_CALLBACK (on_mouse_settings_changed), settings);
|
||||
|
||||
settings->enable_animations = g_settings_get_boolean (settings->interface_settings,
|
||||
KEY_ENABLE_ANIMATIONS);
|
||||
settings->primary_paste = g_settings_get_boolean (settings->interface_settings,
|
||||
KEY_PRIMARY_PASTE);
|
||||
settings->gtk_theme = g_settings_get_string (settings->interface_settings,
|
||||
KEY_GTK_THEME);
|
||||
settings->gtk_icon_theme = g_settings_get_string (settings->interface_settings,
|
||||
KEY_GTK_ICON_THEME);
|
||||
settings->drag_threshold = g_settings_get_int (settings->mouse_settings,
|
||||
KEY_DRAG_THRESHOLD);
|
||||
}
|
||||
|
||||
/**
|
||||
* st_settings_get:
|
||||
*
|
||||
* Gets the #StSettings
|
||||
*
|
||||
* Returns: (transfer none): a settings object
|
||||
**/
|
||||
StSettings *
|
||||
st_settings_get (void)
|
||||
{
|
||||
static StSettings *settings = NULL;
|
||||
|
||||
if (!settings)
|
||||
settings = g_object_new (ST_TYPE_SETTINGS, NULL);
|
||||
|
||||
return settings;
|
||||
}
|
@@ -1,34 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* st-settings.h: Global settings
|
||||
*
|
||||
* Copyright 2019 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU Lesser General Public License,
|
||||
* version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope 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/>.
|
||||
*/
|
||||
|
||||
#if !defined(ST_H_INSIDE) && !defined(ST_COMPILATION)
|
||||
#error "Only <st/st.h> can be included directly.h"
|
||||
#endif
|
||||
|
||||
#ifndef __ST_SETTINGS_H__
|
||||
#define __ST_SETTINGS_H__
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define ST_TYPE_SETTINGS (st_settings_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (StSettings, st_settings, ST, SETTINGS, GObject)
|
||||
|
||||
StSettings * st_settings_get (void);
|
||||
|
||||
#endif /* __ST_SETTINGS_H__ */
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user