mirror of
https://github.com/moparisthebest/FireTray
synced 2025-01-09 12:38:04 -05:00
use nested timers to mimic sleep()
thread.processNextEvent() is prohibited in Firefox (though used in mozmill/util.js). Nested timers are a bit twisted and ugly. Need to check |yield| and generators: http://unixpapa.com/js/sleep.html, dactyl/base.jsm (K. Maglione)
This commit is contained in:
parent
c4c5a3425b
commit
5882e3b9c5
@ -15,7 +15,7 @@ let log = firetray.Logging.getLogger("firetray.Chat");
|
||||
firetray.Chat = {
|
||||
initialized: false,
|
||||
observedTopics: {},
|
||||
shouldAcknowledgeConvs: {
|
||||
shouldAcknowledgeConvs: { // TODO: FOUDIL: rename to convsToAcknoledge
|
||||
ids: {},
|
||||
length: function(){return Object.keys(this.ids).length;}
|
||||
},
|
||||
@ -136,7 +136,8 @@ firetray.Chat = {
|
||||
if (this.shouldAcknowledgeConvs.length() > 1) return; // already calling attention
|
||||
|
||||
this.setUrgencyMaybe(conv);
|
||||
firetray.ChatStatusIcon.startIconBlinking();
|
||||
// firetray.ChatStatusIcon.startIconBlinking();
|
||||
firetray.ChatStatusIcon.startCrossFade();
|
||||
},
|
||||
|
||||
/**
|
||||
@ -162,7 +163,8 @@ firetray.Chat = {
|
||||
if(this.shouldAcknowledgeConvs.length() === 0) {
|
||||
log.debug("do stop icon blinking !!!");
|
||||
firetray.ChatStatusIcon.setUrgency(xid, false);
|
||||
firetray.ChatStatusIcon.stopIconBlinking();
|
||||
// firetray.ChatStatusIcon.stopIconBlinking();
|
||||
firetray.ChatStatusIcon.stopCrossFade();
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -40,6 +40,7 @@ firetray.ChatStatusIcon = {
|
||||
themedIconNameCurrent: null,
|
||||
signals: {'focus-in': {callback: {}, handler: {}}},
|
||||
timers: {},
|
||||
events: {},
|
||||
|
||||
init: function() {
|
||||
if (!firetray.Handler.inMailApp) throw "ChatStatusIcon for mail app only";
|
||||
@ -73,6 +74,11 @@ firetray.ChatStatusIcon = {
|
||||
},
|
||||
|
||||
setIconImageFromGIcon: function(gicon) {
|
||||
if (firetray.Chat.shouldAcknowledgeConvs.length()) {
|
||||
this.events['icon-changed'] = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!firetray.ChatStatusIcon.trayIcon || !gicon)
|
||||
log.error("Icon missing");
|
||||
gtk.gtk_status_icon_set_from_gicon(firetray.ChatStatusIcon.trayIcon, gicon);
|
||||
@ -91,32 +97,18 @@ firetray.ChatStatusIcon = {
|
||||
* EXPERIMENTAL fancy blinking.
|
||||
* TODO: how to wait for last fade in to restore themedIconNameCurrent
|
||||
*/
|
||||
crossFade: function() {
|
||||
|
||||
/* borrowed from mozmill utils.js*/
|
||||
function sleep(milliseconds) {
|
||||
var timeup = false;
|
||||
function wait() { timeup = true; }
|
||||
let timer = Components.classes["@mozilla.org/timer;1"]
|
||||
.createInstance(Components.interfaces.nsITimer);
|
||||
timer.initWithCallback(wait, milliseconds, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
|
||||
|
||||
var thread = Components.classes["@mozilla.org/thread-manager;1"].
|
||||
getService().currentThread;
|
||||
while(!timeup) {
|
||||
thread.processNextEvent(true);
|
||||
}
|
||||
}
|
||||
startCrossFade: function() {
|
||||
this.crossFade(this.buildPixBuf());
|
||||
},
|
||||
|
||||
buildPixBuf: function() {
|
||||
let icon_theme = gtk.gtk_icon_theme_get_for_screen(gdk.gdk_screen_get_default());
|
||||
firetray.ChatStatusIcon.timers['cross-fade'] = firetray.Utils.timer(
|
||||
500, Ci.nsITimer.TYPE_REPEATING_SLACK, function() {
|
||||
|
||||
// get pixbuf
|
||||
let arry = gobject.gchar.ptr.array()(2);
|
||||
arry[0] = gobject.gchar.array()(firetray.ChatStatusIcon.themedIconNameCurrent);
|
||||
arry[1] = null;
|
||||
log.debug("theme="+icon_theme+", arry="+arry);
|
||||
log.debug("icon name="+firetray.ChatStatusIcon.themedIconNameCurrent+", theme="+icon_theme+", arry="+arry);
|
||||
let icon_info = gtk.gtk_icon_theme_choose_icon(icon_theme, arry, 22, gtk.GTK_ICON_LOOKUP_FORCE_SIZE);
|
||||
|
||||
// create pixbuf
|
||||
@ -134,16 +126,19 @@ firetray.ChatStatusIcon = {
|
||||
if (n_channels != 4)
|
||||
log.error("wrong nb of channels for pixbuf");
|
||||
|
||||
return pixbuf; // TO BE UNREFED WITH to g_object_unref() !!
|
||||
},
|
||||
|
||||
crossFade: function(pixbuf) {
|
||||
// init transform
|
||||
let width = gdk.gdk_pixbuf_get_width(pixbuf);
|
||||
let height = gdk.gdk_pixbuf_get_height(pixbuf);
|
||||
log.warn("width="+width+", height="+height);
|
||||
let rowstride = gdk.gdk_pixbuf_get_rowstride(pixbuf);
|
||||
log.warn("rowstride="+rowstride);
|
||||
log.debug("width="+width+", height="+height);
|
||||
let n_channels = gdk.gdk_pixbuf_get_n_channels(pixbuf);
|
||||
let length = width*height*n_channels;
|
||||
let pixels = ctypes.cast(gdk.gdk_pixbuf_get_pixels(pixbuf),
|
||||
gobject.guchar.array(length).ptr);
|
||||
log.warn("pixels="+pixels);
|
||||
log.debug("pixels="+pixels);
|
||||
|
||||
// backup alpha for later fade-in
|
||||
let buffer = new ArrayBuffer(width*height);
|
||||
@ -152,28 +147,60 @@ firetray.ChatStatusIcon = {
|
||||
alpha_bak[(i-3)/n_channels] = pixels.contents[i];
|
||||
|
||||
const ALPHA_STEP = 5;
|
||||
let timers = [];
|
||||
|
||||
// fade out
|
||||
for (let a=255; a>0; a-=ALPHA_STEP) {
|
||||
for(let i=3; i<length; i+=n_channels)
|
||||
if (pixels.contents[i]-ALPHA_STEP>0)
|
||||
pixels.contents[i] -= ALPHA_STEP;
|
||||
gtk.gtk_status_icon_set_from_pixbuf(firetray.ChatStatusIcon.trayIcon, pixbuf);
|
||||
sleep(10);
|
||||
}
|
||||
|
||||
// fade in
|
||||
for (let a=255; a>0; a-=ALPHA_STEP) {
|
||||
function fadeIn(alpha) {
|
||||
for(let i=3; i<length; i+=n_channels)
|
||||
if (pixels.contents[i]+ALPHA_STEP<=alpha_bak[(i-3)/n_channels]) {
|
||||
pixels.contents[i] += ALPHA_STEP;
|
||||
}
|
||||
log.info("gtk_status_icon_set_from_pixbuf="+pixbuf);
|
||||
gtk.gtk_status_icon_set_from_pixbuf(firetray.ChatStatusIcon.trayIcon, pixbuf);
|
||||
sleep(10);
|
||||
|
||||
if (alpha < 255) {
|
||||
alpha += ALPHA_STEP;
|
||||
timers.push(firetray.Utils.timer(10, Ci.nsITimer.TYPE_ONE_SHOT,
|
||||
function(){fadeIn(alpha);}));
|
||||
|
||||
} else {
|
||||
if (firetray.ChatStatusIcon.events['stop-cross-fade']) {
|
||||
delete firetray.ChatStatusIcon.events['stop-cross-fade'];
|
||||
firetray.ChatStatusIcon.setIconImage(firetray.ChatStatusIcon.themedIconNameCurrent);
|
||||
return;
|
||||
|
||||
} else if (firetray.ChatStatusIcon.events['icon-changed']) {
|
||||
delete firetray.ChatStatusIcon.events['icon-changed'];
|
||||
firetray.ChatStatusIcon.crossFade(firetray.ChatStatusIcon.buildPixBuf());
|
||||
return;
|
||||
|
||||
} else {
|
||||
timers.push(firetray.Utils.timer(500, Ci.nsITimer.TYPE_ONE_SHOT,
|
||||
function(){fadeOut(255);}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gobject.g_object_unref(pixbuf);
|
||||
});
|
||||
function fadeOut(alpha) {
|
||||
for(let i=3; i<length; i+=n_channels)
|
||||
if (pixels.contents[i]-ALPHA_STEP>0)
|
||||
pixels.contents[i] -= ALPHA_STEP;
|
||||
log.info("gtk_status_icon_set_from_pixbuf="+pixbuf);
|
||||
gtk.gtk_status_icon_set_from_pixbuf(firetray.ChatStatusIcon.trayIcon, pixbuf);
|
||||
|
||||
if (alpha > 0) {
|
||||
alpha -= ALPHA_STEP;
|
||||
timers.push(firetray.Utils.timer(10, Ci.nsITimer.TYPE_ONE_SHOT,
|
||||
function(){fadeOut(alpha);}));
|
||||
|
||||
} else {
|
||||
fadeIn(0);
|
||||
}
|
||||
}
|
||||
|
||||
fadeOut(255);
|
||||
|
||||
gobject.g_object_unref(pixbuf); // FIXME: not sure if this shouldn't be done at 'stop-cross-fade'
|
||||
log.info("pixbuf unref'd");
|
||||
},
|
||||
|
||||
startIconBlinking: function() { // gtk_status_icon_set_blinking() deprecated
|
||||
@ -194,6 +221,10 @@ firetray.ChatStatusIcon = {
|
||||
this.on = false;
|
||||
},
|
||||
|
||||
stopCrossFade: function() {
|
||||
this.events['stop-cross-fade'] = true;
|
||||
},
|
||||
|
||||
setUrgency: function(xid, urgent) {
|
||||
gtk.gtk_window_set_urgency_hint(firetray.Handler.gtkWindows.get(xid), urgent);
|
||||
},
|
||||
|
@ -331,6 +331,7 @@ firetray.Handler.setIconText = function(text, color) { // FIXME: function too lo
|
||||
gdk.gdk_pixbuf_composite(bufAlpha,dest,0,0,w,h,0,0,1,1,gdk.GDK_INTERP_NEAREST,255);
|
||||
gobject.g_object_unref(bufAlpha);
|
||||
|
||||
log.info("gtk_status_icon_set_from_pixbuf="+dest);
|
||||
gtk.gtk_status_icon_set_from_pixbuf(firetray.StatusIcon.trayIcon, dest);
|
||||
} catch (x) {
|
||||
log.error(x);
|
||||
|
Loading…
Reference in New Issue
Block a user