Compare commits
20 Commits
citadel
...
wip/grab-h
Author | SHA1 | Date | |
---|---|---|---|
|
64bacc6286 | ||
|
50fec9e1f8 | ||
|
b03f7564e3 | ||
|
ef9006fa65 | ||
|
485d16ca4e | ||
|
1e40264ee4 | ||
|
ae22bde368 | ||
|
32502af652 | ||
|
7d693cbd17 | ||
|
d86e57a8d9 | ||
|
75985ae0ce | ||
|
7ee897ead5 | ||
|
7c371392da | ||
|
ab549f763d | ||
|
ea25331a55 | ||
|
c6bc1526fa | ||
|
871ae3f9b2 | ||
|
8ebbf442cd | ||
|
b936f094d1 | ||
|
165265f4fb |
@ -114,14 +114,6 @@ AC_SUBST([GNOME_KEYBINDINGS_KEYSDIR])
|
|||||||
|
|
||||||
GOBJECT_INTROSPECTION_CHECK([$GOBJECT_INTROSPECTION_MIN_VERSION])
|
GOBJECT_INTROSPECTION_CHECK([$GOBJECT_INTROSPECTION_MIN_VERSION])
|
||||||
|
|
||||||
saved_CFLAGS=$CFLAGS
|
|
||||||
saved_LIBS=$LIBS
|
|
||||||
CFLAGS=$GNOME_SHELL_CFLAGS
|
|
||||||
LIBS=$GNOME_SHELL_LIBS
|
|
||||||
AC_CHECK_FUNCS(JS_NewGlobalObject XFixesCreatePointerBarrier)
|
|
||||||
CFLAGS=$saved_CFLAGS
|
|
||||||
LIBS=$saved_LIBS
|
|
||||||
|
|
||||||
PKG_CHECK_MODULES(GNOME_SHELL_JS, gio-2.0 gjs-internals-1.0 >= $GJS_MIN_VERSION)
|
PKG_CHECK_MODULES(GNOME_SHELL_JS, gio-2.0 gjs-internals-1.0 >= $GJS_MIN_VERSION)
|
||||||
PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-3.0 libcroco-0.6 >= 0.6.8 x11)
|
PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-3.0 libcroco-0.6 >= 0.6.8 x11)
|
||||||
PKG_CHECK_MODULES(TRAY, gtk+-3.0)
|
PKG_CHECK_MODULES(TRAY, gtk+-3.0)
|
||||||
|
@ -48,18 +48,16 @@ const AlphabeticalView = new Lang.Class({
|
|||||||
style_class: 'vfade' });
|
style_class: 'vfade' });
|
||||||
this.actor.add_actor(box);
|
this.actor.add_actor(box);
|
||||||
this.actor.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
|
this.actor.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
|
||||||
this.actor.connect('notify::mapped', Lang.bind(this,
|
let action = new Clutter.PanAction({ interpolate: true });
|
||||||
function() {
|
action.connect('pan', Lang.bind(this, this._onPan));
|
||||||
if (!this.actor.mapped)
|
this.actor.add_action(action);
|
||||||
return;
|
},
|
||||||
|
|
||||||
let adjustment = this.actor.vscroll.adjustment;
|
_onPan: function(action) {
|
||||||
let direction = Overview.SwipeScrollDirection.VERTICAL;
|
let [dist, dx, dy] = action.get_motion_delta(0);
|
||||||
Main.overview.setScrollAdjustment(adjustment, direction);
|
let adjustment = this.actor.vscroll.adjustment;
|
||||||
|
adjustment.value -= (dy / this.actor.height) * adjustment.page_size;
|
||||||
// Reset scroll on mapping
|
return false;
|
||||||
adjustment.value = 0;
|
|
||||||
}));
|
|
||||||
},
|
},
|
||||||
|
|
||||||
removeAll: function() {
|
removeAll: function() {
|
||||||
|
@ -43,7 +43,6 @@ const GrabHelper = new Lang.Class({
|
|||||||
|
|
||||||
this._actors = [];
|
this._actors = [];
|
||||||
this._capturedEventId = 0;
|
this._capturedEventId = 0;
|
||||||
this._eventId = 0;
|
|
||||||
this._keyFocusNotifyId = 0;
|
this._keyFocusNotifyId = 0;
|
||||||
this._focusWindowChangedId = 0;
|
this._focusWindowChangedId = 0;
|
||||||
this._ignoreRelease = false;
|
this._ignoreRelease = false;
|
||||||
@ -77,10 +76,25 @@ const GrabHelper = new Lang.Class({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_actorInGrabStack: function(actor) {
|
||||||
|
while (actor) {
|
||||||
|
for (let i = 0; i < this._grabStack.length; i++) {
|
||||||
|
let grab = this._grabStack[i];
|
||||||
|
if (grab.actor == actor)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
actor = actor.get_parent();
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
},
|
||||||
|
|
||||||
_isWithinGrabbedActor: function(actor) {
|
_isWithinGrabbedActor: function(actor) {
|
||||||
|
let currentActor = this.currentGrab.actor;
|
||||||
while (actor) {
|
while (actor) {
|
||||||
if (this._actors.indexOf(actor) != -1)
|
if (this._actors.indexOf(actor) != -1)
|
||||||
return true;
|
return true;
|
||||||
|
if (actor == currentActor)
|
||||||
|
return true;
|
||||||
actor = actor.get_parent();
|
actor = actor.get_parent();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -90,6 +104,14 @@ const GrabHelper = new Lang.Class({
|
|||||||
return this._grabStack[this._grabStack.length - 1] || {};
|
return this._grabStack[this._grabStack.length - 1] || {};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
get grabbed() {
|
||||||
|
return this._grabStack.length > 0;
|
||||||
|
},
|
||||||
|
|
||||||
|
get grabStack() {
|
||||||
|
return this._grabStack;
|
||||||
|
},
|
||||||
|
|
||||||
_findStackIndex: function(actor) {
|
_findStackIndex: function(actor) {
|
||||||
if (!actor)
|
if (!actor)
|
||||||
return -1;
|
return -1;
|
||||||
@ -171,7 +193,6 @@ const GrabHelper = new Lang.Class({
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
this._capturedEventId = global.stage.connect('captured-event', Lang.bind(this, this._onCapturedEvent));
|
this._capturedEventId = global.stage.connect('captured-event', Lang.bind(this, this._onCapturedEvent));
|
||||||
this._eventId = global.stage.connect('event', Lang.bind(this, this._onEvent));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this._modalCount++;
|
this._modalCount++;
|
||||||
@ -188,11 +209,6 @@ const GrabHelper = new Lang.Class({
|
|||||||
this._capturedEventId = 0;
|
this._capturedEventId = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this._eventId > 0) {
|
|
||||||
global.stage.disconnect(this._eventId);
|
|
||||||
this._eventId = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Main.popModal(this._owner);
|
Main.popModal(this._owner);
|
||||||
global.sync_pointer();
|
global.sync_pointer();
|
||||||
},
|
},
|
||||||
@ -323,27 +339,22 @@ const GrabHelper = new Lang.Class({
|
|||||||
if (Main.keyboard.shouldTakeEvent(event))
|
if (Main.keyboard.shouldTakeEvent(event))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (button) {
|
if (type == Clutter.EventType.KEY_PRESS &&
|
||||||
// If we have a press event, ignore the next event,
|
|
||||||
// which should be a release event.
|
|
||||||
if (press)
|
|
||||||
this._ignoreRelease = true;
|
|
||||||
this.ungrab({ actor: this._grabStack[0].actor });
|
|
||||||
}
|
|
||||||
|
|
||||||
return this._modalCount > 0;
|
|
||||||
},
|
|
||||||
|
|
||||||
// We catch 'event' rather than 'key-press-event' so that we get
|
|
||||||
// a chance to run before the overview's own Escape check
|
|
||||||
_onEvent: function(actor, event) {
|
|
||||||
if (event.type() == Clutter.EventType.KEY_PRESS &&
|
|
||||||
event.get_key_symbol() == Clutter.KEY_Escape) {
|
event.get_key_symbol() == Clutter.KEY_Escape) {
|
||||||
this.ungrab();
|
this.ungrab();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
if (button) {
|
||||||
|
// If we have a press event, ignore the next event,
|
||||||
|
// which should be a release event.
|
||||||
|
if (press)
|
||||||
|
this._ignoreRelease = true;
|
||||||
|
let i = this._actorInGrabStack(event.get_source()) + 1;
|
||||||
|
this.ungrab({ actor: this._grabStack[i].actor });
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._modalCount > 0;
|
||||||
},
|
},
|
||||||
|
|
||||||
_onKeyFocusChanged: function() {
|
_onKeyFocusChanged: function() {
|
||||||
|
136
js/ui/layout.js
136
js/ui/layout.js
@ -19,6 +19,12 @@ const STARTUP_ANIMATION_TIME = 0.2;
|
|||||||
const KEYBOARD_ANIMATION_TIME = 0.5;
|
const KEYBOARD_ANIMATION_TIME = 0.5;
|
||||||
const PLYMOUTH_TRANSITION_TIME = 1;
|
const PLYMOUTH_TRANSITION_TIME = 1;
|
||||||
|
|
||||||
|
const MESSAGE_TRAY_PRESSURE_THRESHOLD = 200;
|
||||||
|
// The maximium amount that the user is allowed to travel
|
||||||
|
// perpendicular to the barrier before we release the accumulated
|
||||||
|
// pressure.
|
||||||
|
const MESSAGE_TRAY_MAX_SKIRT = 100;
|
||||||
|
|
||||||
const MonitorConstraint = new Lang.Class({
|
const MonitorConstraint = new Lang.Class({
|
||||||
Name: 'MonitorConstraint',
|
Name: 'MonitorConstraint',
|
||||||
Extends: Clutter.Constraint,
|
Extends: Clutter.Constraint,
|
||||||
@ -106,9 +112,9 @@ const LayoutManager = new Lang.Class({
|
|||||||
this._keyboardIndex = -1;
|
this._keyboardIndex = -1;
|
||||||
this._hotCorners = [];
|
this._hotCorners = [];
|
||||||
this._background = null;
|
this._background = null;
|
||||||
this._leftPanelBarrier = 0;
|
this._leftPanelBarrier = null;
|
||||||
this._rightPanelBarrier = 0;
|
this._rightPanelBarrier = null;
|
||||||
this._trayBarrier = 0;
|
this._trayBarrier = null;
|
||||||
|
|
||||||
this._chrome = new Chrome(this);
|
this._chrome = new Chrome(this);
|
||||||
|
|
||||||
@ -129,6 +135,8 @@ const LayoutManager = new Lang.Class({
|
|||||||
this.trayBox = new St.Widget({ name: 'trayBox',
|
this.trayBox = new St.Widget({ name: 'trayBox',
|
||||||
layout_manager: new Clutter.BinLayout() });
|
layout_manager: new Clutter.BinLayout() });
|
||||||
this.addChrome(this.trayBox);
|
this.addChrome(this.trayBox);
|
||||||
|
this.trayBox.connect('allocation-changed',
|
||||||
|
Lang.bind(this, this._updateTrayBarrier));
|
||||||
|
|
||||||
this.keyboardBox = new St.BoxLayout({ name: 'keyboardBox',
|
this.keyboardBox = new St.BoxLayout({ name: 'keyboardBox',
|
||||||
reactive: true,
|
reactive: true,
|
||||||
@ -257,24 +265,50 @@ const LayoutManager = new Lang.Class({
|
|||||||
},
|
},
|
||||||
|
|
||||||
_updatePanelBarriers: function() {
|
_updatePanelBarriers: function() {
|
||||||
if (this._leftPanelBarrier)
|
if (this._leftPanelBarrier) {
|
||||||
global.destroy_pointer_barrier(this._leftPanelBarrier);
|
this._leftPanelBarrier.destroy();
|
||||||
if (this._rightPanelBarrier)
|
this._leftPanelBarrier = null;
|
||||||
global.destroy_pointer_barrier(this._rightPanelBarrier);
|
}
|
||||||
|
|
||||||
|
if (this._rightPanelBarrier) {
|
||||||
|
this._rightPanelBarrier.destroy();
|
||||||
|
this._rightPanelBarrier = null;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.panelBox.height) {
|
if (this.panelBox.height) {
|
||||||
let primary = this.primaryMonitor;
|
let primary = this.primaryMonitor;
|
||||||
this._leftPanelBarrier =
|
|
||||||
global.create_pointer_barrier(primary.x, primary.y,
|
this._leftPanelBarrier = new Meta.Barrier({ display: global.display,
|
||||||
primary.x, primary.y + this.panelBox.height,
|
x1: primary.x, y1: primary.y,
|
||||||
1 /* BarrierPositiveX */);
|
x2: primary.x, y2: primary.y + this.panelBox.height,
|
||||||
this._rightPanelBarrier =
|
directions: Meta.BarrierDirection.POSITIVE_X });
|
||||||
global.create_pointer_barrier(primary.x + primary.width, primary.y,
|
this._rightPanelBarrier = new Meta.Barrier({ display: global.display,
|
||||||
primary.x + primary.width, primary.y + this.panelBox.height,
|
x1: primary.x + primary.width, y1: primary.y,
|
||||||
4 /* BarrierNegativeX */);
|
x2: primary.x + primary.width, y2: primary.y + this.panelBox.height,
|
||||||
} else {
|
directions: Meta.BarrierDirection.NEGATIVE_X });
|
||||||
this._leftPanelBarrier = 0;
|
}
|
||||||
this._rightPanelBarrier = 0;
|
},
|
||||||
|
|
||||||
|
_updateTrayBarrier: function() {
|
||||||
|
let monitor = this.bottomMonitor;
|
||||||
|
|
||||||
|
if (this._trayBarrier) {
|
||||||
|
this._trayBarrier.destroy();
|
||||||
|
this._trayBarrier = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Main.messageTray) {
|
||||||
|
this._trayBarrier = new Meta.Barrier({ display: global.display,
|
||||||
|
x1: monitor.x, x2: monitor.x + monitor.width,
|
||||||
|
y1: monitor.y + monitor.height - 1, y2: monitor.y + monitor.height - 1,
|
||||||
|
directions: Meta.BarrierDirection.NEGATIVE_Y });
|
||||||
|
|
||||||
|
this._trayPressure = new PressureBarrier(this._trayBarrier,
|
||||||
|
MESSAGE_TRAY_PRESSURE_THRESHOLD,
|
||||||
|
MESSAGE_TRAY_MAX_SKIRT);
|
||||||
|
this._trayPressure.connect('trigger', function() {
|
||||||
|
Main.messageTray.openTray();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1127,5 +1161,69 @@ const Chrome = new Lang.Class({
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Signals.addSignalMethods(Chrome.prototype);
|
Signals.addSignalMethods(Chrome.prototype);
|
||||||
|
|
||||||
|
const PressureBarrier = new Lang.Class({
|
||||||
|
Name: 'TrayPressure',
|
||||||
|
|
||||||
|
_init: function(barrier, pressureThreshold, perpThreshold) {
|
||||||
|
this._barrier = barrier;
|
||||||
|
this._pressureThreshold = pressureThreshold;
|
||||||
|
this._perpThreshold = perpThreshold;
|
||||||
|
this._getVelocityAndPerp = this._makeGetVelocityAndPerp(barrier);
|
||||||
|
|
||||||
|
this._reset(0);
|
||||||
|
|
||||||
|
this._barrierHitId = this._barrier.connect('hit', Lang.bind(this, this._onBarrierHit));
|
||||||
|
},
|
||||||
|
|
||||||
|
destroy: function() {
|
||||||
|
this._barrier.disconnect(this._barrierHitId);
|
||||||
|
this._barrier = null;
|
||||||
|
},
|
||||||
|
|
||||||
|
_reset: function(eventId) {
|
||||||
|
this._currentEventId = eventId;
|
||||||
|
this._currentPressure = 0;
|
||||||
|
this._perpAccumulator = 0;
|
||||||
|
},
|
||||||
|
|
||||||
|
_makeGetVelocityAndPerp: function(barrier) {
|
||||||
|
if (barrier.y1 === barrier.y2) {
|
||||||
|
return function(event) {
|
||||||
|
return [Math.abs(event.dy), event.dx];
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return function(event) {
|
||||||
|
return [Math.abs(event.dx), event.dy];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_onBarrierHit: function(barrier, event) {
|
||||||
|
// Event IDs are incremented every time the user stops
|
||||||
|
// hitting the barrier. So, if the event ID switches,
|
||||||
|
// reset the current state, and start over.
|
||||||
|
if (this._currentEventId != event.event_id) {
|
||||||
|
this._reset(event.event_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
let [velocity, perp] = this._getVelocityAndPerp(event);
|
||||||
|
this._perpAccumulator += perp;
|
||||||
|
|
||||||
|
// If the user travels too far in the direction perpendicular
|
||||||
|
// to the barrier, start over from scratch -- the user is simply
|
||||||
|
// trying to skirt along the barrier.
|
||||||
|
if (Math.abs(this._perpAccumulator) >= this._perpThreshold) {
|
||||||
|
this._reset(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._currentPressure += velocity;
|
||||||
|
if (this._currentPressure >= this._pressureThreshold) {
|
||||||
|
this.emit('trigger');
|
||||||
|
this._reset(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Signals.addSignalMethods(PressureBarrier.prototype);
|
||||||
|
@ -40,11 +40,6 @@ const LONGER_HIDE_TIMEOUT = 0.6;
|
|||||||
// range from the point where it left the tray.
|
// range from the point where it left the tray.
|
||||||
const MOUSE_LEFT_ACTOR_THRESHOLD = 20;
|
const MOUSE_LEFT_ACTOR_THRESHOLD = 20;
|
||||||
|
|
||||||
// Time the user needs to leave the mouse on the bottom pixel row to open the tray
|
|
||||||
const TRAY_DWELL_TIME = 1000; // ms
|
|
||||||
// Time resolution when tracking the mouse to catch the open tray dwell
|
|
||||||
const TRAY_DWELL_CHECK_INTERVAL = 100; // ms
|
|
||||||
|
|
||||||
const IDLE_TIME = 1000;
|
const IDLE_TIME = 1000;
|
||||||
|
|
||||||
const State = {
|
const State = {
|
||||||
@ -1441,7 +1436,6 @@ const MessageTray = new Lang.Class({
|
|||||||
this._clickedSummaryItem = null;
|
this._clickedSummaryItem = null;
|
||||||
this._clickedSummaryItemMouseButton = -1;
|
this._clickedSummaryItemMouseButton = -1;
|
||||||
this._clickedSummaryItemAllocationChangedId = 0;
|
this._clickedSummaryItemAllocationChangedId = 0;
|
||||||
this._pointerBarrier = 0;
|
|
||||||
|
|
||||||
this._closeButton = makeCloseButton();
|
this._closeButton = makeCloseButton();
|
||||||
this._closeButton.hide();
|
this._closeButton.hide();
|
||||||
@ -1537,12 +1531,6 @@ const MessageTray = new Lang.Class({
|
|||||||
this._summaryItems = [];
|
this._summaryItems = [];
|
||||||
this._chatSummaryItemsCount = 0;
|
this._chatSummaryItemsCount = 0;
|
||||||
|
|
||||||
let pointerWatcher = PointerWatcher.getPointerWatcher();
|
|
||||||
pointerWatcher.addWatch(TRAY_DWELL_CHECK_INTERVAL, Lang.bind(this, this._checkTrayDwell));
|
|
||||||
this._trayDwellTimeoutId = 0;
|
|
||||||
this._trayDwelling = false;
|
|
||||||
this._trayDwellUserTime = 0;
|
|
||||||
|
|
||||||
this._sessionUpdated();
|
this._sessionUpdated();
|
||||||
this._updateNoMessagesLabel();
|
this._updateNoMessagesLabel();
|
||||||
},
|
},
|
||||||
@ -1572,52 +1560,7 @@ const MessageTray = new Lang.Class({
|
|||||||
this._updateState();
|
this._updateState();
|
||||||
},
|
},
|
||||||
|
|
||||||
_checkTrayDwell: function(x, y) {
|
openTray: function() {
|
||||||
let monitor = Main.layoutManager.bottomMonitor;
|
|
||||||
let shouldDwell = (x >= monitor.x && x <= monitor.x + monitor.width &&
|
|
||||||
y == monitor.y + monitor.height - 1);
|
|
||||||
if (shouldDwell) {
|
|
||||||
// We only set up dwell timeout when the user is not hovering over the tray
|
|
||||||
// (!this.actor.hover). This avoids bringing up the message tray after the
|
|
||||||
// user clicks on a notification with the pointer on the bottom pixel
|
|
||||||
// of the monitor. The _trayDwelling variable is used so that we only try to
|
|
||||||
// fire off one tray dwell - if it fails (because, say, the user has the mouse down),
|
|
||||||
// we don't try again until the user moves the mouse up and down again.
|
|
||||||
if (!this._trayDwelling && !this.actor.hover && this._trayDwellTimeoutId == 0) {
|
|
||||||
// Save the interaction timestamp so we can detect user input
|
|
||||||
let focusWindow = global.display.focus_window;
|
|
||||||
this._trayDwellUserTime = focusWindow ? focusWindow.user_time : 0;
|
|
||||||
|
|
||||||
this._trayDwellTimeoutId = Mainloop.timeout_add(TRAY_DWELL_TIME,
|
|
||||||
Lang.bind(this, this._trayDwellTimeout));
|
|
||||||
}
|
|
||||||
this._trayDwelling = true;
|
|
||||||
} else {
|
|
||||||
this._cancelTrayDwell();
|
|
||||||
this._trayDwelling = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_cancelTrayDwell: function() {
|
|
||||||
if (this._trayDwellTimeoutId != 0) {
|
|
||||||
Mainloop.source_remove(this._trayDwellTimeoutId);
|
|
||||||
this._trayDwellTimeoutId = 0;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_trayDwellTimeout: function() {
|
|
||||||
this._trayDwellTimeoutId = 0;
|
|
||||||
|
|
||||||
if (Main.modalCount > 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// If the user interacted with the focus window since we started the tray
|
|
||||||
// dwell (by clicking or typing), don't activate the message tray
|
|
||||||
let focusWindow = global.display.focus_window;
|
|
||||||
let currentUserTime = focusWindow ? focusWindow.user_time : 0;
|
|
||||||
if (currentUserTime != this._trayDwellUserTime)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
this._traySummoned = true;
|
this._traySummoned = true;
|
||||||
this._updateState();
|
this._updateState();
|
||||||
|
|
||||||
@ -1849,9 +1792,6 @@ const MessageTray = new Lang.Class({
|
|||||||
|
|
||||||
_onTrayHoverChanged: function() {
|
_onTrayHoverChanged: function() {
|
||||||
if (this.actor.hover) {
|
if (this.actor.hover) {
|
||||||
// No dwell inside notifications at the bottom of the screen
|
|
||||||
this._cancelTrayDwell();
|
|
||||||
|
|
||||||
// Don't do anything if the one pixel area at the bottom is hovered over while the tray is hidden.
|
// Don't do anything if the one pixel area at the bottom is hovered over while the tray is hidden.
|
||||||
if (this._trayState == State.HIDDEN && this._notificationState == State.HIDDEN)
|
if (this._trayState == State.HIDDEN && this._notificationState == State.HIDDEN)
|
||||||
return;
|
return;
|
||||||
|
@ -46,18 +46,6 @@ const GLSL_DIM_EFFECT_CODE = '\
|
|||||||
cogl_color_out.xyz = cogl_color_out.xyz * (1.0 - a); \
|
cogl_color_out.xyz = cogl_color_out.xyz * (1.0 - a); \
|
||||||
cogl_color_out.a = 1.0;';
|
cogl_color_out.a = 1.0;';
|
||||||
|
|
||||||
const SwipeScrollDirection = {
|
|
||||||
NONE: 0,
|
|
||||||
HORIZONTAL: 1,
|
|
||||||
VERTICAL: 2
|
|
||||||
};
|
|
||||||
|
|
||||||
const SwipeScrollResult = {
|
|
||||||
CANCEL: 0,
|
|
||||||
SWIPE: 1,
|
|
||||||
CLICK: 2
|
|
||||||
};
|
|
||||||
|
|
||||||
const ShellInfo = new Lang.Class({
|
const ShellInfo = new Lang.Class({
|
||||||
Name: 'ShellInfo',
|
Name: 'ShellInfo',
|
||||||
|
|
||||||
@ -165,8 +153,6 @@ const Overview = new Lang.Class({
|
|||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
this._scrollDirection = SwipeScrollDirection.NONE;
|
|
||||||
this._scrollAdjustment = null;
|
|
||||||
this._capturedEventId = 0;
|
this._capturedEventId = 0;
|
||||||
this._buttonPressId = 0;
|
this._buttonPressId = 0;
|
||||||
|
|
||||||
@ -341,159 +327,11 @@ const Overview = new Lang.Class({
|
|||||||
return DND.DragMotionResult.CONTINUE;
|
return DND.DragMotionResult.CONTINUE;
|
||||||
},
|
},
|
||||||
|
|
||||||
setScrollAdjustment: function(adjustment, direction) {
|
addAction: function(action) {
|
||||||
if (this.isDummy)
|
if (this.isDummy)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this._scrollAdjustment = adjustment;
|
this._group.add_action(action);
|
||||||
if (this._scrollAdjustment == null)
|
|
||||||
this._scrollDirection = SwipeScrollDirection.NONE;
|
|
||||||
else
|
|
||||||
this._scrollDirection = direction;
|
|
||||||
},
|
|
||||||
|
|
||||||
_onButtonPress: function(actor, event) {
|
|
||||||
if (this._scrollDirection == SwipeScrollDirection.NONE
|
|
||||||
|| event.get_button() != 1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
let [stageX, stageY] = event.get_coords();
|
|
||||||
this._dragStartX = this._dragX = stageX;
|
|
||||||
this._dragStartY = this._dragY = stageY;
|
|
||||||
this._dragStartValue = this._scrollAdjustment.value;
|
|
||||||
this._lastMotionTime = -1; // used to track "stopping" while swipe-scrolling
|
|
||||||
this._capturedEventId = global.stage.connect('captured-event',
|
|
||||||
Lang.bind(this, this._onCapturedEvent));
|
|
||||||
this.emit('swipe-scroll-begin');
|
|
||||||
},
|
|
||||||
|
|
||||||
_onCapturedEvent: function(actor, event) {
|
|
||||||
let stageX, stageY;
|
|
||||||
let threshold = Gtk.Settings.get_default().gtk_dnd_drag_threshold;
|
|
||||||
|
|
||||||
switch(event.type()) {
|
|
||||||
case Clutter.EventType.BUTTON_RELEASE:
|
|
||||||
[stageX, stageY] = event.get_coords();
|
|
||||||
|
|
||||||
// default to snapping back to the original value
|
|
||||||
let newValue = this._dragStartValue;
|
|
||||||
|
|
||||||
let minValue = this._scrollAdjustment.lower;
|
|
||||||
let maxValue = this._scrollAdjustment.upper - this._scrollAdjustment.page_size;
|
|
||||||
|
|
||||||
let direction;
|
|
||||||
if (this._scrollDirection == SwipeScrollDirection.HORIZONTAL) {
|
|
||||||
direction = stageX > this._dragStartX ? -1 : 1;
|
|
||||||
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
|
|
||||||
direction *= -1;
|
|
||||||
} else {
|
|
||||||
direction = stageY > this._dragStartY ? -1 : 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We default to scroll a full page size; both the first
|
|
||||||
// and the last page may be smaller though, so we need to
|
|
||||||
// adjust difference in those cases.
|
|
||||||
let difference = direction * this._scrollAdjustment.page_size;
|
|
||||||
if (this._dragStartValue + difference > maxValue)
|
|
||||||
difference = maxValue - this._dragStartValue;
|
|
||||||
else if (this._dragStartValue + difference < minValue)
|
|
||||||
difference = minValue - this._dragStartValue;
|
|
||||||
|
|
||||||
// If the user has moved more than half the scroll
|
|
||||||
// difference, we want to "settle" to the new value
|
|
||||||
// even if the user stops dragging rather "throws" by
|
|
||||||
// releasing during the drag.
|
|
||||||
let distance = this._dragStartValue - this._scrollAdjustment.value;
|
|
||||||
let noStop = Math.abs(distance / difference) > 0.5;
|
|
||||||
|
|
||||||
// We detect if the user is stopped by comparing the
|
|
||||||
// timestamp of the button release with the timestamp of
|
|
||||||
// the last motion. Experimentally, a difference of 0 or 1
|
|
||||||
// millisecond indicates that the mouse is in motion, a
|
|
||||||
// larger difference indicates that the mouse is stopped.
|
|
||||||
if ((this._lastMotionTime > 0 &&
|
|
||||||
this._lastMotionTime > event.get_time() - 2) ||
|
|
||||||
noStop) {
|
|
||||||
if (this._dragStartValue + difference >= minValue &&
|
|
||||||
this._dragStartValue + difference <= maxValue)
|
|
||||||
newValue += difference;
|
|
||||||
}
|
|
||||||
|
|
||||||
let result;
|
|
||||||
|
|
||||||
// See if the user has moved the mouse enough to trigger
|
|
||||||
// a drag
|
|
||||||
if (Math.abs(stageX - this._dragStartX) < threshold &&
|
|
||||||
Math.abs(stageY - this._dragStartY) < threshold) {
|
|
||||||
// no motion? It's a click!
|
|
||||||
result = SwipeScrollResult.CLICK;
|
|
||||||
this.emit('swipe-scroll-end', result);
|
|
||||||
} else {
|
|
||||||
if (newValue == this._dragStartValue)
|
|
||||||
result = SwipeScrollResult.CANCEL;
|
|
||||||
else
|
|
||||||
result = SwipeScrollResult.SWIPE;
|
|
||||||
|
|
||||||
// The event capture handler is disconnected
|
|
||||||
// while scrolling to the final position, so
|
|
||||||
// to avoid undesired prelights we raise
|
|
||||||
// the cover pane.
|
|
||||||
this._coverPane.raise_top();
|
|
||||||
this._coverPane.show();
|
|
||||||
|
|
||||||
Tweener.addTween(this._scrollAdjustment,
|
|
||||||
{ value: newValue,
|
|
||||||
time: ANIMATION_TIME,
|
|
||||||
transition: 'easeOutQuad',
|
|
||||||
onCompleteScope: this,
|
|
||||||
onComplete: function() {
|
|
||||||
this._coverPane.hide();
|
|
||||||
this.emit('swipe-scroll-end',
|
|
||||||
result);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
global.stage.disconnect(this._capturedEventId);
|
|
||||||
this._capturedEventId = 0;
|
|
||||||
|
|
||||||
return result != SwipeScrollResult.CLICK;
|
|
||||||
|
|
||||||
case Clutter.EventType.MOTION:
|
|
||||||
[stageX, stageY] = event.get_coords();
|
|
||||||
let dx = this._dragX - stageX;
|
|
||||||
let dy = this._dragY - stageY;
|
|
||||||
let primary = Main.layoutManager.primaryMonitor;
|
|
||||||
|
|
||||||
this._dragX = stageX;
|
|
||||||
this._dragY = stageY;
|
|
||||||
this._lastMotionTime = event.get_time();
|
|
||||||
|
|
||||||
// See if the user has moved the mouse enough to trigger
|
|
||||||
// a drag
|
|
||||||
if (Math.abs(stageX - this._dragStartX) < threshold &&
|
|
||||||
Math.abs(stageY - this._dragStartY) < threshold)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (this._scrollDirection == SwipeScrollDirection.HORIZONTAL) {
|
|
||||||
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
|
|
||||||
this._scrollAdjustment.value -= (dx / primary.width) * this._scrollAdjustment.page_size;
|
|
||||||
else
|
|
||||||
this._scrollAdjustment.value += (dx / primary.width) * this._scrollAdjustment.page_size;
|
|
||||||
} else {
|
|
||||||
this._scrollAdjustment.value += (dy / primary.height) * this._scrollAdjustment.page_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// Block enter/leave events to avoid prelights
|
|
||||||
// during swipe-scroll
|
|
||||||
case Clutter.EventType.ENTER:
|
|
||||||
case Clutter.EventType.LEAVE:
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_getDesktopClone: function() {
|
_getDesktopClone: function() {
|
||||||
@ -596,9 +434,6 @@ const Overview = new Lang.Class({
|
|||||||
this._modal = true;
|
this._modal = true;
|
||||||
this._animateVisible();
|
this._animateVisible();
|
||||||
this._shown = true;
|
this._shown = true;
|
||||||
|
|
||||||
this._buttonPressId = this._group.connect('button-press-event',
|
|
||||||
Lang.bind(this, this._onButtonPress));
|
|
||||||
},
|
},
|
||||||
|
|
||||||
fadeInDesktop: function() {
|
fadeInDesktop: function() {
|
||||||
@ -698,10 +533,6 @@ const Overview = new Lang.Class({
|
|||||||
|
|
||||||
this._shown = false;
|
this._shown = false;
|
||||||
this._syncInputMode();
|
this._syncInputMode();
|
||||||
|
|
||||||
if (this._buttonPressId > 0)
|
|
||||||
this._group.disconnect(this._buttonPressId);
|
|
||||||
this._buttonPressId = 0;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// hideTemporarily:
|
// hideTemporarily:
|
||||||
|
@ -12,6 +12,7 @@ const St = imports.gi.St;
|
|||||||
const Atk = imports.gi.Atk;
|
const Atk = imports.gi.Atk;
|
||||||
|
|
||||||
const BoxPointer = imports.ui.boxpointer;
|
const BoxPointer = imports.ui.boxpointer;
|
||||||
|
const GrabHelper = imports.ui.grabHelper;
|
||||||
const Main = imports.ui.main;
|
const Main = imports.ui.main;
|
||||||
const Params = imports.misc.params;
|
const Params = imports.misc.params;
|
||||||
const Tweener = imports.ui.tweener;
|
const Tweener = imports.ui.tweener;
|
||||||
@ -658,14 +659,23 @@ const PopupSliderMenuItem = new Lang.Class({
|
|||||||
|
|
||||||
_onScrollEvent: function (actor, event) {
|
_onScrollEvent: function (actor, event) {
|
||||||
let direction = event.get_scroll_direction();
|
let direction = event.get_scroll_direction();
|
||||||
|
let delta;
|
||||||
|
|
||||||
|
if (event.is_pointer_emulated())
|
||||||
|
return;
|
||||||
|
|
||||||
if (direction == Clutter.ScrollDirection.DOWN) {
|
if (direction == Clutter.ScrollDirection.DOWN) {
|
||||||
this._value = Math.max(0, this._value - SLIDER_SCROLL_STEP);
|
delta = -SLIDER_SCROLL_STEP;
|
||||||
}
|
} else if (direction == Clutter.ScrollDirection.UP) {
|
||||||
else if (direction == Clutter.ScrollDirection.UP) {
|
delta = +SLIDER_SCROLL_STEP;
|
||||||
this._value = Math.min(1, this._value + SLIDER_SCROLL_STEP);
|
} else if (direction == Clutter.ScrollDirection.SMOOTH) {
|
||||||
|
let [dx, dy] = event.get_scroll_delta();
|
||||||
|
// Even though the slider is horizontal, use dy to match
|
||||||
|
// the UP/DOWN above.
|
||||||
|
delta = -dy / 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._value = Math.min(Math.max(0, this._value + delta), 1);
|
||||||
this._slider.queue_repaint();
|
this._slider.queue_repaint();
|
||||||
this.emit('value-changed', this._value);
|
this.emit('value-changed', this._value);
|
||||||
},
|
},
|
||||||
@ -1204,7 +1214,6 @@ const PopupMenu = new Lang.Class({
|
|||||||
this.actor = this._boxPointer.actor;
|
this.actor = this._boxPointer.actor;
|
||||||
this.actor._delegate = this;
|
this.actor._delegate = this;
|
||||||
this.actor.style_class = 'popup-menu-boxpointer';
|
this.actor.style_class = 'popup-menu-boxpointer';
|
||||||
this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent));
|
|
||||||
|
|
||||||
this._boxWrapper = new Shell.GenericContainer();
|
this._boxWrapper = new Shell.GenericContainer();
|
||||||
this._boxWrapper.connect('get-preferred-width', Lang.bind(this, this._boxGetPreferredWidth));
|
this._boxWrapper.connect('get-preferred-width', Lang.bind(this, this._boxGetPreferredWidth));
|
||||||
@ -1234,15 +1243,6 @@ const PopupMenu = new Lang.Class({
|
|||||||
this.box.allocate(box, flags);
|
this.box.allocate(box, flags);
|
||||||
},
|
},
|
||||||
|
|
||||||
_onKeyPressEvent: function(actor, event) {
|
|
||||||
if (event.get_key_symbol() == Clutter.Escape) {
|
|
||||||
this.close(BoxPointer.PopupAnimation.FULL);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
|
|
||||||
setArrowOrigin: function(origin) {
|
setArrowOrigin: function(origin) {
|
||||||
this._boxPointer.setArrowOrigin(origin);
|
this._boxPointer.setArrowOrigin(origin);
|
||||||
},
|
},
|
||||||
@ -1537,7 +1537,6 @@ const PopupComboMenu = new Lang.Class({
|
|||||||
|
|
||||||
this.actor = this.box;
|
this.actor = this.box;
|
||||||
this.actor._delegate = this;
|
this.actor._delegate = this;
|
||||||
this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent));
|
|
||||||
this.actor.connect('key-focus-in', Lang.bind(this, this._onKeyFocusIn));
|
this.actor.connect('key-focus-in', Lang.bind(this, this._onKeyFocusIn));
|
||||||
sourceActor.connect('style-changed',
|
sourceActor.connect('style-changed',
|
||||||
Lang.bind(this, this._onSourceActorStyleChanged));
|
Lang.bind(this, this._onSourceActorStyleChanged));
|
||||||
@ -1545,15 +1544,6 @@ const PopupComboMenu = new Lang.Class({
|
|||||||
global.focus_manager.add_group(this.actor);
|
global.focus_manager.add_group(this.actor);
|
||||||
},
|
},
|
||||||
|
|
||||||
_onKeyPressEvent: function(actor, event) {
|
|
||||||
if (event.get_key_symbol() == Clutter.Escape) {
|
|
||||||
this.close(BoxPointer.PopupAnimation.FULL);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
|
|
||||||
_onKeyFocusIn: function(actor) {
|
_onKeyFocusIn: function(actor) {
|
||||||
let items = this._getMenuItems();
|
let items = this._getMenuItems();
|
||||||
let activeItem = items[this._activeItemPos];
|
let activeItem = items[this._activeItemPos];
|
||||||
@ -2044,17 +2034,8 @@ const PopupMenuManager = new Lang.Class({
|
|||||||
|
|
||||||
_init: function(owner) {
|
_init: function(owner) {
|
||||||
this._owner = owner;
|
this._owner = owner;
|
||||||
this.grabbed = false;
|
this._grabHelper = new GrabHelper.GrabHelper(owner.actor);
|
||||||
|
|
||||||
this._eventCaptureId = 0;
|
|
||||||
this._enterEventId = 0;
|
|
||||||
this._leaveEventId = 0;
|
|
||||||
this._keyFocusNotifyId = 0;
|
|
||||||
this._activeMenu = null;
|
|
||||||
this._menus = [];
|
this._menus = [];
|
||||||
this._menuStack = [];
|
|
||||||
this._preGrabInputMode = null;
|
|
||||||
this._grabbedFromKeynav = false;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
addMenu: function(menu, position) {
|
addMenu: function(menu, position) {
|
||||||
@ -2073,6 +2054,8 @@ const PopupMenuManager = new Lang.Class({
|
|||||||
|
|
||||||
let source = menu.sourceActor;
|
let source = menu.sourceActor;
|
||||||
if (source) {
|
if (source) {
|
||||||
|
if (!menu.blockSourceEvents)
|
||||||
|
this._grabHelper.addActor(source);
|
||||||
menudata.enterId = source.connect('enter-event', Lang.bind(this, function() { this._onMenuSourceEnter(menu); }));
|
menudata.enterId = source.connect('enter-event', Lang.bind(this, function() { this._onMenuSourceEnter(menu); }));
|
||||||
menudata.focusInId = source.connect('key-focus-in', Lang.bind(this, function() { this._onMenuSourceEnter(menu); }));
|
menudata.focusInId = source.connect('key-focus-in', Lang.bind(this, function() { this._onMenuSourceEnter(menu); }));
|
||||||
}
|
}
|
||||||
@ -2085,7 +2068,7 @@ const PopupMenuManager = new Lang.Class({
|
|||||||
|
|
||||||
removeMenu: function(menu) {
|
removeMenu: function(menu) {
|
||||||
if (menu == this._activeMenu)
|
if (menu == this._activeMenu)
|
||||||
this._closeMenu();
|
this._closeMenu(menu);
|
||||||
|
|
||||||
let position = this._findMenu(menu);
|
let position = this._findMenu(menu);
|
||||||
if (position == -1) // not a menu we manage
|
if (position == -1) // not a menu we manage
|
||||||
@ -2102,79 +2085,25 @@ const PopupMenuManager = new Lang.Class({
|
|||||||
if (menudata.focusInId)
|
if (menudata.focusInId)
|
||||||
menu.sourceActor.disconnect(menudata.focusInId);
|
menu.sourceActor.disconnect(menudata.focusInId);
|
||||||
|
|
||||||
|
if (menu.sourceActor)
|
||||||
|
this._grabHelper.removeActor(menu.sourceActor);
|
||||||
this._menus.splice(position, 1);
|
this._menus.splice(position, 1);
|
||||||
},
|
},
|
||||||
|
|
||||||
_grab: function() {
|
get activeMenu() {
|
||||||
Main.pushModal(this._owner.actor);
|
let actor = this._grabHelper.currentGrab.actor;
|
||||||
|
if (actor)
|
||||||
this._eventCaptureId = global.stage.connect('captured-event', Lang.bind(this, this._onEventCapture));
|
return actor._delegate;
|
||||||
// captured-event doesn't see enter/leave events
|
else
|
||||||
this._enterEventId = global.stage.connect('enter-event', Lang.bind(this, this._onEventCapture));
|
return null;
|
||||||
this._leaveEventId = global.stage.connect('leave-event', Lang.bind(this, this._onEventCapture));
|
|
||||||
this._keyFocusNotifyId = global.stage.connect('notify::key-focus', Lang.bind(this, this._onKeyFocusChanged));
|
|
||||||
|
|
||||||
this.grabbed = true;
|
|
||||||
},
|
|
||||||
|
|
||||||
_ungrab: function() {
|
|
||||||
global.stage.disconnect(this._eventCaptureId);
|
|
||||||
this._eventCaptureId = 0;
|
|
||||||
global.stage.disconnect(this._enterEventId);
|
|
||||||
this._enterEventId = 0;
|
|
||||||
global.stage.disconnect(this._leaveEventId);
|
|
||||||
this._leaveEventId = 0;
|
|
||||||
global.stage.disconnect(this._keyFocusNotifyId);
|
|
||||||
this._keyFocusNotifyId = 0;
|
|
||||||
|
|
||||||
this.grabbed = false;
|
|
||||||
Main.popModal(this._owner.actor);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_onMenuOpenState: function(menu, open) {
|
_onMenuOpenState: function(menu, open) {
|
||||||
if (open) {
|
if (open) {
|
||||||
if (this._activeMenu && this._activeMenu.isChildMenu(menu)) {
|
this._grabHelper.grab({ actor: menu.actor, modal: true,
|
||||||
this._menuStack.push(this._activeMenu);
|
onUngrab: Lang.bind(this, this._closeMenu, menu) });
|
||||||
menu.actor.grab_key_focus();
|
|
||||||
}
|
|
||||||
this._activeMenu = menu;
|
|
||||||
} else {
|
} else {
|
||||||
if (this._menuStack.length > 0) {
|
this._grabHelper.ungrab({ actor: menu.actor });
|
||||||
this._activeMenu = this._menuStack.pop();
|
|
||||||
if (menu.sourceActor)
|
|
||||||
menu.sourceActor.grab_key_focus();
|
|
||||||
this._didPop = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check what the focus was before calling pushModal/popModal
|
|
||||||
let focus = global.stage.key_focus;
|
|
||||||
let hadFocus = focus && this._activeMenuContains(focus);
|
|
||||||
|
|
||||||
if (open) {
|
|
||||||
if (!this.grabbed) {
|
|
||||||
this._preGrabInputMode = global.stage_input_mode;
|
|
||||||
this._grabbedFromKeynav = hadFocus;
|
|
||||||
this._grab();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hadFocus)
|
|
||||||
focus.grab_key_focus();
|
|
||||||
else
|
|
||||||
menu.actor.grab_key_focus();
|
|
||||||
} else if (menu == this._activeMenu) {
|
|
||||||
if (this.grabbed)
|
|
||||||
this._ungrab();
|
|
||||||
this._activeMenu = null;
|
|
||||||
|
|
||||||
if (this._grabbedFromKeynav) {
|
|
||||||
if (this._preGrabInputMode == Shell.StageInputMode.FOCUSED)
|
|
||||||
global.stage_input_mode = Shell.StageInputMode.FOCUSED;
|
|
||||||
if (hadFocus && menu.sourceActor)
|
|
||||||
menu.sourceActor.grab_key_focus();
|
|
||||||
else if (focus)
|
|
||||||
focus.grab_key_focus();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -2186,87 +2115,37 @@ const PopupMenuManager = new Lang.Class({
|
|||||||
this.removeMenu(childMenu);
|
this.removeMenu(childMenu);
|
||||||
},
|
},
|
||||||
|
|
||||||
// change the currently-open menu without dropping grab
|
|
||||||
_changeMenu: function(newMenu) {
|
_changeMenu: function(newMenu) {
|
||||||
if (this._activeMenu) {
|
if (this.activeMenu) {
|
||||||
// _onOpenMenuState will drop the grab if it sees
|
this._closeMenu(this.activeMenu);
|
||||||
// this._activeMenu being closed; so clear _activeMenu
|
newMenu.open(false);
|
||||||
// before closing it to keep that from happening
|
} else {
|
||||||
let oldMenu = this._activeMenu;
|
newMenu.open(true);
|
||||||
this._activeMenu = null;
|
}
|
||||||
for (let i = this._menuStack.length - 1; i >= 0; i--)
|
|
||||||
this._menuStack[i].close(BoxPointer.PopupAnimation.FADE);
|
|
||||||
oldMenu.close(BoxPointer.PopupAnimation.FADE);
|
|
||||||
newMenu.open(BoxPointer.PopupAnimation.FADE);
|
|
||||||
} else
|
|
||||||
newMenu.open(BoxPointer.PopupAnimation.FULL);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_onMenuSourceEnter: function(menu) {
|
_onMenuSourceEnter: function(menu) {
|
||||||
if (!this.grabbed || menu == this._activeMenu)
|
if (!this._grabHelper.grabbed)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (this._activeMenu && this._activeMenu.isChildMenu(menu))
|
if (this._grabHelper.isActorGrabbed(menu.actor))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (this._menuStack.indexOf(menu) != -1)
|
let isChildMenu = this._grabHelper.grabStack.some(function(grab) {
|
||||||
return false;
|
let existingMenu = grab.actor._delegate;
|
||||||
|
return existingMenu.isChildMenu(menu);
|
||||||
if (this._menuStack.length > 0 && this._menuStack[0].isChildMenu(menu))
|
});
|
||||||
|
if (isChildMenu)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
this._changeMenu(menu);
|
this._changeMenu(menu);
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
_onKeyFocusChanged: function() {
|
|
||||||
if (!this.grabbed || !this._activeMenu)
|
|
||||||
return;
|
|
||||||
|
|
||||||
let focus = global.stage.key_focus;
|
|
||||||
if (focus) {
|
|
||||||
if (this._activeMenuContains(focus))
|
|
||||||
return;
|
|
||||||
if (this._menuStack.length > 0)
|
|
||||||
return;
|
|
||||||
if (focus._delegate && focus._delegate.menu &&
|
|
||||||
this._findMenu(focus._delegate.menu) != -1)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._closeMenu();
|
|
||||||
},
|
|
||||||
|
|
||||||
_onMenuDestroy: function(menu) {
|
_onMenuDestroy: function(menu) {
|
||||||
this.removeMenu(menu);
|
this.removeMenu(menu);
|
||||||
},
|
},
|
||||||
|
|
||||||
_activeMenuContains: function(actor) {
|
|
||||||
return this._activeMenu != null
|
|
||||||
&& (this._activeMenu.actor.contains(actor) ||
|
|
||||||
(this._activeMenu.sourceActor && this._activeMenu.sourceActor.contains(actor)));
|
|
||||||
},
|
|
||||||
|
|
||||||
_eventIsOnActiveMenu: function(event) {
|
|
||||||
return this._activeMenuContains(event.get_source());
|
|
||||||
},
|
|
||||||
|
|
||||||
_shouldBlockEvent: function(event) {
|
|
||||||
let src = event.get_source();
|
|
||||||
|
|
||||||
if (this._activeMenu != null && this._activeMenu.actor.contains(src))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
for (let i = 0; i < this._menus.length; i++) {
|
|
||||||
let menu = this._menus[i].menu;
|
|
||||||
if (menu.sourceActor && !menu.blockSourceEvents && menu.sourceActor.contains(src)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
_findMenu: function(item) {
|
_findMenu: function(item) {
|
||||||
for (let i = 0; i < this._menus.length; i++) {
|
for (let i = 0; i < this._menus.length; i++) {
|
||||||
let menudata = this._menus[i];
|
let menudata = this._menus[i];
|
||||||
@ -2276,41 +2155,7 @@ const PopupMenuManager = new Lang.Class({
|
|||||||
return -1;
|
return -1;
|
||||||
},
|
},
|
||||||
|
|
||||||
_onEventCapture: function(actor, event) {
|
_closeMenu: function(menu) {
|
||||||
if (!this.grabbed)
|
menu.close(BoxPointer.PopupAnimation.FULL);
|
||||||
return false;
|
|
||||||
|
|
||||||
if (this._owner.menuEventFilter &&
|
|
||||||
this._owner.menuEventFilter(event))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (this._didPop) {
|
|
||||||
this._didPop = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
let activeMenuContains = this._eventIsOnActiveMenu(event);
|
|
||||||
let eventType = event.type();
|
|
||||||
|
|
||||||
if (eventType == Clutter.EventType.BUTTON_RELEASE) {
|
|
||||||
if (activeMenuContains) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
this._closeMenu();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else if (eventType == Clutter.EventType.BUTTON_PRESS && !activeMenuContains) {
|
|
||||||
this._closeMenu();
|
|
||||||
return true;
|
|
||||||
} else if (!this._shouldBlockEvent(event)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
_closeMenu: function() {
|
|
||||||
if (this._activeMenu != null)
|
|
||||||
this._activeMenu.close(BoxPointer.PopupAnimation.FULL);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -194,15 +194,9 @@ const SearchResults = new Lang.Class({
|
|||||||
expand: true,
|
expand: true,
|
||||||
x_align: St.Align.START,
|
x_align: St.Align.START,
|
||||||
y_align: St.Align.START });
|
y_align: St.Align.START });
|
||||||
this.actor.connect('notify::mapped', Lang.bind(this,
|
let action = new Clutter.PanAction({ interpolate: true });
|
||||||
function() {
|
action.connect('pan', Lang.bind(this, this._onPan));
|
||||||
if (!this.actor.mapped)
|
this.actor.add_action(action);
|
||||||
return;
|
|
||||||
|
|
||||||
let adjustment = scrollView.vscroll.adjustment;
|
|
||||||
let direction = Overview.SwipeScrollDirection.VERTICAL;
|
|
||||||
Main.overview.setScrollAdjustment(adjustment, direction);
|
|
||||||
}));
|
|
||||||
|
|
||||||
this._statusText = new St.Label({ style_class: 'search-statustext' });
|
this._statusText = new St.Label({ style_class: 'search-statustext' });
|
||||||
this._statusBin = new St.Bin({ x_align: St.Align.MIDDLE,
|
this._statusBin = new St.Bin({ x_align: St.Align.MIDDLE,
|
||||||
@ -219,6 +213,13 @@ const SearchResults = new Lang.Class({
|
|||||||
this._defaultResult = null;
|
this._defaultResult = null;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_onPan: function(action) {
|
||||||
|
let [dist, dx, dy] = action.get_motion_delta(0);
|
||||||
|
let adjustment = this.actor.vscroll.adjustment;
|
||||||
|
adjustment.value -= (dy / this.actor.height) * adjustment.page_size;
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
createProviderMeta: function(provider) {
|
createProviderMeta: function(provider) {
|
||||||
let providerBox = new St.BoxLayout({ style_class: 'search-section',
|
let providerBox = new St.BoxLayout({ style_class: 'search-section',
|
||||||
vertical: true });
|
vertical: true });
|
||||||
|
@ -66,24 +66,32 @@ const VolumeMenu = new Lang.Class({
|
|||||||
this._onControlStateChanged();
|
this._onControlStateChanged();
|
||||||
},
|
},
|
||||||
|
|
||||||
scroll: function(direction) {
|
scroll: function(event) {
|
||||||
|
let direction = event.get_scroll_direction();
|
||||||
let currentVolume = this._output.volume;
|
let currentVolume = this._output.volume;
|
||||||
|
let delta;
|
||||||
|
|
||||||
|
if (event.is_pointer_emulated())
|
||||||
|
return;
|
||||||
|
|
||||||
if (direction == Clutter.ScrollDirection.DOWN) {
|
if (direction == Clutter.ScrollDirection.DOWN) {
|
||||||
let prev_muted = this._output.is_muted;
|
delta = -VOLUME_ADJUSTMENT_STEP;
|
||||||
this._output.volume = Math.max(0, currentVolume - this._volumeMax * VOLUME_ADJUSTMENT_STEP);
|
} else if (direction == Clutter.ScrollDirection.UP) {
|
||||||
if (this._output.volume < 1) {
|
delta = +VOLUME_ADJUSTMENT_STEP;
|
||||||
this._output.volume = 0;
|
} else if (direction == Clutter.ScrollDirection.SMOOTH) {
|
||||||
if (!prev_muted)
|
let [dx, dy] = event.get_scroll_delta();
|
||||||
this._output.change_is_muted(true);
|
// Use the same math as in the slider.
|
||||||
}
|
delta = -dy / 10;
|
||||||
this._output.push_volume();
|
|
||||||
}
|
}
|
||||||
else if (direction == Clutter.ScrollDirection.UP) {
|
|
||||||
this._output.volume = Math.min(this._volumeMax, currentVolume + this._volumeMax * VOLUME_ADJUSTMENT_STEP);
|
let prev_muted = this._output.is_muted;
|
||||||
this._output.change_is_muted(false);
|
this._output.volume = Math.max(0, currentVolume + this._volumeMax * delta);
|
||||||
this._output.push_volume();
|
if (this._output.volume < 1) {
|
||||||
|
this._output.volume = 0;
|
||||||
|
if (!prev_muted)
|
||||||
|
this._output.change_is_muted(true);
|
||||||
}
|
}
|
||||||
|
this._output.push_volume();
|
||||||
|
|
||||||
this._notifyVolumeChange();
|
this._notifyVolumeChange();
|
||||||
},
|
},
|
||||||
@ -242,6 +250,6 @@ const Indicator = new Lang.Class({
|
|||||||
},
|
},
|
||||||
|
|
||||||
_onScrollEvent: function(actor, event) {
|
_onScrollEvent: function(actor, event) {
|
||||||
this._volumeMenu.scroll(event.get_scroll_direction());
|
this._volumeMenu.scroll(event);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -211,18 +211,19 @@ const ViewSelector = new Lang.Class({
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if(this._activePage) {
|
if(this._activePage) {
|
||||||
|
let oldPage = this._activePage;
|
||||||
Tweener.addTween(this._activePage,
|
Tweener.addTween(this._activePage,
|
||||||
{ opacity: 0,
|
{ opacity: 0,
|
||||||
time: 0.1,
|
time: 0.1,
|
||||||
transition: 'easeOutQuad',
|
transition: 'easeOutQuad',
|
||||||
onComplete: Lang.bind(this,
|
onComplete: Lang.bind(this,
|
||||||
function() {
|
function() {
|
||||||
this._activePage.hide();
|
oldPage.hide();
|
||||||
this._activePage = page;
|
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._activePage = page;
|
||||||
page.show();
|
page.show();
|
||||||
Tweener.addTween(page,
|
Tweener.addTween(page,
|
||||||
{ opacity: 255,
|
{ opacity: 255,
|
||||||
|
@ -265,23 +265,37 @@ const WindowClone = new Lang.Class({
|
|||||||
|
|
||||||
_onScroll : function (actor, event) {
|
_onScroll : function (actor, event) {
|
||||||
let direction = event.get_scroll_direction();
|
let direction = event.get_scroll_direction();
|
||||||
if (direction == Clutter.ScrollDirection.UP) {
|
let delta;
|
||||||
|
|
||||||
|
if (event.is_pointer_emulated())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (direction == Clutter.ScrollDirection.DOWN) {
|
||||||
|
delta = -SCROLL_SCALE_AMOUNT;
|
||||||
|
} else if (direction == Clutter.ScrollDirection.UP) {
|
||||||
|
delta = +SCROLL_SCALE_AMOUNT;
|
||||||
|
} else if (direction == Clutter.ScrollDirection.SMOOTH) {
|
||||||
|
let [dx, dy] = event.get_scroll_delta();
|
||||||
|
delta = -dy * 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (delta > 0) {
|
||||||
if (this._zoomStep == undefined)
|
if (this._zoomStep == undefined)
|
||||||
this._zoomStart();
|
this._zoomStart();
|
||||||
if (this._zoomStep < 100) {
|
if (this._zoomStep < 100) {
|
||||||
this._zoomStep += SCROLL_SCALE_AMOUNT;
|
this._zoomStep += delta;
|
||||||
|
this._zoomStep = Math.min(100, this._zoomStep);
|
||||||
this._zoomUpdate();
|
this._zoomUpdate();
|
||||||
}
|
}
|
||||||
} else if (direction == Clutter.ScrollDirection.DOWN) {
|
} else if (delta < 0) {
|
||||||
if (this._zoomStep > 0) {
|
if (this._zoomStep > 0) {
|
||||||
this._zoomStep -= SCROLL_SCALE_AMOUNT;
|
this._zoomStep += delta;
|
||||||
this._zoomStep = Math.max(0, this._zoomStep);
|
this._zoomStep = Math.max(0, this._zoomStep);
|
||||||
this._zoomUpdate();
|
this._zoomUpdate();
|
||||||
}
|
}
|
||||||
if (this._zoomStep <= 0.0)
|
if (this._zoomStep <= 0.0)
|
||||||
this._zoomEnd();
|
this._zoomEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_zoomUpdate : function () {
|
_zoomUpdate : function () {
|
||||||
|
@ -205,11 +205,11 @@ const WorkspacesView = new Lang.Class({
|
|||||||
this._workspaces[w].positionWindows(Workspace.WindowPositionFlags.ANIMATE);
|
this._workspaces[w].positionWindows(Workspace.WindowPositionFlags.ANIMATE);
|
||||||
},
|
},
|
||||||
|
|
||||||
_scrollToActive: function(showAnimation) {
|
_scrollToActive: function() {
|
||||||
let active = global.screen.get_active_workspace_index();
|
let active = global.screen.get_active_workspace_index();
|
||||||
|
|
||||||
this._updateWorkspaceActors(showAnimation);
|
this._updateWorkspaceActors(true);
|
||||||
this._updateScrollAdjustment(active, showAnimation);
|
this._updateScrollAdjustment(active);
|
||||||
},
|
},
|
||||||
|
|
||||||
// Update workspace actors parameters
|
// Update workspace actors parameters
|
||||||
@ -267,26 +267,21 @@ const WorkspacesView = new Lang.Class({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_updateScrollAdjustment: function(index, showAnimation) {
|
_updateScrollAdjustment: function(index) {
|
||||||
if (this._scrolling)
|
if (this._scrolling)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this._animatingScroll = true;
|
this._animatingScroll = true;
|
||||||
|
|
||||||
if (showAnimation) {
|
Tweener.addTween(this.scrollAdjustment, {
|
||||||
Tweener.addTween(this.scrollAdjustment, {
|
value: index,
|
||||||
value: index,
|
time: WORKSPACE_SWITCH_TIME,
|
||||||
time: WORKSPACE_SWITCH_TIME,
|
transition: 'easeOutQuad',
|
||||||
transition: 'easeOutQuad',
|
onComplete: Lang.bind(this,
|
||||||
onComplete: Lang.bind(this,
|
function() {
|
||||||
function() {
|
this._animatingScroll = false;
|
||||||
this._animatingScroll = false;
|
})
|
||||||
})
|
});
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.scrollAdjustment.value = index;
|
|
||||||
this._animatingScroll = false;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
updateWorkspaces: function(oldNumWorkspaces, newNumWorkspaces) {
|
updateWorkspaces: function(oldNumWorkspaces, newNumWorkspaces) {
|
||||||
@ -313,7 +308,7 @@ const WorkspacesView = new Lang.Class({
|
|||||||
if (this._scrolling)
|
if (this._scrolling)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this._scrollToActive(true);
|
this._scrollToActive();
|
||||||
},
|
},
|
||||||
|
|
||||||
_onDestroy: function() {
|
_onDestroy: function() {
|
||||||
@ -387,24 +382,11 @@ const WorkspacesView = new Lang.Class({
|
|||||||
this._scrolling = true;
|
this._scrolling = true;
|
||||||
},
|
},
|
||||||
|
|
||||||
endSwipeScroll: function(result) {
|
endSwipeScroll: function() {
|
||||||
this._scrolling = false;
|
this._scrolling = false;
|
||||||
|
|
||||||
if (result == Overview.SwipeScrollResult.CLICK) {
|
|
||||||
let [x, y, mod] = global.get_pointer();
|
|
||||||
let actor = global.stage.get_actor_at_pos(Clutter.PickMode.ALL,
|
|
||||||
x, y);
|
|
||||||
|
|
||||||
// Only switch to the workspace when there's no application
|
|
||||||
// windows open. The problem is that it's too easy to miss
|
|
||||||
// an app window and get the wrong one focused.
|
|
||||||
let active = global.screen.get_active_workspace_index();
|
|
||||||
if (this._workspaces[active].isEmpty() &&
|
|
||||||
this.actor.contains(actor))
|
|
||||||
Main.overview.hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure title captions etc are shown as necessary
|
// Make sure title captions etc are shown as necessary
|
||||||
|
this._scrollToActive();
|
||||||
this._updateVisibility();
|
this._updateVisibility();
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -456,9 +438,23 @@ const WorkspacesDisplay = new Lang.Class({
|
|||||||
this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
|
this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
|
||||||
this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
|
this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
|
||||||
this.actor.connect('allocate', Lang.bind(this, this._allocate));
|
this.actor.connect('allocate', Lang.bind(this, this._allocate));
|
||||||
this.actor.connect('notify::mapped', Lang.bind(this, this._setupSwipeScrolling));
|
|
||||||
this.actor.connect('parent-set', Lang.bind(this, this._parentSet));
|
this.actor.connect('parent-set', Lang.bind(this, this._parentSet));
|
||||||
this.actor.set_clip_to_allocation(true);
|
this.actor.set_clip_to_allocation(true);
|
||||||
|
let action = new Clutter.PanAction();
|
||||||
|
action.connect('pan', Lang.bind(this, this._onPan));
|
||||||
|
action.connect('gesture-begin', Lang.bind(this, function() {
|
||||||
|
for (let i = 0; i < this._workspacesViews.length; i++)
|
||||||
|
this._workspacesViews[i].startSwipeScroll();
|
||||||
|
return true;
|
||||||
|
}));
|
||||||
|
action.connect('gesture-end', Lang.bind(this, function() {
|
||||||
|
for (let i = 0; i < this._workspacesViews.length; i++)
|
||||||
|
this._workspacesViews[i].endSwipeScroll();
|
||||||
|
}));
|
||||||
|
Main.overview.addAction(action);
|
||||||
|
this.actor.connect('notify::mapped', Lang.bind(this, function() {
|
||||||
|
action.enabled = this.actor.mapped;
|
||||||
|
}));
|
||||||
|
|
||||||
let controls = new St.Bin({ style_class: 'workspace-controls',
|
let controls = new St.Bin({ style_class: 'workspace-controls',
|
||||||
request_mode: Clutter.RequestMode.WIDTH_FOR_HEIGHT,
|
request_mode: Clutter.RequestMode.WIDTH_FOR_HEIGHT,
|
||||||
@ -531,6 +527,13 @@ const WorkspacesDisplay = new Lang.Class({
|
|||||||
Lang.bind(this, this._updateSwitcherVisibility));
|
Lang.bind(this, this._updateSwitcherVisibility));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_onPan: function(action) {
|
||||||
|
let [dist, dx, dy] = action.get_motion_delta(0);
|
||||||
|
let adjustment = this._scrollAdjustment;
|
||||||
|
adjustment.value -= (dy / this.actor.height) * adjustment.page_size;
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
_updateSwitcherVisibility: function() {
|
_updateSwitcherVisibility: function() {
|
||||||
this._thumbnailsBox.actor.visible =
|
this._thumbnailsBox.actor.visible =
|
||||||
this._settings.get_boolean('dynamic-workspaces') ||
|
this._settings.get_boolean('dynamic-workspaces') ||
|
||||||
@ -640,33 +643,6 @@ const WorkspacesDisplay = new Lang.Class({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_setupSwipeScrolling: function() {
|
|
||||||
if (this._swipeScrollBeginId)
|
|
||||||
Main.overview.disconnect(this._swipeScrollBeginId);
|
|
||||||
this._swipeScrollBeginId = 0;
|
|
||||||
|
|
||||||
if (this._swipeScrollEndId)
|
|
||||||
Main.overview.disconnect(this._swipeScrollEndId);
|
|
||||||
this._swipeScrollEndId = 0;
|
|
||||||
|
|
||||||
if (!this.actor.mapped)
|
|
||||||
return;
|
|
||||||
|
|
||||||
let direction = Overview.SwipeScrollDirection.VERTICAL;
|
|
||||||
Main.overview.setScrollAdjustment(this._scrollAdjustment,
|
|
||||||
direction);
|
|
||||||
this._swipeScrollBeginId = Main.overview.connect('swipe-scroll-begin',
|
|
||||||
Lang.bind(this, function() {
|
|
||||||
for (let i = 0; i < this._workspacesViews.length; i++)
|
|
||||||
this._workspacesViews[i].startSwipeScroll();
|
|
||||||
}));
|
|
||||||
this._swipeScrollEndId = Main.overview.connect('swipe-scroll-end',
|
|
||||||
Lang.bind(this, function(overview, result) {
|
|
||||||
for (let i = 0; i < this._workspacesViews.length; i++)
|
|
||||||
this._workspacesViews[i].endSwipeScroll(result);
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
|
|
||||||
_workspacesOnlyOnPrimaryChanged: function() {
|
_workspacesOnlyOnPrimaryChanged: function() {
|
||||||
this._workspacesOnlyOnPrimary = this._settings.get_boolean('workspaces-only-on-primary');
|
this._workspacesOnlyOnPrimary = this._settings.get_boolean('workspaces-only-on-primary');
|
||||||
|
|
||||||
@ -706,7 +682,6 @@ const WorkspacesDisplay = new Lang.Class({
|
|||||||
this._scrollAdjustment = view.scrollAdjustment;
|
this._scrollAdjustment = view.scrollAdjustment;
|
||||||
this._scrollAdjustment.connect('notify::value',
|
this._scrollAdjustment.connect('notify::value',
|
||||||
Lang.bind(this, this._scrollValueChanged));
|
Lang.bind(this, this._scrollValueChanged));
|
||||||
this._setupSwipeScrolling();
|
|
||||||
}
|
}
|
||||||
this._workspacesViews.push(view);
|
this._workspacesViews.push(view);
|
||||||
}
|
}
|
||||||
|
@ -1007,54 +1007,6 @@ shell_global_end_modal (ShellGlobal *global,
|
|||||||
meta_plugin_end_modal (global->plugin, timestamp);
|
meta_plugin_end_modal (global->plugin, timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* shell_global_create_pointer_barrier:
|
|
||||||
* @global: a #ShellGlobal
|
|
||||||
* @x1: left X coordinate
|
|
||||||
* @y1: top Y coordinate
|
|
||||||
* @x2: right X coordinate
|
|
||||||
* @y2: bottom Y coordinate
|
|
||||||
* @directions: The directions we're allowed to pass through
|
|
||||||
*
|
|
||||||
* If supported by X creates a pointer barrier.
|
|
||||||
*
|
|
||||||
* Return value: value you can pass to shell_global_destroy_pointer_barrier()
|
|
||||||
*/
|
|
||||||
guint32
|
|
||||||
shell_global_create_pointer_barrier (ShellGlobal *global,
|
|
||||||
int x1, int y1, int x2, int y2,
|
|
||||||
int directions)
|
|
||||||
{
|
|
||||||
#if HAVE_XFIXESCREATEPOINTERBARRIER
|
|
||||||
return (guint32)
|
|
||||||
XFixesCreatePointerBarrier (global->xdisplay,
|
|
||||||
DefaultRootWindow (global->xdisplay),
|
|
||||||
x1, y1,
|
|
||||||
x2, y2,
|
|
||||||
directions,
|
|
||||||
0, NULL);
|
|
||||||
#else
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* shell_global_destroy_pointer_barrier:
|
|
||||||
* @global: a #ShellGlobal
|
|
||||||
* @barrier: a pointer barrier
|
|
||||||
*
|
|
||||||
* Destroys the @barrier created by shell_global_create_pointer_barrier().
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
shell_global_destroy_pointer_barrier (ShellGlobal *global, guint32 barrier)
|
|
||||||
{
|
|
||||||
#if HAVE_XFIXESCREATEPOINTERBARRIER
|
|
||||||
g_return_if_fail (barrier > 0);
|
|
||||||
|
|
||||||
XFixesDestroyPointerBarrier (global->xdisplay, (PointerBarrier)barrier);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Code to close all file descriptors before we exec; copied from gspawn.c in GLib.
|
/* Code to close all file descriptors before we exec; copied from gspawn.c in GLib.
|
||||||
*
|
*
|
||||||
* Authors: Padraig O'Briain, Matthias Clasen, Lennart Poettering
|
* Authors: Padraig O'Briain, Matthias Clasen, Lennart Poettering
|
||||||
|
@ -70,15 +70,6 @@ void shell_global_set_cursor (ShellGlobal *global,
|
|||||||
ShellCursor type);
|
ShellCursor type);
|
||||||
void shell_global_unset_cursor (ShellGlobal *global);
|
void shell_global_unset_cursor (ShellGlobal *global);
|
||||||
|
|
||||||
guint32 shell_global_create_pointer_barrier (ShellGlobal *global,
|
|
||||||
int x1,
|
|
||||||
int y1,
|
|
||||||
int x2,
|
|
||||||
int y2,
|
|
||||||
int directions);
|
|
||||||
void shell_global_destroy_pointer_barrier (ShellGlobal *global,
|
|
||||||
guint32 barrier);
|
|
||||||
|
|
||||||
void shell_global_get_pointer (ShellGlobal *global,
|
void shell_global_get_pointer (ShellGlobal *global,
|
||||||
int *x,
|
int *x,
|
||||||
int *y,
|
int *y,
|
||||||
|
@ -665,6 +665,45 @@ st_scroll_view_allocate (ClutterActor *actor,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
adjust_with_delta (StAdjustment *adj,
|
||||||
|
gdouble delta)
|
||||||
|
{
|
||||||
|
gdouble new_value, page_size, scroll_unit;
|
||||||
|
|
||||||
|
g_object_get (adj,
|
||||||
|
"page-size", &page_size,
|
||||||
|
NULL);
|
||||||
|
scroll_unit = pow (page_size, 2.0 / 3.0);
|
||||||
|
|
||||||
|
new_value = st_adjustment_get_value (adj) + delta * scroll_unit;
|
||||||
|
st_adjustment_set_value (adj, new_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
adjust_with_direction (StAdjustment *adj,
|
||||||
|
ClutterScrollDirection direction)
|
||||||
|
{
|
||||||
|
gdouble delta;
|
||||||
|
|
||||||
|
switch (direction)
|
||||||
|
{
|
||||||
|
case CLUTTER_SCROLL_UP:
|
||||||
|
case CLUTTER_SCROLL_LEFT:
|
||||||
|
delta = -1.0;
|
||||||
|
break;
|
||||||
|
case CLUTTER_SCROLL_RIGHT:
|
||||||
|
case CLUTTER_SCROLL_DOWN:
|
||||||
|
delta = 1.0;
|
||||||
|
break;
|
||||||
|
case CLUTTER_SCROLL_SMOOTH:
|
||||||
|
g_assert_not_reached ();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
adjust_with_delta (adj, delta);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
st_scroll_view_style_changed (StWidget *widget)
|
st_scroll_view_style_changed (StWidget *widget)
|
||||||
{
|
{
|
||||||
@ -687,57 +726,32 @@ st_scroll_view_scroll_event (ClutterActor *self,
|
|||||||
ClutterScrollEvent *event)
|
ClutterScrollEvent *event)
|
||||||
{
|
{
|
||||||
StScrollViewPrivate *priv = ST_SCROLL_VIEW (self)->priv;
|
StScrollViewPrivate *priv = ST_SCROLL_VIEW (self)->priv;
|
||||||
gdouble value, step, hvalue, vvalue, delta_x, delta_y;
|
|
||||||
|
|
||||||
/* don't handle scroll events if requested not to */
|
/* don't handle scroll events if requested not to */
|
||||||
if (!priv->mouse_scroll)
|
if (!priv->mouse_scroll)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
switch (event->direction)
|
/* throw away this garbage event. we want smooth scrolling. */
|
||||||
{
|
if (clutter_event_is_pointer_emulated ((ClutterEvent *) event))
|
||||||
case CLUTTER_SCROLL_SMOOTH:
|
return TRUE;
|
||||||
clutter_event_get_scroll_delta ((ClutterEvent *)event,
|
|
||||||
&delta_x, &delta_y);
|
|
||||||
g_object_get (priv->hadjustment,
|
|
||||||
"value", &hvalue,
|
|
||||||
NULL);
|
|
||||||
g_object_get (priv->vadjustment,
|
|
||||||
"value", &vvalue,
|
|
||||||
NULL);
|
|
||||||
break;
|
|
||||||
case CLUTTER_SCROLL_UP:
|
|
||||||
case CLUTTER_SCROLL_DOWN:
|
|
||||||
g_object_get (priv->vadjustment,
|
|
||||||
"step-increment", &step,
|
|
||||||
"value", &value,
|
|
||||||
NULL);
|
|
||||||
break;
|
|
||||||
case CLUTTER_SCROLL_LEFT:
|
|
||||||
case CLUTTER_SCROLL_RIGHT:
|
|
||||||
g_object_get (priv->hadjustment,
|
|
||||||
"step-increment", &step,
|
|
||||||
"value", &value,
|
|
||||||
NULL);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (event->direction)
|
switch (event->direction)
|
||||||
{
|
{
|
||||||
case CLUTTER_SCROLL_SMOOTH:
|
case CLUTTER_SCROLL_SMOOTH:
|
||||||
st_adjustment_set_value (priv->hadjustment, hvalue + delta_x);
|
{
|
||||||
st_adjustment_set_value (priv->vadjustment, vvalue + delta_y);
|
gdouble delta_x, delta_y;
|
||||||
|
clutter_event_get_scroll_delta ((ClutterEvent *)event, &delta_x, &delta_y);
|
||||||
|
adjust_with_delta (priv->hadjustment, delta_x);
|
||||||
|
adjust_with_delta (priv->vadjustment, delta_y);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case CLUTTER_SCROLL_UP:
|
case CLUTTER_SCROLL_UP:
|
||||||
st_adjustment_set_value (priv->vadjustment, value - step);
|
|
||||||
break;
|
|
||||||
case CLUTTER_SCROLL_DOWN:
|
case CLUTTER_SCROLL_DOWN:
|
||||||
st_adjustment_set_value (priv->vadjustment, value + step);
|
adjust_with_direction (priv->vadjustment, event->direction);
|
||||||
break;
|
break;
|
||||||
case CLUTTER_SCROLL_LEFT:
|
case CLUTTER_SCROLL_LEFT:
|
||||||
st_adjustment_set_value (priv->hadjustment, value - step);
|
|
||||||
break;
|
|
||||||
case CLUTTER_SCROLL_RIGHT:
|
case CLUTTER_SCROLL_RIGHT:
|
||||||
st_adjustment_set_value (priv->hadjustment, value + step);
|
adjust_with_direction (priv->hadjustment, event->direction);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user