Compare commits
10 Commits
Author | SHA1 | Date | |
---|---|---|---|
60612cace9 | |||
f057502834 | |||
21a1149532 | |||
6724ca4f63 | |||
7a6c25b3fb | |||
0366e320af | |||
f03793b825 | |||
0907f030b4 | |||
7542e68b6f | |||
9003a34285 |
47
NEWS
47
NEWS
@ -1,3 +1,50 @@
|
|||||||
|
3.1.4
|
||||||
|
=====
|
||||||
|
* Take over inserted media handling and autorun from gnome-session [Cosimo]
|
||||||
|
* Message Tray
|
||||||
|
- Display a count of unread notifications on icons
|
||||||
|
[Jasper, Guillaume; #649356, #654139]
|
||||||
|
- Only remove icons when the sender quits from D-Bus, not when it
|
||||||
|
closes its last window [Neha, Marina; #645764]
|
||||||
|
- Solve problems switching chats between shell and Empathy
|
||||||
|
[Guillaume; #654237]
|
||||||
|
- Fix handling of bad GMarkup in messages [Dan; #650298]
|
||||||
|
- Never show notifications when the screensaver is active [Dan; #654550]
|
||||||
|
* Telepathy integrationpp
|
||||||
|
- Implement Telepathy Debug interface to enable empathy-debugger
|
||||||
|
[Guillaume; #652816]
|
||||||
|
- Allow approving room invitations, and audio/video calls
|
||||||
|
[Guillaume; #653740 #653939]
|
||||||
|
- Send typing notifications [Jonny; #650196]
|
||||||
|
* Fix selection highlighting for light-on-dark entries [Jasper; #643768]
|
||||||
|
* Make control-Return in the overview open a new window [Maxim]
|
||||||
|
* Delay showing the alt-Tab switcher to reduce visual noise when
|
||||||
|
flipping betweeen windows [Dan; #652346]
|
||||||
|
* When we have vertically stacked monitors, put the message tray
|
||||||
|
on the bottom one [Dan; #636963]
|
||||||
|
* Fix various problems with keynav and the Activities button
|
||||||
|
[Dan; #641253 #645759]
|
||||||
|
* Ensure screensaver is locked when switching users [Colin; #654565]
|
||||||
|
* Improve extension creation tool [Jasper; #653206]
|
||||||
|
* Fix compatibility with latest GJS [Giovanni; #654349]
|
||||||
|
* Code cleanups [Adel, Dan, Jasper; #645759 #654577 #654791 #654987]
|
||||||
|
* Misc bug fixes [Richard, Dan, Florian, Giovanni, Jasper, Marc-Antoine, Rui;
|
||||||
|
#647175 #649513 #650452 #651082 #653700 #653989 #654105 #654791 #654267
|
||||||
|
#654269 #654527 #655446]
|
||||||
|
* Build fixes [Florian, Siegfried; #654300]
|
||||||
|
|
||||||
|
Contributors:
|
||||||
|
Giovanni Campagna, Cosimo Cecchi, Guillaume Desmottes, Neha Doijode,
|
||||||
|
Maxim Ermilov, Adel Gadllah, Siegfried-Angel Gevatter Pujals, Richard Hughes,
|
||||||
|
Jonny Lamb, Rui Matos, Florian Müllner, Marc-Antoine Perennou, Colin Walters,
|
||||||
|
Dan Winship, Marina Zhurakhinskaya
|
||||||
|
|
||||||
|
Translations:
|
||||||
|
Mario Blättermann, Paul Seyfert [de], Jorge González, Daniel Mustieles [es],
|
||||||
|
Fran Dieguez [gl], Yaron Shahrabani [he], Luca Ferretti [it],
|
||||||
|
Rudolfs Mazurs [lv], Kjartan Maraas [nb], A S Alam [pa], Yuri Kozlov [ru],
|
||||||
|
Michal Štrba, Matej Urbančič [sl]
|
||||||
|
|
||||||
3.1.3
|
3.1.3
|
||||||
=====
|
=====
|
||||||
* Fix problem with "user theme extension" breaking the CSS for other
|
* Fix problem with "user theme extension" breaking the CSS for other
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
AC_PREREQ(2.63)
|
AC_PREREQ(2.63)
|
||||||
AC_INIT([gnome-shell],[3.1.3],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
|
AC_INIT([gnome-shell],[3.1.4],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
|
||||||
|
|
||||||
AC_CONFIG_HEADERS([config.h])
|
AC_CONFIG_HEADERS([config.h])
|
||||||
AC_CONFIG_SRCDIR([src/shell-global.c])
|
AC_CONFIG_SRCDIR([src/shell-global.c])
|
||||||
@ -66,7 +66,7 @@ AM_CONDITIONAL(BUILD_RECORDER, $build_recorder)
|
|||||||
|
|
||||||
CLUTTER_MIN_VERSION=1.7.5
|
CLUTTER_MIN_VERSION=1.7.5
|
||||||
GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1
|
GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1
|
||||||
GJS_MIN_VERSION=0.7.11
|
GJS_MIN_VERSION=1.29.15
|
||||||
MUTTER_MIN_VERSION=3.0.0
|
MUTTER_MIN_VERSION=3.0.0
|
||||||
GTK_MIN_VERSION=3.0.0
|
GTK_MIN_VERSION=3.0.0
|
||||||
GIO_MIN_VERSION=2.25.9
|
GIO_MIN_VERSION=2.25.9
|
||||||
|
@ -62,7 +62,6 @@
|
|||||||
<child name="clock" schema="org.gnome.shell.clock"/>
|
<child name="clock" schema="org.gnome.shell.clock"/>
|
||||||
<child name="calendar" schema="org.gnome.shell.calendar"/>
|
<child name="calendar" schema="org.gnome.shell.calendar"/>
|
||||||
<child name="recorder" schema="org.gnome.shell.recorder"/>
|
<child name="recorder" schema="org.gnome.shell.recorder"/>
|
||||||
<child name="keyboard" schema="org.gnome.shell.keyboard"/>
|
|
||||||
</schema>
|
</schema>
|
||||||
|
|
||||||
<schema id="org.gnome.shell.calendar" path="/org/gnome/shell/calendar/"
|
<schema id="org.gnome.shell.calendar" path="/org/gnome/shell/calendar/"
|
||||||
@ -76,38 +75,6 @@
|
|||||||
</key>
|
</key>
|
||||||
</schema>
|
</schema>
|
||||||
|
|
||||||
<schema id="org.gnome.shell.keyboard" path="/org/gnome/shell/keyboard/"
|
|
||||||
gettext-domain="@GETTEXT_PACKAGE@">
|
|
||||||
<key name="show-keyboard" type="b">
|
|
||||||
<default>false</default>
|
|
||||||
<_summary>Show the onscreen keyboard</_summary>
|
|
||||||
<_description>
|
|
||||||
If true, display onscreen keyboard.
|
|
||||||
</_description>
|
|
||||||
</key>
|
|
||||||
<key name="keyboard-type" type="s">
|
|
||||||
<default>'touch'</default>
|
|
||||||
<_summary>Which keyboard to use</_summary>
|
|
||||||
<_description>
|
|
||||||
The type of keyboard to use.
|
|
||||||
</_description>
|
|
||||||
</key>
|
|
||||||
<key name="enable-drag" type="b">
|
|
||||||
<default>false</default>
|
|
||||||
<_summary>Enable keyboard dragging</_summary>
|
|
||||||
<_description>
|
|
||||||
If true, enable keyboard dragging.
|
|
||||||
</_description>
|
|
||||||
</key>
|
|
||||||
<key name="enable-float" type="b">
|
|
||||||
<default>false</default>
|
|
||||||
<_summary>Enable floating keyboard</_summary>
|
|
||||||
<_description>
|
|
||||||
If true, enable floating keyboard.
|
|
||||||
</_description>
|
|
||||||
</key>
|
|
||||||
</schema>
|
|
||||||
|
|
||||||
<schema id="org.gnome.shell.clock" path="/org/gnome/shell/clock/"
|
<schema id="org.gnome.shell.clock" path="/org/gnome/shell/clock/"
|
||||||
gettext-domain="@GETTEXT_PACKAGE@">
|
gettext-domain="@GETTEXT_PACKAGE@">
|
||||||
<key name="show-seconds" type="b">
|
<key name="show-seconds" type="b">
|
||||||
|
@ -1839,57 +1839,3 @@ StTooltip StLabel {
|
|||||||
.magnifier-zoom-region.full-screen {
|
.magnifier-zoom-region.full-screen {
|
||||||
border-width: 0px;
|
border-width: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* On-screen Keyboard */
|
|
||||||
|
|
||||||
#keyboard {
|
|
||||||
background: rgba(0,0,0,0.8);
|
|
||||||
}
|
|
||||||
|
|
||||||
.keyboard-layout {
|
|
||||||
spacing: 10px;
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.keyboard-row {
|
|
||||||
spacing: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.keyboard-key {
|
|
||||||
min-height: 30px;
|
|
||||||
min-width: 30px;
|
|
||||||
background-gradient-start: rgba(255,245,245,0.4);
|
|
||||||
background-gradient-end: rgba(105,105,105,0.1);
|
|
||||||
background-gradient-direction: vertical;
|
|
||||||
font-size: 14pt;
|
|
||||||
font-weight: bold;
|
|
||||||
border-radius: 10px;
|
|
||||||
border: 2px solid #a0a0a0;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.keyboard-key:grayed {
|
|
||||||
color: #808080;
|
|
||||||
border-color: #808080;
|
|
||||||
}
|
|
||||||
|
|
||||||
.keyboard-key:checked,
|
|
||||||
.keyboard-key:hover {
|
|
||||||
background: #303030;
|
|
||||||
border: 3px solid white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.keyboard-key:active {
|
|
||||||
background: #808080;
|
|
||||||
}
|
|
||||||
|
|
||||||
.keyboard-subkeys {
|
|
||||||
color: white;
|
|
||||||
padding: 5px;
|
|
||||||
-arrow-border-radius: 10px;
|
|
||||||
-arrow-background-color: #090909;
|
|
||||||
-arrow-border-width: 2px;
|
|
||||||
-arrow-border-color: white;
|
|
||||||
-arrow-base: 20px;
|
|
||||||
-arrow-rise: 10px;
|
|
||||||
}
|
|
||||||
|
@ -30,7 +30,6 @@ nobase_dist_js_DATA = \
|
|||||||
ui/environment.js \
|
ui/environment.js \
|
||||||
ui/extensionSystem.js \
|
ui/extensionSystem.js \
|
||||||
ui/iconGrid.js \
|
ui/iconGrid.js \
|
||||||
ui/keyboard.js \
|
|
||||||
ui/layout.js \
|
ui/layout.js \
|
||||||
ui/lightbox.js \
|
ui/lightbox.js \
|
||||||
ui/link.js \
|
ui/link.js \
|
||||||
|
@ -36,10 +36,6 @@ Chrome.prototype = {
|
|||||||
|
|
||||||
this._trackedActors = [];
|
this._trackedActors = [];
|
||||||
|
|
||||||
Main.connect('initialized', Lang.bind(this, this._finishInit));
|
|
||||||
},
|
|
||||||
|
|
||||||
_finishInit: function() {
|
|
||||||
Main.layoutManager.connect('monitors-changed',
|
Main.layoutManager.connect('monitors-changed',
|
||||||
Lang.bind(this, this._relayout));
|
Lang.bind(this, this._relayout));
|
||||||
global.screen.connect('restacked',
|
global.screen.connect('restacked',
|
||||||
@ -293,6 +289,11 @@ Chrome.prototype = {
|
|||||||
|
|
||||||
for (let i = windows.length - 1; i > -1; i--) {
|
for (let i = windows.length - 1; i > -1; i--) {
|
||||||
let window = windows[i];
|
let window = windows[i];
|
||||||
|
|
||||||
|
// Skip minimized windows
|
||||||
|
if (!window.showing_on_its_workspace())
|
||||||
|
continue;
|
||||||
|
|
||||||
let layer = window.get_meta_window().get_layer();
|
let layer = window.get_meta_window().get_layer();
|
||||||
|
|
||||||
if (layer == Meta.StackLayer.FULLSCREEN) {
|
if (layer == Meta.StackLayer.FULLSCREEN) {
|
||||||
|
@ -1,609 +0,0 @@
|
|||||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
||||||
|
|
||||||
const Caribou = imports.gi.Caribou;
|
|
||||||
const Clutter = imports.gi.Clutter;
|
|
||||||
const DBus = imports.dbus;
|
|
||||||
const Gdk = imports.gi.Gdk;
|
|
||||||
const Gio = imports.gi.Gio;
|
|
||||||
const GLib = imports.gi.GLib;
|
|
||||||
const Lang = imports.lang;
|
|
||||||
const Meta = imports.gi.Meta;
|
|
||||||
const Shell = imports.gi.Shell;
|
|
||||||
const St = imports.gi.St;
|
|
||||||
|
|
||||||
const BoxPointer = imports.ui.boxpointer;
|
|
||||||
const Main = imports.ui.main;
|
|
||||||
const MessageTray = imports.ui.messageTray;
|
|
||||||
const PopupMenu = imports.ui.popupMenu;
|
|
||||||
const Tweener = imports.ui.tweener;
|
|
||||||
|
|
||||||
const KEYBOARD_SCHEMA = 'org.gnome.shell.keyboard';
|
|
||||||
const SHOW_KEYBOARD = 'show-keyboard';
|
|
||||||
const KEYBOARD_TYPE = 'keyboard-type';
|
|
||||||
const ENABLE_DRAGGABLE = 'enable-drag';
|
|
||||||
const ENABLE_FLOAT = 'enable-float';
|
|
||||||
|
|
||||||
// Key constants taken from Antler
|
|
||||||
const PRETTY_KEYS = {
|
|
||||||
'BackSpace': '\u232b',
|
|
||||||
'space': ' ',
|
|
||||||
'Return': '\u23ce',
|
|
||||||
'Caribou_Prefs': '\u2328',
|
|
||||||
'Caribou_ShiftUp': '\u2b06',
|
|
||||||
'Caribou_ShiftDown': '\u2b07',
|
|
||||||
'Caribou_Emoticons': '\u263a',
|
|
||||||
'Caribou_Symbols': '123',
|
|
||||||
'Caribou_Symbols_More': '{#*',
|
|
||||||
'Caribou_Alpha': 'Abc',
|
|
||||||
'Tab': 'Tab',
|
|
||||||
'Escape': 'Esc',
|
|
||||||
'Control_L': 'Ctrl',
|
|
||||||
'Alt_L': 'Alt'
|
|
||||||
};
|
|
||||||
|
|
||||||
const CaribouKeyboardIface = {
|
|
||||||
name: 'org.gnome.Caribou.Keyboard',
|
|
||||||
methods: [ { name: 'Show',
|
|
||||||
inSignature: '',
|
|
||||||
outSignature: ''
|
|
||||||
},
|
|
||||||
{ name: 'Hide',
|
|
||||||
inSignature: '',
|
|
||||||
outSignature: ''
|
|
||||||
},
|
|
||||||
{ name: 'SetCursorLocation',
|
|
||||||
inSignature: 'iiii',
|
|
||||||
outSignature: ''
|
|
||||||
},
|
|
||||||
{ name: 'SetEntryLocation',
|
|
||||||
inSignature: 'iiii',
|
|
||||||
outSignature: ''
|
|
||||||
} ],
|
|
||||||
properties: [ { name: 'Name',
|
|
||||||
signature: 's',
|
|
||||||
access: 'read' } ]
|
|
||||||
};
|
|
||||||
|
|
||||||
function Key() {
|
|
||||||
this._init.apply(this, arguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
Key.prototype = {
|
|
||||||
_init : function(key, key_width, key_height) {
|
|
||||||
this._key = key;
|
|
||||||
|
|
||||||
this._width = key_width;
|
|
||||||
this._height = key_height;
|
|
||||||
|
|
||||||
this.actor = this._getKey();
|
|
||||||
|
|
||||||
this._extended_keys = this._key.get_extended_keys();
|
|
||||||
this._extended_keyboard = {};
|
|
||||||
|
|
||||||
if (this._key.name == "Control_L" || this._key.name == "Alt_L")
|
|
||||||
this._key.latch = true;
|
|
||||||
|
|
||||||
this._key.connect('key-pressed', Lang.bind(this, function ()
|
|
||||||
{ this.actor.checked = true }));
|
|
||||||
this._key.connect('key-released', Lang.bind(this, function ()
|
|
||||||
{ this.actor.checked = false; }));
|
|
||||||
|
|
||||||
if (this._extended_keys.length > 0) {
|
|
||||||
this._grabbed = false;
|
|
||||||
this._eventCaptureId = 0;
|
|
||||||
this._key.connect('notify::show-subkeys', Lang.bind(this, this._onShowSubkeysChanged));
|
|
||||||
this._boxPointer = new BoxPointer.BoxPointer(St.Side.BOTTOM,
|
|
||||||
{ x_fill: true,
|
|
||||||
y_fill: true,
|
|
||||||
x_align: St.Align.START });
|
|
||||||
// Adds style to existing keyboard style to avoid repetition
|
|
||||||
this._boxPointer.actor.add_style_class_name('keyboard-subkeys');
|
|
||||||
this._getExtendedKeys();
|
|
||||||
this.actor._extended_keys = this._extended_keyboard;
|
|
||||||
this._boxPointer.actor.hide();
|
|
||||||
Main.chrome.addActor(this._boxPointer.actor, { visibleInFullscreen: true,
|
|
||||||
affectsStruts: false });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_getKey: function () {
|
|
||||||
let label = this._key.name;
|
|
||||||
|
|
||||||
if (label.length > 1) {
|
|
||||||
let pretty = PRETTY_KEYS[label];
|
|
||||||
if (pretty)
|
|
||||||
label = pretty;
|
|
||||||
else
|
|
||||||
label = this._getUnichar(this._key);
|
|
||||||
}
|
|
||||||
|
|
||||||
label = GLib.markup_escape_text(label, -1);
|
|
||||||
let button = new St.Button ({ label: label, style_class: 'keyboard-key' });
|
|
||||||
|
|
||||||
button.width = this._width;
|
|
||||||
button.key_width = this._key.width;
|
|
||||||
button.height = this._height;
|
|
||||||
button.draggable = false;
|
|
||||||
button.connect('button-press-event', Lang.bind(this, function () { this._key.press(); }));
|
|
||||||
button.connect('button-release-event', Lang.bind(this, function () { this._key.release(); }));
|
|
||||||
|
|
||||||
return button;
|
|
||||||
},
|
|
||||||
|
|
||||||
_getUnichar: function(key) {
|
|
||||||
let keyval = key.keyval;
|
|
||||||
let unichar = Gdk.keyval_to_unicode(keyval);
|
|
||||||
if (unichar) {
|
|
||||||
return String.fromCharCode(unichar);
|
|
||||||
} else {
|
|
||||||
return key.name;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_getExtendedKeys: function () {
|
|
||||||
this._extended_keyboard = new St.BoxLayout({ style_class: 'keyboard-layout',
|
|
||||||
vertical: false });
|
|
||||||
for (let i = 0; i < this._extended_keys.length; ++i) {
|
|
||||||
let extended_key = this._extended_keys[i];
|
|
||||||
let label = this._getUnichar(extended_key);
|
|
||||||
let key = new St.Button({ label: label, style_class: 'keyboard-key' });
|
|
||||||
key.extended_key = extended_key;
|
|
||||||
key.width = this._width;
|
|
||||||
key.height = this._height;
|
|
||||||
key.draggable = false;
|
|
||||||
key.connect('button-press-event', Lang.bind(this, function () { extended_key.press(); }));
|
|
||||||
key.connect('button-release-event', Lang.bind(this, function () { extended_key.release(); }));
|
|
||||||
this._extended_keyboard.add(key);
|
|
||||||
}
|
|
||||||
this._boxPointer.bin.add_actor(this._extended_keyboard);
|
|
||||||
},
|
|
||||||
|
|
||||||
_onEventCapture: function (actor, event) {
|
|
||||||
let source = event.get_source();
|
|
||||||
if (event.type() == Clutter.EventType.BUTTON_PRESS ||
|
|
||||||
(event.type() == Clutter.EventType.BUTTON_RELEASE && source.draggable)) {
|
|
||||||
if (this._extended_keyboard.contains(source)) {
|
|
||||||
if (source.draggable) {
|
|
||||||
source.extended_key.press();
|
|
||||||
source.extended_key.release();
|
|
||||||
}
|
|
||||||
this._ungrab();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
this._boxPointer.actor.hide();
|
|
||||||
this._ungrab();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
|
|
||||||
_ungrab: function () {
|
|
||||||
global.stage.disconnect(this._eventCaptureId);
|
|
||||||
this._eventCaptureId = 0;
|
|
||||||
this._grabbed = false;
|
|
||||||
Main.popModal(this.actor);
|
|
||||||
},
|
|
||||||
|
|
||||||
_onShowSubkeysChanged: function () {
|
|
||||||
if (this._key.show_subkeys) {
|
|
||||||
this.actor.fake_release();
|
|
||||||
this._boxPointer.actor.raise_top();
|
|
||||||
this._boxPointer.setPosition(this.actor, 5, 0.5);
|
|
||||||
this._boxPointer.show(true);
|
|
||||||
this.actor.set_hover(false);
|
|
||||||
if (!this._grabbed) {
|
|
||||||
Main.pushModal(this.actor);
|
|
||||||
this._eventCaptureId = global.stage.connect('captured-event', Lang.bind(this, this._onEventCapture));
|
|
||||||
this._grabbed = true;
|
|
||||||
}
|
|
||||||
this._key.release();
|
|
||||||
} else {
|
|
||||||
if (this._grabbed)
|
|
||||||
this._ungrab();
|
|
||||||
this._boxPointer.hide(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function Keyboard() {
|
|
||||||
this._init.apply(this, arguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
Keyboard.prototype = {
|
|
||||||
_init: function () {
|
|
||||||
DBus.session.exportObject('/org/gnome/Caribou/Keyboard', this);
|
|
||||||
DBus.session.acquire_name('org.gnome.Caribou.Keyboard', 0, null, null);
|
|
||||||
|
|
||||||
this.actor = new St.BoxLayout({ name: 'keyboard', vertical: true, reactive: true });
|
|
||||||
|
|
||||||
this._keyboardSettings = new Gio.Settings({ schema: KEYBOARD_SCHEMA });
|
|
||||||
this._keyboardSettings.connect('changed', Lang.bind(this, this._display));
|
|
||||||
|
|
||||||
this._setupKeyboard();
|
|
||||||
|
|
||||||
Main.layoutManager.connect('monitors-changed', Lang.bind(this, this._redraw));
|
|
||||||
|
|
||||||
Main.layoutManager.bottomBox.add_actor(this.actor);
|
|
||||||
},
|
|
||||||
|
|
||||||
init: function () {
|
|
||||||
this._display();
|
|
||||||
},
|
|
||||||
|
|
||||||
_setupKeyboard: function() {
|
|
||||||
if (this._keyboardNotifyId)
|
|
||||||
this._keyboard.disconnect(this._keyboardNotifyId);
|
|
||||||
let children = this.actor.get_children();
|
|
||||||
for (let i = 0; i < children.length; i++)
|
|
||||||
children[i].destroy();
|
|
||||||
|
|
||||||
this._keyboard = new Caribou.KeyboardModel({ keyboard_type: this._keyboardSettings.get_string(KEYBOARD_TYPE) });
|
|
||||||
this._groups = {};
|
|
||||||
this._current_page = null;
|
|
||||||
|
|
||||||
// Initialize keyboard key measurements
|
|
||||||
this._numOfHorizKeys = 0;
|
|
||||||
this._numOfVertKeys = 0;
|
|
||||||
|
|
||||||
this._floatId = 0;
|
|
||||||
|
|
||||||
this._addKeys();
|
|
||||||
|
|
||||||
this._keyboardNotifyId = this._keyboard.connect('notify::active-group', Lang.bind(this, this._onGroupChanged));
|
|
||||||
},
|
|
||||||
|
|
||||||
_display: function () {
|
|
||||||
if (this._keyboard.keyboard_type != this._keyboardSettings.get_string(KEYBOARD_TYPE))
|
|
||||||
this._setupKeyboard();
|
|
||||||
|
|
||||||
this._showKeyboard = this._keyboardSettings.get_boolean(SHOW_KEYBOARD);
|
|
||||||
this._draggable = this._keyboardSettings.get_boolean(ENABLE_DRAGGABLE);
|
|
||||||
this._floating = this._keyboardSettings.get_boolean(ENABLE_FLOAT);
|
|
||||||
if (this._floating) {
|
|
||||||
this._floatId = this.actor.connect('button-press-event', Lang.bind(this, this._startDragging));
|
|
||||||
this._dragging = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
this.actor.disconnect(this._floatId);
|
|
||||||
if (this._showKeyboard)
|
|
||||||
this.show();
|
|
||||||
else {
|
|
||||||
this.hide();
|
|
||||||
this.destroySource();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_startDragging: function (actor, event) {
|
|
||||||
if (this._dragging) // don't allow two drags at the same time
|
|
||||||
return;
|
|
||||||
this._dragging = true;
|
|
||||||
this._preDragStageMode = global.stage_input_mode;
|
|
||||||
|
|
||||||
Clutter.grab_pointer(this.actor);
|
|
||||||
global.set_stage_input_mode(Shell.StageInputMode.FULLSCREEN);
|
|
||||||
|
|
||||||
this._releaseId = this.actor.connect('button-release-event', Lang.bind(this, this._endDragging));
|
|
||||||
this._motionId = this.actor.connect('motion-event', Lang.bind(this, this._motionEvent));
|
|
||||||
[this._dragStartX, this._dragStartY] = event.get_coords();
|
|
||||||
[this._currentX, this._currentY] = this.actor.get_position();
|
|
||||||
},
|
|
||||||
|
|
||||||
_endDragging: function () {
|
|
||||||
if (this._dragging) {
|
|
||||||
this.actor.disconnect(this._releaseId);
|
|
||||||
this.actor.disconnect(this._motionId);
|
|
||||||
|
|
||||||
Clutter.ungrab_pointer();
|
|
||||||
global.set_stage_input_mode(this._preDragStageMode);
|
|
||||||
global.unset_cursor();
|
|
||||||
this._dragging = false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
_motionEvent: function(actor, event) {
|
|
||||||
let absX, absY;
|
|
||||||
[absX, absY] = event.get_coords();
|
|
||||||
global.set_cursor(Shell.Cursor.DND_IN_DRAG);
|
|
||||||
this._moveHandle(absX, absY);
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
_moveHandle: function (stageX, stageY) {
|
|
||||||
let x, y;
|
|
||||||
x = stageX - this._dragStartX + this._currentX;
|
|
||||||
y = stageY - this._dragStartY + this._currentY;
|
|
||||||
this.actor.set_position(x,y);
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
_addKeys: function () {
|
|
||||||
let groups = this._keyboard.get_groups();
|
|
||||||
for (let i = 0; i < groups.length; ++i) {
|
|
||||||
let gname = groups[i];
|
|
||||||
let group = this._keyboard.get_group(gname);
|
|
||||||
group.connect('notify::active-level', Lang.bind(this, this._onLevelChanged));
|
|
||||||
let layers = {};
|
|
||||||
let levels = group.get_levels();
|
|
||||||
for (let j = 0; j < levels.length; ++j) {
|
|
||||||
let lname = levels[j];
|
|
||||||
let level = group.get_level(lname);
|
|
||||||
let layout = new St.BoxLayout({ style_class: 'keyboard-layout',
|
|
||||||
vertical: true });
|
|
||||||
this._loadRows(level, layout);
|
|
||||||
layers[lname] = layout;
|
|
||||||
this.actor.add(layout, { x_fill: false });
|
|
||||||
|
|
||||||
layout.hide();
|
|
||||||
}
|
|
||||||
this._groups[gname] = layers;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._setActiveLayer();
|
|
||||||
},
|
|
||||||
|
|
||||||
_getTrayIcon: function () {
|
|
||||||
let trayButton = new St.Button ({ label: "tray", style_class: 'keyboard-key' });
|
|
||||||
trayButton.key_width = 1;
|
|
||||||
trayButton.connect('button-press-event', Lang.bind(this, function () {
|
|
||||||
Main.layoutManager.updateForTray();
|
|
||||||
}));
|
|
||||||
|
|
||||||
Main.overview.connect('showing', Lang.bind(this, function () {
|
|
||||||
trayButton.reactive = false;
|
|
||||||
trayButton.add_style_pseudo_class('grayed');
|
|
||||||
}));
|
|
||||||
Main.overview.connect('hiding', Lang.bind(this, function () {
|
|
||||||
trayButton.reactive = true;
|
|
||||||
trayButton.remove_style_pseudo_class('grayed');
|
|
||||||
}));
|
|
||||||
|
|
||||||
return trayButton;
|
|
||||||
},
|
|
||||||
|
|
||||||
_addRows : function (keys, layout) {
|
|
||||||
let keyboard_row = new St.BoxLayout();
|
|
||||||
for (let i = 0; i < keys.length; ++i) {
|
|
||||||
let children = keys[i].get_children();
|
|
||||||
let right_box = new St.BoxLayout({ style_class: 'keyboard-row' });
|
|
||||||
let left_box = new St.BoxLayout({ style_class: 'keyboard-row' });
|
|
||||||
for (let j = 0; j < children.length; ++j) {
|
|
||||||
if (this._numOfHorizKeys == 0)
|
|
||||||
this._numOfHorizKeys = children.length;
|
|
||||||
let key = children[j];
|
|
||||||
let button = new Key(key, 0, 0);
|
|
||||||
|
|
||||||
if (key.align == 'right')
|
|
||||||
right_box.add(button.actor);
|
|
||||||
else
|
|
||||||
left_box.add(button.actor);
|
|
||||||
if (key.name == "Caribou_Prefs") {
|
|
||||||
key.connect('key-released', Lang.bind(this, this._onPrefsClick));
|
|
||||||
|
|
||||||
// Add new key for hiding message tray
|
|
||||||
right_box.add(this._getTrayIcon());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
keyboard_row.add(left_box, { expand: true, x_fill: false, x_align: St.Align.START });
|
|
||||||
keyboard_row.add(right_box, { expand: true, x_fill: false, x_align: St.Align.END });
|
|
||||||
}
|
|
||||||
layout.add(keyboard_row);
|
|
||||||
},
|
|
||||||
|
|
||||||
_manageTray: function () {
|
|
||||||
this.createSource();
|
|
||||||
},
|
|
||||||
|
|
||||||
_onPrefsClick: function () {
|
|
||||||
this.hide();
|
|
||||||
this._manageTray();
|
|
||||||
},
|
|
||||||
|
|
||||||
_loadRows : function (level, layout) {
|
|
||||||
let rows = level.get_rows();
|
|
||||||
for (let i = 0; i < rows.length; ++i) {
|
|
||||||
let row = rows[i];
|
|
||||||
if (this._numOfVertKeys == 0)
|
|
||||||
this._numOfVertKeys = rows.length;
|
|
||||||
this._addRows(row.get_columns(), layout);
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
_redraw: function () {
|
|
||||||
let monitor = Main.layoutManager.bottomMonitor;
|
|
||||||
let maxHeight = monitor.height / 3;
|
|
||||||
this.actor.width = monitor.width;
|
|
||||||
|
|
||||||
let layout = this._current_page;
|
|
||||||
let verticalSpacing = layout.get_theme_node().get_length('spacing');
|
|
||||||
let padding = layout.get_theme_node().get_length('padding');
|
|
||||||
|
|
||||||
let box = layout.get_children()[0].get_children()[0];
|
|
||||||
let horizontalSpacing = box.get_theme_node().get_length('spacing');
|
|
||||||
let allHorizontalSpacing = (this._numOfHorizKeys - 1) * horizontalSpacing;
|
|
||||||
let keyWidth = Math.floor((this.actor.width - allHorizontalSpacing - 2 * padding) / this._numOfHorizKeys);
|
|
||||||
|
|
||||||
let allVerticalSpacing = (this._numOfVertKeys - 1) * verticalSpacing;
|
|
||||||
let keyHeight = Math.floor((maxHeight - allVerticalSpacing - 2 * padding) / this._numOfVertKeys);
|
|
||||||
|
|
||||||
let keySize = Math.min(keyWidth, keyHeight);
|
|
||||||
this.actor.height = keySize * this._numOfVertKeys + allVerticalSpacing + 2 * padding;
|
|
||||||
|
|
||||||
let rows = this._current_page.get_children();
|
|
||||||
for (let i = 0; i < rows.length; ++i) {
|
|
||||||
let keyboard_row = rows[i];
|
|
||||||
let boxes = keyboard_row.get_children();
|
|
||||||
for (let j = 0; j < boxes.length; ++j) {
|
|
||||||
let keys = boxes[j].get_children();
|
|
||||||
for (let k = 0; k < keys.length; ++k) {
|
|
||||||
let child = keys[k];
|
|
||||||
child.width = keySize * child.key_width;
|
|
||||||
child.height = keySize;
|
|
||||||
child.draggable = this._draggable;
|
|
||||||
if (child._extended_keys) {
|
|
||||||
let extended_keys = child._extended_keys.get_children();
|
|
||||||
for (let n = 0; n < extended_keys.length; ++n) {
|
|
||||||
let extended_key = extended_keys[n];
|
|
||||||
extended_key.width = keySize;
|
|
||||||
extended_key.height = keySize;
|
|
||||||
extended_key.draggable = this._draggable;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_onLevelChanged: function () {
|
|
||||||
this._setActiveLayer();
|
|
||||||
this._redraw();
|
|
||||||
},
|
|
||||||
|
|
||||||
_onGroupChanged: function () {
|
|
||||||
this._setActiveLayer();
|
|
||||||
this._redraw();
|
|
||||||
},
|
|
||||||
|
|
||||||
_setActiveLayer: function () {
|
|
||||||
let active_group_name = this._keyboard.active_group;
|
|
||||||
let active_group = this._keyboard.get_group(active_group_name);
|
|
||||||
let active_level = active_group.active_level;
|
|
||||||
let layers = this._groups[active_group_name];
|
|
||||||
|
|
||||||
if (this._current_page != null) {
|
|
||||||
this._current_page.hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
this._current_page = layers[active_level];
|
|
||||||
this._current_page.show();
|
|
||||||
},
|
|
||||||
|
|
||||||
createSource: function () {
|
|
||||||
if (this._source == null) {
|
|
||||||
this._source = new KeyboardSource(this);
|
|
||||||
Main.messageTray.add(this._source);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
destroySource: function () {
|
|
||||||
if (this._source) {
|
|
||||||
this._source.destroy();
|
|
||||||
this._source = null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
show: function () {
|
|
||||||
this._redraw();
|
|
||||||
Main.layoutManager.showKeyboard();
|
|
||||||
},
|
|
||||||
|
|
||||||
hide: function () {
|
|
||||||
Main.layoutManager.hideKeyboard();
|
|
||||||
},
|
|
||||||
|
|
||||||
// Window placement method
|
|
||||||
_updatePosition: function (x, y) {
|
|
||||||
let primary = Main.layoutManager.primaryMonitor;
|
|
||||||
x -= this.actor.width / 2;
|
|
||||||
// Determines bottom/top centered
|
|
||||||
if (y <= primary.height / 2)
|
|
||||||
y += this.actor.height / 2;
|
|
||||||
else
|
|
||||||
y -= 3 * this.actor.height / 2;
|
|
||||||
|
|
||||||
// Accounting for monitor boundaries
|
|
||||||
if (x < primary.x)
|
|
||||||
x = primary.x;
|
|
||||||
if (x + this.actor.width > primary.width)
|
|
||||||
x = primary.width - this.actor.width;
|
|
||||||
|
|
||||||
this.actor.set_position(x, y);
|
|
||||||
},
|
|
||||||
|
|
||||||
_moveTemporarily: function () {
|
|
||||||
this._currentWindow = global.screen.get_display().focus_window;
|
|
||||||
let rect = this._currentWindow.get_outer_rect();
|
|
||||||
this._currentWindow.x = rect.x;
|
|
||||||
this._currentWindow.y = rect.y;
|
|
||||||
|
|
||||||
let newX = this._currentWindow.x;
|
|
||||||
let newY = 3 * this.actor.height / 2;
|
|
||||||
this._currentWindow.move_frame(true, newX, newY);
|
|
||||||
},
|
|
||||||
|
|
||||||
_setLocation: function (x, y) {
|
|
||||||
if (this._floating)
|
|
||||||
this._updatePosition(x, y);
|
|
||||||
else {
|
|
||||||
if (y >= 2 * this.actor.height)
|
|
||||||
this._moveTemporarily();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// D-Bus methods
|
|
||||||
Show: function() {
|
|
||||||
this.destroySource();
|
|
||||||
this.show();
|
|
||||||
},
|
|
||||||
|
|
||||||
Hide: function() {
|
|
||||||
if (this._currentWindow) {
|
|
||||||
this._currentWindow.move_frame(true, this._currentWindow.x, this._currentWindow.y);
|
|
||||||
this._currentWindow = null;
|
|
||||||
}
|
|
||||||
this.hide();
|
|
||||||
this._manageTray();
|
|
||||||
},
|
|
||||||
|
|
||||||
SetCursorLocation: function(x, y, w, h) {
|
|
||||||
this._setLocation(x, y);
|
|
||||||
},
|
|
||||||
|
|
||||||
SetEntryLocation: function(x, y, w, h) {
|
|
||||||
this._setLocation(x, y);
|
|
||||||
},
|
|
||||||
|
|
||||||
get Name() {
|
|
||||||
return 'gnome-shell';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
DBus.conformExport(Keyboard.prototype, CaribouKeyboardIface);
|
|
||||||
|
|
||||||
function KeyboardSource() {
|
|
||||||
this._init.apply(this, arguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
KeyboardSource.prototype = {
|
|
||||||
__proto__: MessageTray.Source.prototype,
|
|
||||||
|
|
||||||
_init: function(keyboard) {
|
|
||||||
this._keyboard = keyboard;
|
|
||||||
MessageTray.Source.prototype._init.call(this, _("Keyboard"));
|
|
||||||
|
|
||||||
this._setSummaryIcon(this.createNotificationIcon());
|
|
||||||
},
|
|
||||||
|
|
||||||
createNotificationIcon: function() {
|
|
||||||
return new St.Icon({ icon_name: 'input-keyboard',
|
|
||||||
icon_type: St.IconType.SYMBOLIC,
|
|
||||||
icon_size: this.ICON_SIZE });
|
|
||||||
},
|
|
||||||
|
|
||||||
handleSummaryClick: function() {
|
|
||||||
let event = Clutter.get_current_event();
|
|
||||||
if (event.type() != Clutter.EventType.BUTTON_RELEASE)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (event.get_button() != 1)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
this.open();
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
open: function() {
|
|
||||||
this._keyboard.show();
|
|
||||||
this._keyboard.destroySource();
|
|
||||||
}
|
|
||||||
};
|
|
@ -6,17 +6,8 @@ const Signals = imports.signals;
|
|||||||
const St = imports.gi.St;
|
const St = imports.gi.St;
|
||||||
|
|
||||||
const Main = imports.ui.main;
|
const Main = imports.ui.main;
|
||||||
const Meta = imports.gi.Meta;
|
|
||||||
const Panel = imports.ui.panel;
|
|
||||||
const Tweener = imports.ui.tweener;
|
const Tweener = imports.ui.tweener;
|
||||||
|
|
||||||
const State = {
|
|
||||||
HIDDEN: 0,
|
|
||||||
SHOWING: 1,
|
|
||||||
SHOWN: 2,
|
|
||||||
HIDING: 3
|
|
||||||
};
|
|
||||||
|
|
||||||
const HOT_CORNER_ACTIVATION_TIMEOUT = 0.5;
|
const HOT_CORNER_ACTIVATION_TIMEOUT = 0.5;
|
||||||
|
|
||||||
function LayoutManager() {
|
function LayoutManager() {
|
||||||
@ -30,95 +21,8 @@ LayoutManager.prototype = {
|
|||||||
this.primaryMonitor = null;
|
this.primaryMonitor = null;
|
||||||
this.primaryIndex = -1;
|
this.primaryIndex = -1;
|
||||||
this._hotCorners = [];
|
this._hotCorners = [];
|
||||||
this.bottomBox = new Clutter.Group();
|
|
||||||
this.topBox = new Clutter.Group({ clip_to_allocation: true });
|
|
||||||
this.bottomBox.add_actor(this.topBox);
|
|
||||||
|
|
||||||
global.screen.connect('monitors-changed', Lang.bind(this, this._monitorsChanged));
|
|
||||||
this._updateMonitors();
|
this._updateMonitors();
|
||||||
|
|
||||||
Main.connect('layout-initialized', Lang.bind(this, this._initChrome));
|
|
||||||
|
|
||||||
Main.connect('main-ui-initialized', Lang.bind(this, this._finishInit));
|
|
||||||
},
|
|
||||||
|
|
||||||
_initChrome: function() {
|
|
||||||
Main.chrome.addActor(this.bottomBox, { affectsStruts: false,
|
|
||||||
visibleInFullscreen: true });
|
|
||||||
},
|
|
||||||
|
|
||||||
// _updateHotCorners needs access to Main.panel
|
|
||||||
_finishInit: function() {
|
|
||||||
this._updateHotCorners();
|
|
||||||
|
|
||||||
this.topBox.height = Main.messageTray.actor.height;
|
|
||||||
this.topBox.y = - Main.messageTray.actor.height;
|
|
||||||
|
|
||||||
this._keyboardState = Main.keyboard.actor.visible ? State.SHOWN : State.HIDDEN;
|
|
||||||
this._traySummoned = true;
|
|
||||||
|
|
||||||
Main.keyboard.actor.connect('allocation-changed', Lang.bind(this, this._reposition));
|
|
||||||
},
|
|
||||||
|
|
||||||
_reposition: function () {
|
|
||||||
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function () { this._updateForKeyboard(); }));
|
|
||||||
},
|
|
||||||
|
|
||||||
_updateForKeyboard: function () {
|
|
||||||
if (Tweener.isTweening(this.bottomBox))
|
|
||||||
return;
|
|
||||||
|
|
||||||
this.topBox.y = - Main.messageTray.actor.height;
|
|
||||||
let bottom = this.bottomMonitor.y + this.bottomMonitor.height;
|
|
||||||
if (this._keyboardState == State.SHOWN)
|
|
||||||
this.bottomBox.y = bottom - Main.keyboard.actor.height;
|
|
||||||
else {
|
|
||||||
this.bottomBox.y = bottom;
|
|
||||||
this._keyboardState = State.HIDDEN;
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
updateForTray: function () {
|
|
||||||
if (this._keyboardState == State.SHOWN) {
|
|
||||||
if (this._traySummoned) {
|
|
||||||
Main.messageTray.lock();
|
|
||||||
this._traySummoned = false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Main.messageTray.unlock();
|
|
||||||
this._traySummoned = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Main.messageTray.unlock();
|
|
||||||
this._traySummoned = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
showKeyboard: function () {
|
|
||||||
let bottom = this.bottomMonitor.y + this.bottomMonitor.height;
|
|
||||||
// Keyboard height cannot be found directly since the first
|
|
||||||
// call to this method may be when Keyboard.Keyboard() has
|
|
||||||
// not returned; therefore the keyboard would be null
|
|
||||||
Tweener.addTween(this.bottomBox,
|
|
||||||
{ y: bottom - Main.keyboard.actor.height,
|
|
||||||
time: 0.5,
|
|
||||||
transition: 'easeOutQuad',
|
|
||||||
});
|
|
||||||
this._keyboardState = State.SHOWN;
|
|
||||||
this.updateForTray();
|
|
||||||
},
|
|
||||||
|
|
||||||
hideKeyboard: function () {
|
|
||||||
let bottom = this.bottomMonitor.y + this.bottomMonitor.height;
|
|
||||||
Tweener.addTween(this.bottomBox,
|
|
||||||
{ y: bottom,
|
|
||||||
time: 0.5,
|
|
||||||
transition: 'easeOutQuad'
|
|
||||||
});
|
|
||||||
this._keyboardState = State.HIDDEN;
|
|
||||||
this.updateForTray();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// This is called by Main after everything else is constructed;
|
// This is called by Main after everything else is constructed;
|
||||||
@ -153,9 +57,6 @@ LayoutManager.prototype = {
|
|||||||
}
|
}
|
||||||
this.primaryMonitor = this.monitors[this.primaryIndex];
|
this.primaryMonitor = this.monitors[this.primaryIndex];
|
||||||
this.bottomMonitor = this.monitors[this.bottomIndex];
|
this.bottomMonitor = this.monitors[this.bottomIndex];
|
||||||
|
|
||||||
this.bottomBox.set_position(0, this.bottomMonitor.y + this.bottomMonitor.height);
|
|
||||||
this.bottomBox.width = this.bottomMonitor.width;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_updateHotCorners: function() {
|
_updateHotCorners: function() {
|
||||||
|
119
js/ui/main.js
119
js/ui/main.js
@ -10,7 +10,6 @@ const Lang = imports.lang;
|
|||||||
const Mainloop = imports.mainloop;
|
const Mainloop = imports.mainloop;
|
||||||
const Meta = imports.gi.Meta;
|
const Meta = imports.gi.Meta;
|
||||||
const Shell = imports.gi.Shell;
|
const Shell = imports.gi.Shell;
|
||||||
const Signals = imports.signals;
|
|
||||||
const St = imports.gi.St;
|
const St = imports.gi.St;
|
||||||
|
|
||||||
const AutomountManager = imports.ui.automountManager;
|
const AutomountManager = imports.ui.automountManager;
|
||||||
@ -21,7 +20,6 @@ const EndSessionDialog = imports.ui.endSessionDialog;
|
|||||||
const PolkitAuthenticationAgent = imports.ui.polkitAuthenticationAgent;
|
const PolkitAuthenticationAgent = imports.ui.polkitAuthenticationAgent;
|
||||||
const Environment = imports.ui.environment;
|
const Environment = imports.ui.environment;
|
||||||
const ExtensionSystem = imports.ui.extensionSystem;
|
const ExtensionSystem = imports.ui.extensionSystem;
|
||||||
const Keyboard = imports.ui.keyboard;
|
|
||||||
const MessageTray = imports.ui.messageTray;
|
const MessageTray = imports.ui.messageTray;
|
||||||
const Overview = imports.ui.overview;
|
const Overview = imports.ui.overview;
|
||||||
const Panel = imports.ui.panel;
|
const Panel = imports.ui.panel;
|
||||||
@ -47,34 +45,32 @@ let automountManager = null;
|
|||||||
let autorunManager = null;
|
let autorunManager = null;
|
||||||
let chrome = null;
|
let chrome = null;
|
||||||
let panel = null;
|
let panel = null;
|
||||||
|
let hotCorners = [];
|
||||||
let placesManager = null;
|
let placesManager = null;
|
||||||
let overview = null;
|
let overview = null;
|
||||||
|
let runDialog = null;
|
||||||
|
let lookingGlass = null;
|
||||||
let wm = null;
|
let wm = null;
|
||||||
let messageTray = null;
|
let messageTray = null;
|
||||||
let notificationDaemon = null;
|
let notificationDaemon = null;
|
||||||
let windowAttentionHandler = null;
|
let windowAttentionHandler = null;
|
||||||
let telepathyClient = null;
|
let telepathyClient = null;
|
||||||
let ctrlAltTabManager = null;
|
let ctrlAltTabManager = null;
|
||||||
|
let recorder = null;
|
||||||
let shellDBusService = null;
|
let shellDBusService = null;
|
||||||
|
let modalCount = 0;
|
||||||
|
let modalActorFocusStack = [];
|
||||||
let uiGroup = null;
|
let uiGroup = null;
|
||||||
let magnifier = null;
|
let magnifier = null;
|
||||||
let xdndHandler = null;
|
let xdndHandler = null;
|
||||||
let statusIconDispatcher = null;
|
let statusIconDispatcher = null;
|
||||||
let keyboard = null;
|
|
||||||
let layoutManager = null;
|
let layoutManager = null;
|
||||||
|
|
||||||
let _runDialog = null;
|
|
||||||
let lookingGlass = null;
|
|
||||||
let _recorder = null;
|
|
||||||
let _modalCount = 0;
|
|
||||||
let _modalActorFocusStack = [];
|
|
||||||
let _errorLogStack = [];
|
let _errorLogStack = [];
|
||||||
let _startDate;
|
let _startDate;
|
||||||
let _defaultCssStylesheet = null;
|
let _defaultCssStylesheet = null;
|
||||||
let _cssStylesheet = null;
|
let _cssStylesheet = null;
|
||||||
|
|
||||||
const Main = this;
|
let background = null;
|
||||||
Signals.addSignalMethods(Main)
|
|
||||||
|
|
||||||
function start() {
|
function start() {
|
||||||
// Monkey patch utility functions into the global proxy;
|
// Monkey patch utility functions into the global proxy;
|
||||||
@ -136,62 +132,50 @@ function start() {
|
|||||||
global.overlay_group.reparent(uiGroup);
|
global.overlay_group.reparent(uiGroup);
|
||||||
global.stage.add_actor(uiGroup);
|
global.stage.add_actor(uiGroup);
|
||||||
|
|
||||||
// Initialize JS modules. We do this in several steps, so that
|
|
||||||
// less-fundamental modules can depend on more-fundamental ones.
|
|
||||||
|
|
||||||
// Overall layout management
|
|
||||||
layoutManager = new Layout.LayoutManager();
|
layoutManager = new Layout.LayoutManager();
|
||||||
chrome = new Chrome.Chrome();
|
|
||||||
ctrlAltTabManager = new CtrlAltTab.CtrlAltTabManager();
|
|
||||||
Main.emit('layout-initialized');
|
|
||||||
|
|
||||||
// Major UI elements; initialize overview first since both panel
|
|
||||||
// and messageTray connect to its signals
|
|
||||||
overview = new Overview.Overview();
|
|
||||||
panel = new Panel.Panel();
|
|
||||||
messageTray = new MessageTray.MessageTray();
|
|
||||||
keyboard = new Keyboard.Keyboard();
|
|
||||||
Main.emit('main-ui-initialized');
|
|
||||||
|
|
||||||
// Now the rest of the JS modules (arbitrarily in alphabetical
|
|
||||||
// order).
|
|
||||||
keyboard.init();
|
|
||||||
magnifier = new Magnifier.Magnifier();
|
|
||||||
notificationDaemon = new NotificationDaemon.NotificationDaemon();
|
|
||||||
placesManager = new PlaceDisplay.PlacesManager();
|
placesManager = new PlaceDisplay.PlacesManager();
|
||||||
statusIconDispatcher = new StatusIconDispatcher.StatusIconDispatcher();
|
|
||||||
telepathyClient = new TelepathyClient.Client();
|
|
||||||
windowAttentionHandler = new WindowAttentionHandler.WindowAttentionHandler();
|
|
||||||
wm = new WindowManager.WindowManager();
|
|
||||||
xdndHandler = new XdndHandler.XdndHandler();
|
xdndHandler = new XdndHandler.XdndHandler();
|
||||||
|
ctrlAltTabManager = new CtrlAltTab.CtrlAltTabManager();
|
||||||
|
overview = new Overview.Overview();
|
||||||
|
chrome = new Chrome.Chrome();
|
||||||
|
magnifier = new Magnifier.Magnifier();
|
||||||
|
statusIconDispatcher = new StatusIconDispatcher.StatusIconDispatcher();
|
||||||
|
panel = new Panel.Panel();
|
||||||
|
wm = new WindowManager.WindowManager();
|
||||||
|
messageTray = new MessageTray.MessageTray();
|
||||||
|
notificationDaemon = new NotificationDaemon.NotificationDaemon();
|
||||||
|
windowAttentionHandler = new WindowAttentionHandler.WindowAttentionHandler();
|
||||||
|
telepathyClient = new TelepathyClient.Client();
|
||||||
automountManager = new AutomountManager.AutomountManager();
|
automountManager = new AutomountManager.AutomountManager();
|
||||||
autorunManager = new AutorunManager.AutorunManager();
|
autorunManager = new AutorunManager.AutorunManager();
|
||||||
|
|
||||||
Main.emit('initialized');
|
layoutManager.init();
|
||||||
|
overview.init();
|
||||||
|
statusIconDispatcher.start(messageTray.actor);
|
||||||
|
|
||||||
_startDate = new Date();
|
_startDate = new Date();
|
||||||
|
|
||||||
let recorderSettings = new Gio.Settings({ schema: 'org.gnome.shell.recorder' });
|
let recorderSettings = new Gio.Settings({ schema: 'org.gnome.shell.recorder' });
|
||||||
|
|
||||||
global.screen.connect('toggle-recording', function() {
|
global.screen.connect('toggle-recording', function() {
|
||||||
if (_recorder == null) {
|
if (recorder == null) {
|
||||||
_recorder = new Shell.Recorder({ stage: global.stage });
|
recorder = new Shell.Recorder({ stage: global.stage });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_recorder.is_recording()) {
|
if (recorder.is_recording()) {
|
||||||
_recorder.pause();
|
recorder.pause();
|
||||||
} else {
|
} else {
|
||||||
// read the parameters from GSettings always in case they have changed
|
// read the parameters from GSettings always in case they have changed
|
||||||
_recorder.set_framerate(recorderSettings.get_int('framerate'));
|
recorder.set_framerate(recorderSettings.get_int('framerate'));
|
||||||
_recorder.set_filename('shell-%d%u-%c.' + recorderSettings.get_string('file-extension'));
|
recorder.set_filename('shell-%d%u-%c.' + recorderSettings.get_string('file-extension'));
|
||||||
let pipeline = recorderSettings.get_string('pipeline');
|
let pipeline = recorderSettings.get_string('pipeline');
|
||||||
|
|
||||||
if (!pipeline.match(/^\s*$/))
|
if (!pipeline.match(/^\s*$/))
|
||||||
_recorder.set_pipeline(pipeline);
|
recorder.set_pipeline(pipeline);
|
||||||
else
|
else
|
||||||
_recorder.set_pipeline(null);
|
recorder.set_pipeline(null);
|
||||||
|
|
||||||
_recorder.record();
|
recorder.record();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -207,7 +191,6 @@ function start() {
|
|||||||
ExtensionSystem.init();
|
ExtensionSystem.init();
|
||||||
ExtensionSystem.loadExtensions();
|
ExtensionSystem.loadExtensions();
|
||||||
|
|
||||||
// Initialize the panel status area now that extensions are loaded
|
|
||||||
panel.startStatusArea();
|
panel.startStatusArea();
|
||||||
panel.startupAnimation();
|
panel.startupAnimation();
|
||||||
|
|
||||||
@ -532,7 +515,7 @@ function getWindowActorsForWorkspace(workspaceIndex) {
|
|||||||
// all key events will be delivered to the stage, so ::captured-event
|
// all key events will be delivered to the stage, so ::captured-event
|
||||||
// on the stage can be used for global keybindings.)
|
// on the stage can be used for global keybindings.)
|
||||||
function _globalKeyPressHandler(actor, event) {
|
function _globalKeyPressHandler(actor, event) {
|
||||||
if (_modalCount == 0)
|
if (modalCount == 0)
|
||||||
return false;
|
return false;
|
||||||
if (event.type() != Clutter.EventType.KEY_PRESS)
|
if (event.type() != Clutter.EventType.KEY_PRESS)
|
||||||
return false;
|
return false;
|
||||||
@ -557,7 +540,7 @@ function _globalKeyPressHandler(actor, event) {
|
|||||||
|
|
||||||
// Other bindings are only available when the overview is up and
|
// Other bindings are only available when the overview is up and
|
||||||
// no modal dialog is present.
|
// no modal dialog is present.
|
||||||
if (!overview.visible || _modalCount > 1)
|
if (!overview.visible || modalCount > 1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// This isn't a Meta.KeyBindingAction yet
|
// This isn't a Meta.KeyBindingAction yet
|
||||||
@ -598,8 +581,8 @@ function _globalKeyPressHandler(actor, event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function _findModal(actor) {
|
function _findModal(actor) {
|
||||||
for (let i = 0; i < _modalActorFocusStack.length; i++) {
|
for (let i = 0; i < modalActorFocusStack.length; i++) {
|
||||||
if (_modalActorFocusStack[i].actor == actor)
|
if (modalActorFocusStack[i].actor == actor)
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
@ -629,7 +612,7 @@ function pushModal(actor, timestamp) {
|
|||||||
if (timestamp == undefined)
|
if (timestamp == undefined)
|
||||||
timestamp = global.get_current_time();
|
timestamp = global.get_current_time();
|
||||||
|
|
||||||
if (_modalCount == 0) {
|
if (modalCount == 0) {
|
||||||
if (!global.begin_modal(timestamp)) {
|
if (!global.begin_modal(timestamp)) {
|
||||||
log('pushModal: invocation of begin_modal failed');
|
log('pushModal: invocation of begin_modal failed');
|
||||||
return false;
|
return false;
|
||||||
@ -638,11 +621,11 @@ function pushModal(actor, timestamp) {
|
|||||||
|
|
||||||
global.set_stage_input_mode(Shell.StageInputMode.FULLSCREEN);
|
global.set_stage_input_mode(Shell.StageInputMode.FULLSCREEN);
|
||||||
|
|
||||||
_modalCount += 1;
|
modalCount += 1;
|
||||||
let actorDestroyId = actor.connect('destroy', function() {
|
let actorDestroyId = actor.connect('destroy', function() {
|
||||||
let index = _findModal(actor);
|
let index = _findModal(actor);
|
||||||
if (index >= 0)
|
if (index >= 0)
|
||||||
_modalActorFocusStack.splice(index, 1);
|
modalActorFocusStack.splice(index, 1);
|
||||||
});
|
});
|
||||||
let curFocus = global.stage.get_key_focus();
|
let curFocus = global.stage.get_key_focus();
|
||||||
let curFocusDestroyId;
|
let curFocusDestroyId;
|
||||||
@ -650,10 +633,10 @@ function pushModal(actor, timestamp) {
|
|||||||
curFocusDestroyId = curFocus.connect('destroy', function() {
|
curFocusDestroyId = curFocus.connect('destroy', function() {
|
||||||
let index = _findModal(actor);
|
let index = _findModal(actor);
|
||||||
if (index >= 0)
|
if (index >= 0)
|
||||||
_modalActorFocusStack[index].actor = null;
|
modalActorFocusStack[index].actor = null;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
_modalActorFocusStack.push({ actor: actor,
|
modalActorFocusStack.push({ actor: actor,
|
||||||
focus: curFocus,
|
focus: curFocus,
|
||||||
destroyId: actorDestroyId,
|
destroyId: actorDestroyId,
|
||||||
focusDestroyId: curFocusDestroyId });
|
focusDestroyId: curFocusDestroyId });
|
||||||
@ -688,28 +671,28 @@ function popModal(actor, timestamp) {
|
|||||||
throw new Error('incorrect pop');
|
throw new Error('incorrect pop');
|
||||||
}
|
}
|
||||||
|
|
||||||
_modalCount -= 1;
|
modalCount -= 1;
|
||||||
|
|
||||||
let record = _modalActorFocusStack[focusIndex];
|
let record = modalActorFocusStack[focusIndex];
|
||||||
record.actor.disconnect(record.destroyId);
|
record.actor.disconnect(record.destroyId);
|
||||||
|
|
||||||
if (focusIndex == _modalActorFocusStack.length - 1) {
|
if (focusIndex == modalActorFocusStack.length - 1) {
|
||||||
if (record.focus)
|
if (record.focus)
|
||||||
record.focus.disconnect(record.focusDestroyId);
|
record.focus.disconnect(record.focusDestroyId);
|
||||||
global.stage.set_key_focus(record.focus);
|
global.stage.set_key_focus(record.focus);
|
||||||
} else {
|
} else {
|
||||||
let t = _modalActorFocusStack[_modalActorFocusStack.length - 1];
|
let t = modalActorFocusStack[modalActorFocusStack.length - 1];
|
||||||
if (t.focus)
|
if (t.focus)
|
||||||
t.focus.disconnect(t.focusDestroyId);
|
t.focus.disconnect(t.focusDestroyId);
|
||||||
// Remove from the middle, shift the focus chain up
|
// Remove from the middle, shift the focus chain up
|
||||||
for (let i = _modalActorFocusStack.length - 1; i > focusIndex; i--) {
|
for (let i = modalActorFocusStack.length - 1; i > focusIndex; i--) {
|
||||||
_modalActorFocusStack[i].focus = _modalActorFocusStack[i - 1].focus;
|
modalActorFocusStack[i].focus = modalActorFocusStack[i - 1].focus;
|
||||||
_modalActorFocusStack[i].focusDestroyId = _modalActorFocusStack[i - 1].focusDestroyId;
|
modalActorFocusStack[i].focusDestroyId = modalActorFocusStack[i - 1].focusDestroyId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_modalActorFocusStack.splice(focusIndex, 1);
|
modalActorFocusStack.splice(focusIndex, 1);
|
||||||
|
|
||||||
if (_modalCount > 0)
|
if (modalCount > 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
global.end_modal(timestamp);
|
global.end_modal(timestamp);
|
||||||
@ -725,10 +708,10 @@ function createLookingGlass() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getRunDialog() {
|
function getRunDialog() {
|
||||||
if (_runDialog == null) {
|
if (runDialog == null) {
|
||||||
_runDialog = new RunDialog.RunDialog();
|
runDialog = new RunDialog.RunDialog();
|
||||||
}
|
}
|
||||||
return _runDialog;
|
return runDialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -68,14 +68,19 @@ function _fixMarkup(text, allowMarkup) {
|
|||||||
// Support &, ", ', < and >, escape all other
|
// Support &, ", ', < and >, escape all other
|
||||||
// occurrences of '&'.
|
// occurrences of '&'.
|
||||||
let _text = text.replace(/&(?!amp;|quot;|apos;|lt;|gt;)/g, '&');
|
let _text = text.replace(/&(?!amp;|quot;|apos;|lt;|gt;)/g, '&');
|
||||||
|
|
||||||
// Support <b>, <i>, and <u>, escape anything else
|
// Support <b>, <i>, and <u>, escape anything else
|
||||||
// so it displays as raw markup.
|
// so it displays as raw markup.
|
||||||
return _text.replace(/<(\/?[^biu]>|[^>\/][^>])/g, '<$1');
|
_text = _text.replace(/<(?!\/?[biu]>)/g, '<');
|
||||||
} else {
|
|
||||||
// Escape everything
|
try {
|
||||||
let _text = text.replace(/&/g, '&');
|
Pango.parse_markup(_text, -1, '');
|
||||||
return _text.replace(/</g, '<');
|
return _text;
|
||||||
|
} catch (e) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// !allowMarkup, or invalid markup
|
||||||
|
return GLib.markup_escape_text(text, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
function URLHighlighter(text, lineWrap, allowMarkup) {
|
function URLHighlighter(text, lineWrap, allowMarkup) {
|
||||||
@ -1301,9 +1306,9 @@ MessageTray.prototype = {
|
|||||||
this._focusGrabber.connect('focus-grabbed', Lang.bind(this,
|
this._focusGrabber.connect('focus-grabbed', Lang.bind(this,
|
||||||
function() {
|
function() {
|
||||||
if (this._summaryBoxPointer.bin.child)
|
if (this._summaryBoxPointer.bin.child)
|
||||||
this.lock();
|
this._lock();
|
||||||
}));
|
}));
|
||||||
this._focusGrabber.connect('focus-ungrabbed', Lang.bind(this, this.unlock));
|
this._focusGrabber.connect('focus-ungrabbed', Lang.bind(this, this._unlock));
|
||||||
this._focusGrabber.connect('button-pressed', Lang.bind(this,
|
this._focusGrabber.connect('button-pressed', Lang.bind(this,
|
||||||
function(focusGrabber, source) {
|
function(focusGrabber, source) {
|
||||||
if (this._clickedSummaryItem && !this._clickedSummaryItem.actor.contains(source))
|
if (this._clickedSummaryItem && !this._clickedSummaryItem.actor.contains(source))
|
||||||
@ -1313,7 +1318,7 @@ MessageTray.prototype = {
|
|||||||
this._focusGrabber.connect('escape-pressed', Lang.bind(this, this._escapeTray));
|
this._focusGrabber.connect('escape-pressed', Lang.bind(this, this._escapeTray));
|
||||||
|
|
||||||
this._trayState = State.HIDDEN;
|
this._trayState = State.HIDDEN;
|
||||||
this._locked = 0;
|
this._locked = false;
|
||||||
this._useLongerTrayLeftTimeout = false;
|
this._useLongerTrayLeftTimeout = false;
|
||||||
this._trayLeftTimeoutId = 0;
|
this._trayLeftTimeoutId = 0;
|
||||||
this._pointerInTray = false;
|
this._pointerInTray = false;
|
||||||
@ -1329,9 +1334,9 @@ MessageTray.prototype = {
|
|||||||
this._notificationRemoved = false;
|
this._notificationRemoved = false;
|
||||||
this._reNotifyAfterHideNotification = null;
|
this._reNotifyAfterHideNotification = null;
|
||||||
|
|
||||||
Main.layoutManager.topBox.add_actor(this.actor);
|
Main.chrome.addActor(this.actor, { affectsStruts: false,
|
||||||
|
visibleInFullscreen: true });
|
||||||
Main.chrome.trackActor(this._notificationBin);
|
Main.chrome.trackActor(this._notificationBin);
|
||||||
Main.chrome.trackActor(this._summaryBin);
|
|
||||||
Main.chrome.trackActor(this._summaryBoxPointer.actor);
|
Main.chrome.trackActor(this._summaryBoxPointer.actor);
|
||||||
|
|
||||||
Main.layoutManager.connect('monitors-changed', Lang.bind(this, this._setSizePosition));
|
Main.layoutManager.connect('monitors-changed', Lang.bind(this, this._setSizePosition));
|
||||||
@ -1341,9 +1346,9 @@ MessageTray.prototype = {
|
|||||||
Main.overview.connect('showing', Lang.bind(this,
|
Main.overview.connect('showing', Lang.bind(this,
|
||||||
function() {
|
function() {
|
||||||
this._overviewVisible = true;
|
this._overviewVisible = true;
|
||||||
if (this._locked > 0) {
|
if (this._locked) {
|
||||||
this._unsetClickedSummaryItem();
|
this._unsetClickedSummaryItem();
|
||||||
this.unlock();
|
this._unlock();
|
||||||
} else {
|
} else {
|
||||||
this._updateState();
|
this._updateState();
|
||||||
}
|
}
|
||||||
@ -1351,9 +1356,9 @@ MessageTray.prototype = {
|
|||||||
Main.overview.connect('hiding', Lang.bind(this,
|
Main.overview.connect('hiding', Lang.bind(this,
|
||||||
function() {
|
function() {
|
||||||
this._overviewVisible = false;
|
this._overviewVisible = false;
|
||||||
if (this._locked > 0) {
|
if (this._locked) {
|
||||||
this._unsetClickedSummaryItem();
|
this._unsetClickedSummaryItem();
|
||||||
this.unlock();
|
this._unlock();
|
||||||
} else {
|
} else {
|
||||||
this._updateState();
|
this._updateState();
|
||||||
}
|
}
|
||||||
@ -1372,7 +1377,7 @@ MessageTray.prototype = {
|
|||||||
_setSizePosition: function() {
|
_setSizePosition: function() {
|
||||||
let monitor = Main.layoutManager.bottomMonitor;
|
let monitor = Main.layoutManager.bottomMonitor;
|
||||||
this.actor.x = monitor.x;
|
this.actor.x = monitor.x;
|
||||||
this.actor.y = -1;
|
this.actor.y = monitor.y + monitor.height - 1;
|
||||||
this.actor.width = monitor.width;
|
this.actor.width = monitor.width;
|
||||||
this._notificationBin.x = 0;
|
this._notificationBin.x = 0;
|
||||||
this._notificationBin.width = monitor.width;
|
this._notificationBin.width = monitor.width;
|
||||||
@ -1524,16 +1529,15 @@ MessageTray.prototype = {
|
|||||||
this._notificationQueue.splice(index, 1);
|
this._notificationQueue.splice(index, 1);
|
||||||
},
|
},
|
||||||
|
|
||||||
lock: function() {
|
_lock: function() {
|
||||||
this._locked += 1;
|
this._locked = true;
|
||||||
this._updateState();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
unlock: function() {
|
_unlock: function() {
|
||||||
if (this._locked > 0)
|
if (!this._locked)
|
||||||
this._locked -= 1;
|
return;
|
||||||
this._pointerInSummary = false;
|
this._locked = false;
|
||||||
this._pointerInTray = false;
|
this._pointerInTray = this.actor.hover && !this._summaryBoxPointer.bin.hover;
|
||||||
this._updateState();
|
this._updateState();
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1817,7 +1821,7 @@ MessageTray.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
_escapeTray: function() {
|
_escapeTray: function() {
|
||||||
this.unlock();
|
this._unlock();
|
||||||
this._pointerInTray = false;
|
this._pointerInTray = false;
|
||||||
this._pointerInSummary = false;
|
this._pointerInSummary = false;
|
||||||
this._updateNotificationTimeout(0);
|
this._updateNotificationTimeout(0);
|
||||||
@ -1835,7 +1839,7 @@ MessageTray.prototype = {
|
|||||||
let notificationsPending = this._notificationQueue.length > 0 && (!this._busy || notificationUrgent);
|
let notificationsPending = this._notificationQueue.length > 0 && (!this._busy || notificationUrgent);
|
||||||
let notificationPinned = this._pointerInTray && !this._pointerInSummary && !this._notificationRemoved;
|
let notificationPinned = this._pointerInTray && !this._pointerInSummary && !this._notificationRemoved;
|
||||||
let notificationExpanded = this._notificationBin.y < 0;
|
let notificationExpanded = this._notificationBin.y < 0;
|
||||||
let notificationExpired = (this._notificationTimeoutId == 0 && !(this._notification && this._notification.urgency == Urgency.CRITICAL) && !this._pointerInTray && (this._locked == 0)) || this._notificationRemoved;
|
let notificationExpired = (this._notificationTimeoutId == 0 && !(this._notification && this._notification.urgency == Urgency.CRITICAL) && !this._pointerInTray && !this._locked) || this._notificationRemoved;
|
||||||
let canShowNotification = notificationsPending && this._summaryState == State.HIDDEN;
|
let canShowNotification = notificationsPending && this._summaryState == State.HIDDEN;
|
||||||
|
|
||||||
if (this._notificationState == State.HIDDEN) {
|
if (this._notificationState == State.HIDDEN) {
|
||||||
@ -1851,17 +1855,17 @@ MessageTray.prototype = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Summary
|
// Summary
|
||||||
let summarySummoned = this._pointerInSummary || this._overviewVisible || (this._locked > 0);
|
let summarySummoned = this._pointerInSummary || this._overviewVisible;
|
||||||
let summaryPinned = this._summaryTimeoutId != 0 || this._pointerInTray || summarySummoned;
|
let summaryPinned = this._summaryTimeoutId != 0 || this._pointerInTray || summarySummoned || this._locked;
|
||||||
let summaryHovered = this._pointerInTray || this._pointerInSummary;
|
let summaryHovered = this._pointerInTray || this._pointerInSummary;
|
||||||
let summaryVisibleWithNoHover = (this._overviewVisible || this._locked > 0) && !summaryHovered;
|
let summaryVisibleWithNoHover = (this._overviewVisible || this._locked) && !summaryHovered;
|
||||||
let summaryNotificationIsForExpandedSummaryItem = (this._clickedSummaryItem == this._expandedSummaryItem);
|
let summaryNotificationIsForExpandedSummaryItem = (this._clickedSummaryItem == this._expandedSummaryItem);
|
||||||
|
|
||||||
let notificationsVisible = (this._notificationState == State.SHOWING ||
|
let notificationsVisible = (this._notificationState == State.SHOWING ||
|
||||||
this._notificationState == State.SHOWN);
|
this._notificationState == State.SHOWN);
|
||||||
let notificationsDone = !notificationsVisible && !notificationsPending;
|
let notificationsDone = !notificationsVisible && !notificationsPending;
|
||||||
|
|
||||||
let summaryOptionalInOverview = this._overviewVisible && (this._locked == 0) && !summaryHovered;
|
let summaryOptionalInOverview = this._overviewVisible && !this._locked && !summaryHovered;
|
||||||
let mustHideSummary = (notificationsPending && (notificationUrgent || summaryOptionalInOverview))
|
let mustHideSummary = (notificationsPending && (notificationUrgent || summaryOptionalInOverview))
|
||||||
|| notificationsVisible;
|
|| notificationsVisible;
|
||||||
|
|
||||||
@ -1945,16 +1949,18 @@ MessageTray.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
_showTray: function() {
|
_showTray: function() {
|
||||||
|
let monitor = Main.layoutManager.bottomMonitor;
|
||||||
this._tween(this.actor, '_trayState', State.SHOWN,
|
this._tween(this.actor, '_trayState', State.SHOWN,
|
||||||
{ y: 0,
|
{ y: monitor.y + monitor.height - this.actor.height,
|
||||||
time: ANIMATION_TIME,
|
time: ANIMATION_TIME,
|
||||||
transition: 'easeOutQuad'
|
transition: 'easeOutQuad'
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
_hideTray: function() {
|
_hideTray: function() {
|
||||||
|
let monitor = Main.layoutManager.bottomMonitor;
|
||||||
this._tween(this.actor, '_trayState', State.HIDDEN,
|
this._tween(this.actor, '_trayState', State.HIDDEN,
|
||||||
{ y: Main.layoutManager.topBox.height - 1,
|
{ y: monitor.y + monitor.height - 1,
|
||||||
time: ANIMATION_TIME,
|
time: ANIMATION_TIME,
|
||||||
transition: 'easeOutQuad'
|
transition: 'easeOutQuad'
|
||||||
});
|
});
|
||||||
|
@ -97,10 +97,8 @@ NotificationDaemon.prototype = {
|
|||||||
this._notifications = {};
|
this._notifications = {};
|
||||||
this._busProxy = new Bus();
|
this._busProxy = new Bus();
|
||||||
|
|
||||||
Main.connect('initialized', Lang.bind(this, function() {
|
Main.statusIconDispatcher.connect('message-icon-added', Lang.bind(this, this._onTrayIconAdded));
|
||||||
Main.statusIconDispatcher.connect('message-icon-added', Lang.bind(this, this._onTrayIconAdded));
|
Main.statusIconDispatcher.connect('message-icon-removed', Lang.bind(this, this._onTrayIconRemoved));
|
||||||
Main.statusIconDispatcher.connect('message-icon-removed', Lang.bind(this, this._onTrayIconRemoved));
|
|
||||||
}));
|
|
||||||
|
|
||||||
Shell.WindowTracker.get_default().connect('notify::focus-app',
|
Shell.WindowTracker.get_default().connect('notify::focus-app',
|
||||||
Lang.bind(this, this._onFocusAppChanged));
|
Lang.bind(this, this._onFocusAppChanged));
|
||||||
@ -463,9 +461,11 @@ Source.prototype = {
|
|||||||
|
|
||||||
_onNameVanished: function() {
|
_onNameVanished: function() {
|
||||||
// Destroy the notification source when its sender is removed from DBus.
|
// Destroy the notification source when its sender is removed from DBus.
|
||||||
|
// Only do so if this.app is set to avoid removing "notify-send" sources, senders
|
||||||
|
// of which аre removed from DBus immediately.
|
||||||
// Sender being removed from DBus would normally result in a tray icon being removed,
|
// Sender being removed from DBus would normally result in a tray icon being removed,
|
||||||
// so allow the code path that handles the tray icon being removed to handle that case.
|
// so allow the code path that handles the tray icon being removed to handle that case.
|
||||||
if (!this.trayIcon)
|
if (!this.trayIcon && this.app)
|
||||||
this.destroy();
|
this.destroy();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -153,18 +153,6 @@ Overview.prototype = {
|
|||||||
|
|
||||||
this._coverPane.hide();
|
this._coverPane.hide();
|
||||||
|
|
||||||
this._windowSwitchTimeoutId = 0;
|
|
||||||
this._windowSwitchTimestamp = 0;
|
|
||||||
this._lastActiveWorkspaceIndex = -1;
|
|
||||||
this._lastHoveredWindow = null;
|
|
||||||
this._needsFakePointerEvent = false;
|
|
||||||
|
|
||||||
this.workspaces = null;
|
|
||||||
|
|
||||||
Main.connect('initialized', Lang.bind(this, this._finishInit));
|
|
||||||
},
|
|
||||||
|
|
||||||
_finishInit: function() {
|
|
||||||
// XDND
|
// XDND
|
||||||
this._dragMonitor = {
|
this._dragMonitor = {
|
||||||
dragMotion: Lang.bind(this, this._onDragMotion)
|
dragMotion: Lang.bind(this, this._onDragMotion)
|
||||||
@ -173,11 +161,22 @@ Overview.prototype = {
|
|||||||
Main.xdndHandler.connect('drag-begin', Lang.bind(this, this._onDragBegin));
|
Main.xdndHandler.connect('drag-begin', Lang.bind(this, this._onDragBegin));
|
||||||
Main.xdndHandler.connect('drag-end', Lang.bind(this, this._onDragEnd));
|
Main.xdndHandler.connect('drag-end', Lang.bind(this, this._onDragEnd));
|
||||||
|
|
||||||
|
this._windowSwitchTimeoutId = 0;
|
||||||
|
this._windowSwitchTimestamp = 0;
|
||||||
|
this._lastActiveWorkspaceIndex = -1;
|
||||||
|
this._lastHoveredWindow = null;
|
||||||
|
this._needsFakePointerEvent = false;
|
||||||
|
|
||||||
|
this.workspaces = null;
|
||||||
|
},
|
||||||
|
|
||||||
|
// The members we construct that are implemented in JS might
|
||||||
|
// want to access the overview as Main.overview to connect
|
||||||
|
// signal handlers and so forth. So we create them after
|
||||||
|
// construction in this init() method.
|
||||||
|
init: function() {
|
||||||
this.shellInfo = new ShellInfo();
|
this.shellInfo = new ShellInfo();
|
||||||
|
|
||||||
// The members we construct that are implemented in JS might
|
|
||||||
// want to access the overview as Main.overview to connect
|
|
||||||
// signal handlers and so forth. So we create them here.
|
|
||||||
this.viewSelector = new ViewSelector.ViewSelector();
|
this.viewSelector = new ViewSelector.ViewSelector();
|
||||||
this._group.add_actor(this.viewSelector.actor);
|
this._group.add_actor(this.viewSelector.actor);
|
||||||
|
|
||||||
@ -450,16 +449,19 @@ Overview.prototype = {
|
|||||||
let primary = Main.layoutManager.primaryMonitor;
|
let primary = Main.layoutManager.primaryMonitor;
|
||||||
let rtl = (St.Widget.get_default_direction () == St.TextDirection.RTL);
|
let rtl = (St.Widget.get_default_direction () == St.TextDirection.RTL);
|
||||||
|
|
||||||
|
let contentY = Main.panel.actor.height;
|
||||||
|
let contentHeight = primary.height - contentY - Main.messageTray.actor.height;
|
||||||
|
|
||||||
this._group.set_position(primary.x, primary.y);
|
this._group.set_position(primary.x, primary.y);
|
||||||
this._group.set_size(primary.width, primary.height);
|
this._group.set_size(primary.width, primary.height);
|
||||||
|
|
||||||
this._coverPane.set_position(primary.x, primary.y);
|
this._coverPane.set_position(0, contentY);
|
||||||
this._coverPane.set_size(primary.width, primary.height);
|
this._coverPane.set_size(primary.width, contentHeight);
|
||||||
|
|
||||||
let dashWidth = Math.round(DASH_SPLIT_FRACTION * primary.width);
|
let dashWidth = Math.round(DASH_SPLIT_FRACTION * primary.width);
|
||||||
let viewWidth = primary.width - dashWidth - this._spacing;
|
let viewWidth = primary.width - dashWidth - this._spacing;
|
||||||
let viewHeight = primary.height - 2 * this._spacing;
|
let viewHeight = contentHeight - 2 * this._spacing;
|
||||||
let viewY = primary.y + this._spacing;
|
let viewY = contentY + this._spacing;
|
||||||
let viewX = rtl ? 0 : dashWidth + this._spacing;
|
let viewX = rtl ? 0 : dashWidth + this._spacing;
|
||||||
|
|
||||||
// Set the dash's x position - y is handled by a constraint
|
// Set the dash's x position - y is handled by a constraint
|
||||||
|
@ -939,6 +939,9 @@ Panel.prototype = {
|
|||||||
corner.actor.set_style_pseudo_class(pseudoClass);
|
corner.actor.set_style_pseudo_class(pseudoClass);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
Main.statusIconDispatcher.connect('status-icon-added', Lang.bind(this, this._onTrayIconAdded));
|
||||||
|
Main.statusIconDispatcher.connect('status-icon-removed', Lang.bind(this, this._onTrayIconRemoved));
|
||||||
|
|
||||||
Main.chrome.addActor(this.actor);
|
Main.chrome.addActor(this.actor);
|
||||||
Main.chrome.addActor(this._leftCorner.actor, { affectsStruts: false,
|
Main.chrome.addActor(this._leftCorner.actor, { affectsStruts: false,
|
||||||
affectsInputRegion: false });
|
affectsInputRegion: false });
|
||||||
@ -967,11 +970,8 @@ Panel.prototype = {
|
|||||||
this._statusArea[role] = indicator;
|
this._statusArea[role] = indicator;
|
||||||
}
|
}
|
||||||
|
|
||||||
Main.statusIconDispatcher.connect('status-icon-added', Lang.bind(this, this._onTrayIconAdded));
|
|
||||||
Main.statusIconDispatcher.connect('status-icon-removed', Lang.bind(this, this._onTrayIconRemoved));
|
|
||||||
|
|
||||||
// PopupMenuManager depends on menus being added in order for
|
// PopupMenuManager depends on menus being added in order for
|
||||||
// keyboard navigation, so we couldn't add this before
|
// keyboard navigation
|
||||||
this._menus.addMenu(this._userMenu.menu);
|
this._menus.addMenu(this._userMenu.menu);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -40,8 +40,6 @@ const KEY_TEXT_SCALING_FACTOR = 'text-scaling-factor';
|
|||||||
|
|
||||||
const HIGH_CONTRAST_THEME = 'HighContrast';
|
const HIGH_CONTRAST_THEME = 'HighContrast';
|
||||||
|
|
||||||
const KEYBOARD_SCHEMA = 'org.gnome.shell.keyboard'
|
|
||||||
|
|
||||||
function ATIndicator() {
|
function ATIndicator() {
|
||||||
this._init.apply(this, arguments);
|
this._init.apply(this, arguments);
|
||||||
}
|
}
|
||||||
@ -70,9 +68,9 @@ ATIndicator.prototype = {
|
|||||||
// 'screen-reader-enabled');
|
// 'screen-reader-enabled');
|
||||||
// this.menu.addMenuItem(screenReader);
|
// this.menu.addMenuItem(screenReader);
|
||||||
|
|
||||||
let screenKeyboard = this._buildItem(_("Screen Keyboard"), KEYBOARD_SCHEMA,
|
// let screenKeyboard = this._buildItem(_("Screen Keyboard"), APPLICATIONS_SCHEMA,
|
||||||
'show-keyboard');
|
// 'screen-keyboard-enabled');
|
||||||
this.menu.addMenuItem(screenKeyboard);
|
// this.menu.addMenuItem(screenKeyboard);
|
||||||
|
|
||||||
let visualBell = this._buildItemGConf(_("Visual Alerts"), client, KEY_VISUAL_BELL);
|
let visualBell = this._buildItemGConf(_("Visual Alerts"), client, KEY_VISUAL_BELL);
|
||||||
this.menu.addMenuItem(visualBell);
|
this.menu.addMenuItem(visualBell);
|
||||||
|
@ -4,7 +4,6 @@ const Lang = imports.lang;
|
|||||||
const Shell = imports.gi.Shell;
|
const Shell = imports.gi.Shell;
|
||||||
const Signals = imports.signals;
|
const Signals = imports.signals;
|
||||||
|
|
||||||
const Main = imports.ui.main;
|
|
||||||
const MessageTray = imports.ui.messageTray;
|
const MessageTray = imports.ui.messageTray;
|
||||||
const NotificationDaemon = imports.ui.notificationDaemon;
|
const NotificationDaemon = imports.ui.notificationDaemon;
|
||||||
const Util = imports.misc.util;
|
const Util = imports.misc.util;
|
||||||
@ -39,10 +38,10 @@ StatusIconDispatcher.prototype = {
|
|||||||
// status icons
|
// status icons
|
||||||
// http://bugzilla.gnome.org/show_bug.cgi=id=621382
|
// http://bugzilla.gnome.org/show_bug.cgi=id=621382
|
||||||
Util.killall('indicator-application-service');
|
Util.killall('indicator-application-service');
|
||||||
|
},
|
||||||
|
|
||||||
Main.connect('initialized', Lang.bind(this, function() {
|
start: function(themeWidget) {
|
||||||
this._traymanager.manage_stage(global.stage, Main.messageTray.actor);
|
this._traymanager.manage_stage(global.stage, themeWidget);
|
||||||
}));
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_onTrayIconAdded: function(o, icon) {
|
_onTrayIconAdded: function(o, icon) {
|
||||||
|
@ -551,6 +551,7 @@ WorkspacesDisplay.prototype = {
|
|||||||
Lang.bind(this, this._onScrollEvent));
|
Lang.bind(this, this._onScrollEvent));
|
||||||
|
|
||||||
this._monitorIndex = Main.layoutManager.primaryIndex;
|
this._monitorIndex = Main.layoutManager.primaryIndex;
|
||||||
|
this._monitor = Main.layoutManager.monitors[this._monitorIndex];
|
||||||
|
|
||||||
this._thumbnailsBox = new WorkspaceThumbnail.ThumbnailsBox();
|
this._thumbnailsBox = new WorkspaceThumbnail.ThumbnailsBox();
|
||||||
controls.add_actor(this._thumbnailsBox.actor);
|
controls.add_actor(this._thumbnailsBox.actor);
|
||||||
|
@ -28,6 +28,7 @@ CLEANFILES += $(service_DATA)
|
|||||||
CLEANFILES += $(gir_DATA) $(typelib_DATA)
|
CLEANFILES += $(gir_DATA) $(typelib_DATA)
|
||||||
|
|
||||||
bin_SCRIPTS += gnome-shell-extension-tool
|
bin_SCRIPTS += gnome-shell-extension-tool
|
||||||
|
EXTRA_DIST += gnome-shell-extension-tool.in
|
||||||
bin_PROGRAMS = gnome-shell-real
|
bin_PROGRAMS = gnome-shell-real
|
||||||
|
|
||||||
if USE_JHBUILD_WRAPPER_SCRIPT
|
if USE_JHBUILD_WRAPPER_SCRIPT
|
||||||
@ -36,6 +37,7 @@ bin_SCRIPTS += gnome-shell-jhbuild
|
|||||||
else
|
else
|
||||||
gnome_shell = gnome-shell-real
|
gnome_shell = gnome-shell-real
|
||||||
endif
|
endif
|
||||||
|
EXTRA_DIST += gnome-shell-jhbuild.in
|
||||||
|
|
||||||
noinst_DATA = gnome-shell
|
noinst_DATA = gnome-shell
|
||||||
gnome-shell: $(gnome_shell) Makefile
|
gnome-shell: $(gnome_shell) Makefile
|
||||||
@ -65,7 +67,6 @@ gnome-shell-extension-tool: gnome-shell-extension-tool.in Makefile
|
|||||||
$(AM_V_GEN) sed $(generated_script_substitutions) $< > $@.tmp && mv $@.tmp $@ && chmod a+x $@
|
$(AM_V_GEN) sed $(generated_script_substitutions) $< > $@.tmp && mv $@.tmp $@ && chmod a+x $@
|
||||||
|
|
||||||
CLEANFILES += gnome-shell $(bin_SCRIPTS)
|
CLEANFILES += gnome-shell $(bin_SCRIPTS)
|
||||||
EXTRA_DIST += $(bin_SCRIPTS:=.in)
|
|
||||||
|
|
||||||
include Makefile-gdmuser.am
|
include Makefile-gdmuser.am
|
||||||
include Makefile-st.am
|
include Makefile-st.am
|
||||||
|
@ -32,18 +32,17 @@
|
|||||||
|
|
||||||
#include <clutter/x11/clutter-x11.h>
|
#include <clutter/x11/clutter-x11.h>
|
||||||
#include <gdk/gdkx.h>
|
#include <gdk/gdkx.h>
|
||||||
|
#include <girepository.h>
|
||||||
#include <gjs/gjs.h>
|
#include <gjs/gjs.h>
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
#include "shell-global.h"
|
#include "shell-global.h"
|
||||||
#include "shell-global-private.h"
|
#include "shell-global-private.h"
|
||||||
|
|
||||||
static char **include_path = NULL;
|
|
||||||
static char *command = NULL;
|
static char *command = NULL;
|
||||||
|
|
||||||
static GOptionEntry entries[] = {
|
static GOptionEntry entries[] = {
|
||||||
{ "command", 'c', 0, G_OPTION_ARG_STRING, &command, "Program passed in as a string", "COMMAND" },
|
{ "command", 'c', 0, G_OPTION_ARG_STRING, &command, "Program passed in as a string", "COMMAND" },
|
||||||
{ "include-path", 'I', 0, G_OPTION_ARG_STRING_ARRAY, &include_path, "Add the directory DIR to the list of directories to search for js files.", "DIR" },
|
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -131,6 +130,14 @@ main(int argc, char **argv)
|
|||||||
clutter_stage_set_title (CLUTTER_STAGE (stage), title);
|
clutter_stage_set_title (CLUTTER_STAGE (stage), title);
|
||||||
g_free (title);
|
g_free (title);
|
||||||
|
|
||||||
|
#if HAVE_BLUETOOTH
|
||||||
|
/* The module imports are all so intertwined that if the test
|
||||||
|
* imports anything in js/ui, it will probably eventually end up
|
||||||
|
* pulling in ui/status/bluetooth.js. So we need this.
|
||||||
|
*/
|
||||||
|
g_irepository_prepend_search_path (BLUETOOTH_DIR);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* evaluate the script */
|
/* evaluate the script */
|
||||||
error = NULL;
|
error = NULL;
|
||||||
if (!gjs_context_eval (js_context, script, len,
|
if (!gjs_context_eval (js_context, script, len,
|
||||||
|
@ -18,7 +18,8 @@ TEST_JS = \
|
|||||||
testcommon/border-image.png \
|
testcommon/border-image.png \
|
||||||
testcommon/face-plain.png \
|
testcommon/face-plain.png \
|
||||||
testcommon/ui.js \
|
testcommon/ui.js \
|
||||||
unit/format.js
|
unit/format.js \
|
||||||
|
unit/markup.js
|
||||||
EXTRA_DIST += $(TEST_JS)
|
EXTRA_DIST += $(TEST_JS)
|
||||||
|
|
||||||
TEST_MISC = \
|
TEST_MISC = \
|
||||||
@ -28,6 +29,7 @@ EXTRA_DIST += $(TEST_MISC)
|
|||||||
run-test.sh: run-test.sh.in
|
run-test.sh: run-test.sh.in
|
||||||
$(AM_V_GEN) sed \
|
$(AM_V_GEN) sed \
|
||||||
-e "s|@MUTTER_TYPELIB_DIR[@]|$(MUTTER_TYPELIB_DIR)|" \
|
-e "s|@MUTTER_TYPELIB_DIR[@]|$(MUTTER_TYPELIB_DIR)|" \
|
||||||
|
-e "s|@JHBUILD_TYPELIBDIR[@]|$(JHBUILD_TYPELIBDIR)|" \
|
||||||
-e "s|@srcdir[@]|$(srcdir)|" \
|
-e "s|@srcdir[@]|$(srcdir)|" \
|
||||||
$< > $@ && chmod a+x $@
|
$< > $@ && chmod a+x $@
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ builddir=`cd $builddir && pwd`
|
|||||||
srcdir=$builddir/@srcdir@
|
srcdir=$builddir/@srcdir@
|
||||||
srcdir=`cd $srcdir && pwd`
|
srcdir=`cd $srcdir && pwd`
|
||||||
|
|
||||||
GI_TYPELIB_PATH="@MUTTER_TYPELIB_DIR@:$builddir/../src"
|
GI_TYPELIB_PATH="$GI_TYPELIB_PATH${GI_TYPELIB_PATH:+:}@MUTTER_TYPELIB_DIR@:@JHBUILD_TYPELIBDIR@:$builddir/../src"
|
||||||
GJS_PATH="$srcdir:$srcdir/../js"
|
GJS_PATH="$srcdir:$srcdir/../js"
|
||||||
GJS_DEBUG_OUTPUT=stderr
|
GJS_DEBUG_OUTPUT=stderr
|
||||||
$verbose || GJS_DEBUG_TOPICS="JS ERROR;JS LOG"
|
$verbose || GJS_DEBUG_TOPICS="JS ERROR;JS LOG"
|
||||||
|
142
tests/unit/markup.js
Normal file
142
tests/unit/markup.js
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
|
// Test cases for MessageTray markup parsing
|
||||||
|
|
||||||
|
const JsUnit = imports.jsUnit;
|
||||||
|
const Pango = imports.gi.Pango;
|
||||||
|
|
||||||
|
const Environment = imports.ui.environment;
|
||||||
|
Environment.init();
|
||||||
|
|
||||||
|
const MessageTray = imports.ui.messageTray;
|
||||||
|
|
||||||
|
// Assert that @input, assumed to be markup, gets "fixed" to @output,
|
||||||
|
// which is valid markup. If @output is null, @input is expected to
|
||||||
|
// convert to itself
|
||||||
|
function assertConverts(input, output) {
|
||||||
|
if (!output)
|
||||||
|
output = input;
|
||||||
|
let fixed = MessageTray._fixMarkup(input, true);
|
||||||
|
JsUnit.assertEquals(output, fixed);
|
||||||
|
|
||||||
|
let parsed = false;
|
||||||
|
try {
|
||||||
|
Pango.parse_markup(fixed, -1, '');
|
||||||
|
parsed = true;
|
||||||
|
} catch (e) {}
|
||||||
|
JsUnit.assertEquals(true, parsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assert that @input, assumed to be plain text, gets escaped to @output,
|
||||||
|
// which is valid markup.
|
||||||
|
function assertEscapes(input, output) {
|
||||||
|
let fixed = MessageTray._fixMarkup(input, false);
|
||||||
|
JsUnit.assertEquals(output, fixed);
|
||||||
|
|
||||||
|
let parsed = false;
|
||||||
|
try {
|
||||||
|
Pango.parse_markup(fixed, -1, '');
|
||||||
|
parsed = true;
|
||||||
|
} catch (e) {}
|
||||||
|
JsUnit.assertEquals(true, parsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// CORRECT MARKUP
|
||||||
|
|
||||||
|
assertConverts('foo');
|
||||||
|
assertEscapes('foo', 'foo');
|
||||||
|
|
||||||
|
assertConverts('<b>foo</b>');
|
||||||
|
assertEscapes('<b>foo</b>', '<b>foo</b>');
|
||||||
|
|
||||||
|
assertConverts('something <i>foo</i>');
|
||||||
|
assertEscapes('something <i>foo</i>', 'something <i>foo</i>');
|
||||||
|
|
||||||
|
assertConverts('<u>foo</u> something');
|
||||||
|
assertEscapes('<u>foo</u> something', '<u>foo</u> something');
|
||||||
|
|
||||||
|
assertConverts('<b>bold</b> <i>italic <u>and underlined</u></i>');
|
||||||
|
assertEscapes('<b>bold</b> <i>italic <u>and underlined</u></i>', '<b>bold</b> <i>italic <u>and underlined</u></i>');
|
||||||
|
|
||||||
|
assertConverts('this & that');
|
||||||
|
assertEscapes('this & that', 'this &amp; that');
|
||||||
|
|
||||||
|
assertConverts('this < that');
|
||||||
|
assertEscapes('this < that', 'this &lt; that');
|
||||||
|
|
||||||
|
assertConverts('this < that > the other');
|
||||||
|
assertEscapes('this < that > the other', 'this &lt; that &gt; the other');
|
||||||
|
|
||||||
|
assertConverts('this <<i>that</i>>');
|
||||||
|
assertEscapes('this <<i>that</i>>', 'this &lt;<i>that</i>&gt;');
|
||||||
|
|
||||||
|
assertConverts('<b>this</b> > <i>that</i>');
|
||||||
|
assertEscapes('<b>this</b> > <i>that</i>', '<b>this</b> > <i>that</i>');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// PARTIALLY CORRECT MARKUP
|
||||||
|
// correct bits are kept, incorrect bits are escaped
|
||||||
|
|
||||||
|
// unrecognized entity
|
||||||
|
assertConverts('<b>smile</b> ☺!', '<b>smile</b> &#9786;!');
|
||||||
|
assertEscapes('<b>smile</b> ☺!', '<b>smile</b> &#9786;!');
|
||||||
|
|
||||||
|
// stray '&'; this is really a bug, but it's easier to do it this way
|
||||||
|
assertConverts('<b>this</b> & <i>that</i>', '<b>this</b> & <i>that</i>');
|
||||||
|
assertEscapes('<b>this</b> & <i>that</i>', '<b>this</b> & <i>that</i>');
|
||||||
|
|
||||||
|
// likewise with stray '<'
|
||||||
|
assertConverts('this < that', 'this < that');
|
||||||
|
assertEscapes('this < that', 'this < that');
|
||||||
|
|
||||||
|
assertConverts('<b>this</b> < <i>that</i>', '<b>this</b> < <i>that</i>');
|
||||||
|
assertEscapes('<b>this</b> < <i>that</i>', '<b>this</b> < <i>that</i>');
|
||||||
|
|
||||||
|
assertConverts('this < that > the other', 'this < that > the other');
|
||||||
|
assertEscapes('this < that > the other', 'this < that > the other');
|
||||||
|
|
||||||
|
assertConverts('this <<i>that</i>>', 'this <<i>that</i>>');
|
||||||
|
assertEscapes('this <<i>that</i>>', 'this <<i>that</i>>');
|
||||||
|
|
||||||
|
// unknown tags
|
||||||
|
assertConverts('<unknown>tag</unknown>', '<unknown>tag</unknown>');
|
||||||
|
assertEscapes('<unknown>tag</unknown>', '<unknown>tag</unknown>');
|
||||||
|
|
||||||
|
// make sure we check beyond the first letter
|
||||||
|
assertConverts('<bunknown>tag</bunknown>', '<bunknown>tag</bunknown>');
|
||||||
|
assertEscapes('<bunknown>tag</bunknown>', '<bunknown>tag</bunknown>');
|
||||||
|
|
||||||
|
// with mix of good and bad, we keep the good and escape the bad
|
||||||
|
assertConverts('<i>known</i> and <unknown>tag</unknown>', '<i>known</i> and <unknown>tag</unknown>');
|
||||||
|
assertEscapes('<i>known</i> and <unknown>tag</unknown>', '<i>known</i> and <unknown>tag</unknown>');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// FULLY INCORRECT MARKUP
|
||||||
|
// (fall back to escaping the whole thing)
|
||||||
|
|
||||||
|
// tags not matched up
|
||||||
|
assertConverts('<b>in<i>com</i>plete', '<b>in<i>com</i>plete');
|
||||||
|
assertEscapes('<b>in<i>com</i>plete', '<b>in<i>com</i>plete');
|
||||||
|
|
||||||
|
assertConverts('in<i>com</i>plete</b>', 'in<i>com</i>plete</b>');
|
||||||
|
assertEscapes('in<i>com</i>plete</b>', 'in<i>com</i>plete</b>');
|
||||||
|
|
||||||
|
// we don't support attributes, and it's too complicated to try
|
||||||
|
// to escape both start and end tags, so we just treat it as bad
|
||||||
|
assertConverts('<b>good</b> and <b style=\'bad\'>bad</b>', '<b>good</b> and <b style='bad'>bad</b>');
|
||||||
|
assertEscapes('<b>good</b> and <b style=\'bad\'>bad</b>', '<b>good</b> and <b style='bad'>bad</b>');
|
||||||
|
|
||||||
|
// this is just syntactically invalid
|
||||||
|
assertConverts('<b>unrecognized</b stuff>', '<b>unrecognized</b stuff>');
|
||||||
|
assertEscapes('<b>unrecognized</b stuff>', '<b>unrecognized</b stuff>');
|
||||||
|
|
||||||
|
// mismatched tags
|
||||||
|
assertConverts('<b>mismatched</i>', '<b>mismatched</i>');
|
||||||
|
assertEscapes('<b>mismatched</i>', '<b>mismatched</i>');
|
||||||
|
|
||||||
|
assertConverts('<b>mismatched/unknown</bunknown>', '<b>mismatched/unknown</bunknown>');
|
||||||
|
assertEscapes('<b>mismatched/unknown</bunknown>', '<b>mismatched/unknown</bunknown>');
|
@ -317,7 +317,6 @@
|
|||||||
<dep package="gobject-introspection"/>
|
<dep package="gobject-introspection"/>
|
||||||
<dep package="mutter"/>
|
<dep package="mutter"/>
|
||||||
<dep package="gjs"/>
|
<dep package="gjs"/>
|
||||||
<dep package="caribou"/>
|
|
||||||
<dep package="dconf"/>
|
<dep package="dconf"/>
|
||||||
<dep package="gconf"/>
|
<dep package="gconf"/>
|
||||||
<dep package="glib"/>
|
<dep package="glib"/>
|
||||||
@ -411,7 +410,7 @@
|
|||||||
</dependencies>
|
</dependencies>
|
||||||
</tarball>
|
</tarball>
|
||||||
|
|
||||||
<autotools id="caribou" autogenargs="--enable-gtk3-im">
|
<autotools id="caribou">
|
||||||
<branch repo="git.gnome.org" module="caribou"/>
|
<branch repo="git.gnome.org" module="caribou"/>
|
||||||
</autotools>
|
</autotools>
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user