Skip to content

Commit 91886ac

Browse files
authored
smart-panel v1.4.4: Does not use Mainloop in code - Increased stability (#827)
1 parent 6e702e4 commit 91886ac

File tree

3 files changed

+242
-28
lines changed

3 files changed

+242
-28
lines changed

smart-panel@mohammad-sn/files/smart-panel@mohammad-sn/extension.js

Lines changed: 62 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ const Clutter = imports.gi.Clutter;
1818
const GLib = imports.gi.GLib;
1919
const Lang = imports.lang;
2020
const Main = imports.ui.main;
21-
const Mainloop = imports.mainloop;
2221
const Meta = imports.gi.Meta
2322
const Settings = imports.ui.settings;
2423
const St = imports.gi.St;
@@ -34,6 +33,19 @@ const TimelineSwitcher = imports.ui.appSwitcher.timelineSwitcher;
3433
const ClassicSwitcher = imports.ui.appSwitcher.classicSwitcher;
3534
const AppSwitcher = imports.ui.appSwitcher.appSwitcher;
3635

36+
const {
37+
_sourceIds,
38+
timeout_add_seconds,
39+
timeout_add,
40+
setTimeout,
41+
clearTimeout,
42+
setInterval,
43+
clearInterval,
44+
source_exists,
45+
source_remove,
46+
remove_all_sources
47+
} = require("./mainloopTools");
48+
3749

3850
let newSmartPanelExt = null;
3951

@@ -99,6 +111,7 @@ SmartPanelExt.prototype = {
99111

100112
disable: function() {
101113
this.is_disabled = true;
114+
remove_all_sources();
102115
// FIXME: These lines make Cinnamon unstable!
103116
//~ if (this.sr != null) this._panel.disconnect(this.sr);
104117
//~ if (this.en != null) this._panel.disconnect(this.en);
@@ -110,11 +123,16 @@ SmartPanelExt.prototype = {
110123
enable: function() {
111124
this._panel.reactive = true;
112125
this.is_disabled = false;
113-
this.sr = this._panel.connect('scroll-event' , Lang.bind(this, this._onScroll));
114-
this.en = this._panel.connect('enter-event' , Lang.bind(this, this._onEntered));
115-
this.lv = this._panel.connect('leave-event' , Lang.bind(this, this._onLeave));
116-
this.bp = this._panel.connect('button-press-event' , Lang.bind(this, this._onButtonPress));
117-
this.br = this._panel.connect('button-release-event', Lang.bind(this, this._onButtonRelease));
126+
//~ this.sr = this._panel.connect('scroll-event' , Lang.bind(this, this._onScroll));
127+
//~ this.en = this._panel.connect('enter-event' , Lang.bind(this, this._onEntered));
128+
//~ this.lv = this._panel.connect('leave-event' , Lang.bind(this, this._onLeave));
129+
//~ this.bp = this._panel.connect('button-press-event' , Lang.bind(this, this._onButtonPress));
130+
//~ this.br = this._panel.connect('button-release-event', Lang.bind(this, this._onButtonRelease));
131+
this.sr = this._panel.connect('scroll-event' , (actor, event) => { this._onScroll(actor, event) });
132+
this.en = this._panel.connect('enter-event' , (actor, event) => { this._onEntered(actor, event) });
133+
this.lv = this._panel.connect('leave-event' , (actor, event) => { this._onLeave(actor, event) });
134+
this.bp = this._panel.connect('button-press-event' , (actor, event) => { this._onButtonPress(actor, event) });
135+
this.br = this._panel.connect('button-release-event', (actor, event) => { this._onButtonRelease(actor, event) });
118136
},
119137

120138
_onEntered : function(actor, event) {
@@ -146,7 +164,7 @@ SmartPanelExt.prototype = {
146164
}
147165
else{
148166
this.dblb = true;
149-
Mainloop.timeout_add(this.dblb_T, Lang.bind(this,function() { this.dblb = false; }));
167+
timeout_add(this.dblb_T, () => { this.dblb = false; });
150168
}
151169
}
152170
else if (button == 2) {
@@ -361,13 +379,15 @@ SmartPanelExt.prototype = {
361379
if (!this._switcherIsRuning) new myCoverflowSwitcher(this);
362380
this._switcherIsRuning = true;
363381
let delay = global.settings.get_int("alttab-switcher-delay");
364-
Mainloop.timeout_add(delay, Lang.bind(this, function(){ this._switcherIsRuning = false; }));
382+
//~ timeout_add(delay, Lang.bind(this, function(){ this._switcherIsRuning = false; }));
383+
timeout_add(delay, () => { this._switcherIsRuning = false; });
365384
}
366385
else if (style == 'timeline'){
367386
if (!this._switcherIsRuning) new myTimelineSwitcher(this);
368387
this._switcherIsRuning = true;
369388
let delay = global.settings.get_int("alttab-switcher-delay");
370-
Mainloop.timeout_add(delay, Lang.bind(this, function(){ this._switcherIsRuning = false; }));
389+
//~ timeout_add(delay, Lang.bind(this, function(){ this._switcherIsRuning = false; }));
390+
timeout_add(delay, () => { this._switcherIsRuning = false; });
371391
}
372392
else {
373393
new myClassicSwitcher(this);
@@ -519,9 +539,12 @@ myClassicSwitcher.prototype = {
519539

520540
this._updateList(0);
521541

522-
this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
523-
this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
524-
this.actor.connect('allocate', Lang.bind(this, this._allocate));
542+
//~ this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
543+
//~ this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
544+
//~ this.actor.connect('allocate', Lang.bind(this, this._allocate));
545+
this.actor.connect('get-preferred-width', () => { this._getPreferredWidth() });
546+
this.actor.connect('get-preferred-height', () => { this._getPreferredHeight() });
547+
this.actor.connect('allocate', () => { this._allocate() });
525548

526549
// Need to force an allocation so we can figure out whether we
527550
// need to scroll when selecting
@@ -537,12 +560,16 @@ myClassicSwitcher.prototype = {
537560
else {
538561
this._disableHover();
539562

540-
this.actor.connect('key-press-event', Lang.bind(this, this._keyPressEvent));
541-
this.actor.connect('key-release-event', Lang.bind(this, this._keyReleaseEvent));
542-
this.actor.connect('scroll-event', Lang.bind(this, this._scrollEvent));
543-
this.actor.connect('button-press-event', Lang.bind(this, this.owndestroy));
563+
//~ this.actor.connect('key-press-event', Lang.bind(this, this._keyPressEvent));
564+
//~ this.actor.connect('key-release-event', Lang.bind(this, this._keyReleaseEvent));
565+
//~ this.actor.connect('scroll-event', Lang.bind(this, this._scrollEvent));
566+
//~ this.actor.connect('button-press-event', Lang.bind(this, this.owndestroy));
567+
this.actor.connect('key-press-event', () => { this._keyPressEvent() });
568+
this.actor.connect('key-release-event', () => { this._keyReleaseEvent() });
569+
this.actor.connect('scroll-event', () => { this._scrollEvent() });
570+
this.actor.connect('button-press-event', () => { this.owndestroy() });
544571
let delay = global.settings.get_int("alttab-switcher-delay");
545-
this._initialDelayTimeoutId = Mainloop.timeout_add(delay, Lang.bind(this, this._show));
572+
this._initialDelayTimeoutId = timeout_add(delay, () => { this._show() });
546573
this._currentIndex--;
547574
}
548575
return this._haveModal;
@@ -580,12 +607,16 @@ myTimelineSwitcher.prototype = {
580607
else {
581608
this._disableHover();
582609

583-
this.actor.connect('key-press-event', Lang.bind(this, this._keyPressEvent));
584-
this.actor.connect('key-release-event', Lang.bind(this, this._keyReleaseEvent));
585-
this.actor.connect('scroll-event', Lang.bind(this, this._scrollEvent));
586-
this.actor.connect('button-press-event', Lang.bind(this, this.owndestroy));
610+
//~ this.actor.connect('key-press-event', Lang.bind(this, this._keyPressEvent));
611+
//~ this.actor.connect('key-release-event', Lang.bind(this, this._keyReleaseEvent));
612+
//~ this.actor.connect('scroll-event', Lang.bind(this, this._scrollEvent));
613+
//~ this.actor.connect('button-press-event', Lang.bind(this, this.owndestroy));
614+
this.actor.connect('key-press-event', () => { this._keyPressEvent() });
615+
this.actor.connect('key-release-event', () => { this._keyReleaseEvent() });
616+
this.actor.connect('scroll-event', () => { this._scrollEvent() });
617+
this.actor.connect('button-press-event', () => { this.owndestroy() });
587618
let delay = global.settings.get_int("alttab-switcher-delay");
588-
this._initialDelayTimeoutId = Mainloop.timeout_add(delay, Lang.bind(this, this._show));
619+
this._initialDelayTimeoutId = timeout_add(delay, () => { this._show() });
589620
this._currentIndex--;
590621
}
591622
return this._haveModal;
@@ -624,12 +655,16 @@ myCoverflowSwitcher.prototype = {
624655
else {
625656
this._disableHover();
626657

627-
this.actor.connect('key-press-event', Lang.bind(this, this._keyPressEvent));
628-
this.actor.connect('key-release-event', Lang.bind(this, this._keyReleaseEvent));
629-
this.actor.connect('scroll-event', Lang.bind(this, this._scrollEvent));
630-
this.actor.connect('button-press-event', Lang.bind(this, this.owndestroy));
658+
//~ this.actor.connect('key-press-event', Lang.bind(this, this._keyPressEvent));
659+
//~ this.actor.connect('key-release-event', Lang.bind(this, this._keyReleaseEvent));
660+
//~ this.actor.connect('scroll-event', Lang.bind(this, this._scrollEvent));
661+
//~ this.actor.connect('button-press-event', Lang.bind(this, this.owndestroy));
662+
this.actor.connect('key-press-event', () => { this._keyPressEvent() });
663+
this.actor.connect('key-release-event', () => { this._keyReleaseEvent() });
664+
this.actor.connect('scroll-event', () => { this._scrollEvent() });
665+
this.actor.connect('button-press-event', () => { this.owndestroy() });
631666
let delay = global.settings.get_int("alttab-switcher-delay");
632-
this._initialDelayTimeoutId = Mainloop.timeout_add(delay, Lang.bind(this, this._show));
667+
this._initialDelayTimeoutId = timeout_add(delay, () => { this._show() });
633668
this._currentIndex--;
634669
}
635670
return this._haveModal;
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
const GLib = imports.gi.GLib;
2+
3+
/**
4+
* _sourceIds
5+
* Array containing IDs of all looping loops.
6+
*/
7+
var _sourceIds = [];
8+
9+
/**
10+
* timeout_add_seconds
11+
*
12+
* @callback (function) is executed every @sec (number) seconds
13+
* with @params (dictionnary as {'key1': value1, 'key2': value2, ...}).
14+
*
15+
* @params is often null.
16+
*
17+
*/
18+
function timeout_add_seconds(sec, callback, params=null) {
19+
let id = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, sec, callback);
20+
if (id && (_sourceIds.indexOf(id) === -1)) _sourceIds.push(id);
21+
return id;
22+
}
23+
24+
/**
25+
* timeout_add_seconds
26+
*
27+
* @callback (function) is executed every @ms (number) milliseconds
28+
* with @params (dictionnary as {'key1': value1, 'key2': value2, ...}).
29+
*
30+
* @params is often null.
31+
*
32+
*/
33+
function timeout_add(ms, callback, params=null) {
34+
let id = GLib.timeout_add(GLib.PRIORITY_DEFAULT, ms, callback);
35+
if (id && (_sourceIds.indexOf(id) === -1)) _sourceIds.push(id);
36+
return id;
37+
}
38+
39+
/**
40+
* setTimeout:
41+
* @callback (function): Function to call at the end of the timeout.
42+
* @ms (number): Milliseconds until the timeout expires.
43+
*
44+
* Convenience wrapper for a Mainloop.timeout_add loop that
45+
* returns false.
46+
*
47+
* Returns (number): The ID of the loop.
48+
*/
49+
function setTimeout(callback, ms) {
50+
let args = [];
51+
if (arguments.length > 2) {
52+
args = args.slice.call(arguments, 2);
53+
}
54+
55+
let id = GLib.timeout_add(GLib.PRIORITY_DEFAULT,
56+
ms,
57+
() => {
58+
callback.call(null, ...args);
59+
return false; // Stop repeating
60+
}
61+
);
62+
63+
if (id && (_sourceIds.indexOf(id) === -1)) _sourceIds.push(id);
64+
65+
return id;
66+
}
67+
68+
/**
69+
* clearTimeout:
70+
* @id (number): The ID of the loop to remove.
71+
*
72+
* Convenience wrapper for Mainloop.source_remove.
73+
*/
74+
function clearTimeout(id) {
75+
if (id) {
76+
source_remove(id);
77+
}
78+
}
79+
80+
81+
/**
82+
* setInterval:
83+
* @callback (function): Function to call on every interval.
84+
* @ms (number): Milliseconds between invocations.
85+
*
86+
* Convenience wrapper for a Mainloop.timeout_add loop that
87+
* returns true.
88+
*
89+
* Returns (number): The ID of the loop.
90+
*/
91+
function setInterval(callback, ms) {
92+
let args = [];
93+
if (arguments.length > 2) {
94+
args = args.slice.call(arguments, 2);
95+
}
96+
97+
let id = GLib.timeout_add(GLib.PRIORITY_DEFAULT, ms, () => {
98+
callback.call(null, ...args);
99+
return true; // Repeat
100+
});
101+
102+
if (id && (_sourceIds.indexOf(id) === -1)) _sourceIds.push(id);
103+
104+
return id;
105+
}
106+
107+
/**
108+
* clearInterval:
109+
* @id (number): The ID of the loop to remove.
110+
*
111+
* Convenience wrapper for Mainloop.source_remove.
112+
*/
113+
function clearInterval(id) {
114+
if (id) {
115+
source_remove(id);
116+
}
117+
};
118+
119+
/**
120+
* source_exists
121+
*
122+
* @id (number, or null)
123+
*
124+
* Checks if @id is well the ID of a loop.
125+
*
126+
*/
127+
function source_exists(id) {
128+
let _id = id;
129+
if (!_id) return false;
130+
return (GLib.MainContext.default().find_source_by_id(_id) != null);
131+
}
132+
133+
/**
134+
* source_remove
135+
*
136+
* @id (number): The ID of the loop to stop.
137+
* @remove_from_sourceIds (boolean): *true* (by default) when we want to
138+
* remove @id from _sourceIds. May be *false* for internal functionning.
139+
*
140+
* Convenience wrapper for a Mainloop.source_remove(id) that returns a
141+
* boolean.
142+
*/
143+
function source_remove(id, remove_from_sourceIds=true) {
144+
if (source_exists(id)) {
145+
GLib.source_remove(id);
146+
if (remove_from_sourceIds) {
147+
const pos = _sourceIds.indexOf(id);
148+
if (pos > -1) _sourceIds.splice(pos, 1);
149+
}
150+
return true;
151+
}
152+
return false;
153+
}
154+
155+
/**
156+
* remove_all_sources
157+
*
158+
* Execute it when removing the spice.
159+
* Tries to delete all remaining sources, in order to remove all loops.
160+
*/
161+
function remove_all_sources() {
162+
while (_sourceIds.length > 0) {
163+
let id = _sourceIds.pop();
164+
source_remove(id, false);
165+
}
166+
}
167+
168+
module.exports = {
169+
_sourceIds,
170+
timeout_add_seconds,
171+
timeout_add,
172+
setTimeout,
173+
clearTimeout,
174+
setInterval,
175+
clearInterval,
176+
source_exists,
177+
source_remove,
178+
remove_all_sources
179+
}

smart-panel@mohammad-sn/files/smart-panel@mohammad-sn/metadata.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
],
2424
"description": "Switch between workspaces, show desktop, activate overview or expo, ... by scrolling, double click, mouse gestures etc on free space of the panel.",
2525
"name": "Smart Panel",
26-
"version": "1.4.3",
26+
"version": "1.4.4",
2727
"uuid": "smart-panel@mohammad-sn",
2828
"url": "https://cinnamon-spices.linuxmint.com/extensions/view/80",
2929
"author": "mohammad-sn"

0 commit comments

Comments
 (0)