[Pkg-mozext-commits] [firetray] 358/399: implement experimental cross-fading for blinking chat icon

David Prévot taffit at alioth.debian.org
Tue Oct 29 18:24:14 UTC 2013


This is an automated email from the git hooks/post-receive script.

taffit pushed a commit to branch dfsg-clean
in repository firetray.

commit 208db6f90625a7b5fe0277e30281fdb8e193db85
Author: foudfou <foudil.newbie+git at gmail.com>
Date:   Mon Apr 1 02:58:15 2013 +0200

    implement experimental cross-fading for blinking chat icon
---
 src/modules/FiretrayChat.jsm                 |   37 +++++------
 src/modules/ctypes/linux/gdk.jsm             |   16 ++++-
 src/modules/ctypes/linux/gio.jsm             |    2 +
 src/modules/ctypes/linux/gtk.jsm             |   23 ++++++-
 src/modules/linux/FiretrayChatStatusIcon.jsm |   90 ++++++++++++++++++++++++++
 src/modules/linux/FiretrayPopupMenu.jsm      |    1 -
 src/modules/linux/FiretrayStatusIcon.jsm     |    1 +
 7 files changed, 149 insertions(+), 21 deletions(-)

diff --git a/src/modules/FiretrayChat.jsm b/src/modules/FiretrayChat.jsm
index 2046905..631c4ac 100644
--- a/src/modules/FiretrayChat.jsm
+++ b/src/modules/FiretrayChat.jsm
@@ -84,27 +84,28 @@ firetray.Chat = {
     log.debug('startGetAttentionMaybe');
     let convIsCurrentlyShown = this.isConvCurrentlyShown(conv);
     log.debug("convIsCurrentlyShown="+convIsCurrentlyShown);
-    if (!convIsCurrentlyShown) { // don't blink when conv tab already on top
-      this.acknowledgeOnFocus.must = true;
-      this.acknowledgeOnFocus.conv = conv;
-
-      /* there can potentially be multiple windows, each with a Chat tab and
-       the same conv open... so we need to handle all windows */
-      for (let xid in firetray.Handler.windows) {
-        let win = firetray.Handler.windows[xid].chromeWin;
-        let contactlist = win.document.getElementById("contactlistbox");
-        for (let i=0; i<contactlist.itemCount; ++i) {
-          let item = contactlist.getItemAtIndex(i);
-          if (item.localName !== 'imconv')
-            continue;
-          if (item.hasOwnProperty('conv') && item.conv.target === conv) {
-            firetray.ChatStatusIcon.setUrgency(xid, true);
-          }
+    if (convIsCurrentlyShown)   // don't blink when conv tab already on top
+      return;
+
+    this.acknowledgeOnFocus.must = true;
+    this.acknowledgeOnFocus.conv = conv;
+
+    /* there can potentially be multiple windows, each with a Chat tab and
+     the same conv open... so we need to handle all windows */
+    for (let xid in firetray.Handler.windows) {
+      let win = firetray.Handler.windows[xid].chromeWin;
+      let contactlist = win.document.getElementById("contactlistbox");
+      for (let i=0; i<contactlist.itemCount; ++i) {
+        let item = contactlist.getItemAtIndex(i);
+        if (item.localName !== 'imconv')
+          continue;
+        if (item.hasOwnProperty('conv') && item.conv.target === conv) {
+          firetray.ChatStatusIcon.setUrgency(xid, true);
         }
       }
-
-      firetray.ChatStatusIcon.startIconBlinking();
     }
+
+    firetray.ChatStatusIcon.startIconBlinking();
   },
 
   /**
diff --git a/src/modules/ctypes/linux/gdk.jsm b/src/modules/ctypes/linux/gdk.jsm
index 16d71a0..b665499 100644
--- a/src/modules/ctypes/linux/gdk.jsm
+++ b/src/modules/ctypes/linux/gdk.jsm
@@ -140,6 +140,8 @@ function gdk_defines(lib) {
   this.GDK_SUBSTRUCTURE_MASK        = 1 << 20,
   this.GDK_SCROLL_MASK              = 1 << 21,
   this.GDK_ALL_EVENTS_MASK          = 0x3FFFFE
+  this.GdkColorspace = ctypes.int;     // enum
+  this.GDK_COLORSPACE_RGB = 0;
 
   this.GdkWindow = ctypes.StructType("GdkWindow");
   this.GdkByteOrder = ctypes.int; // enum
@@ -262,9 +264,21 @@ function gdk_defines(lib) {
   lib.lazy_bind("gdk_screen_get_toplevel_windows", gobject.GList.ptr, this.GdkScreen.ptr);
   lib.lazy_bind("gdk_pixbuf_new_from_file", this.GdkPixbuf.ptr, gobject.gchar.ptr, glib.GError.ptr.ptr);
   lib.lazy_bind("gdk_pixbuf_copy", this.GdkPixbuf.ptr, this.GdkPixbuf.ptr);
+  lib.lazy_bind("gdk_pixbuf_composite", ctypes.void_t, this.GdkPixbuf.ptr, this.GdkPixbuf.ptr, ctypes.int, ctypes.int, ctypes.int, ctypes.int, ctypes.double, ctypes.double, ctypes.double, ctypes.double, ctypes.int, ctypes.int);
+  lib.lazy_bind("gdk_pixbuf_get_has_alpha", gobject.gboolean, this.GdkPixbuf.ptr);
+  lib.lazy_bind("gdk_pixbuf_add_alpha", this.GdkPixbuf.ptr, this.GdkPixbuf.ptr, gobject.gboolean, gobject.guchar, gobject.guchar, gobject.guchar);
+
+  lib.lazy_bind("gdk_pixbuf_get_colorspace", this.GdkColorspace, this.GdkPixbuf.ptr);
+  lib.lazy_bind("gdk_pixbuf_get_n_channels", ctypes.int, this.GdkPixbuf.ptr);
+  lib.lazy_bind("gdk_pixbuf_get_has_alpha", gobject.gboolean, this.GdkPixbuf.ptr);
+  lib.lazy_bind("gdk_pixbuf_get_bits_per_sample", ctypes.int, this.GdkPixbuf.ptr);
+  lib.lazy_bind("gdk_pixbuf_get_pixels", gobject.guchar.ptr, this.GdkPixbuf.ptr);
   lib.lazy_bind("gdk_pixbuf_get_width", ctypes.int, this.GdkPixbuf.ptr);
   lib.lazy_bind("gdk_pixbuf_get_height", ctypes.int, this.GdkPixbuf.ptr);
-  lib.lazy_bind("gdk_pixbuf_composite", ctypes.void_t, this.GdkPixbuf.ptr, this.GdkPixbuf.ptr, ctypes.int, ctypes.int, ctypes.int, ctypes.int, ctypes.double, ctypes.double, ctypes.double, ctypes.double, ctypes.int, ctypes.int);
+  lib.lazy_bind("gdk_pixbuf_get_rowstride", ctypes.int, this.GdkPixbuf.ptr);
+  lib.lazy_bind("gdk_pixbuf_get_byte_length", gobject.gsize, this.GdkPixbuf.ptr);
+  lib.lazy_bind("gdk_pixbuf_copy", this.GdkPixbuf.ptr, this.GdkPixbuf.ptr);
+
   lib.lazy_bind("gdk_screen_get_system_colormap", this.GdkColormap.ptr, this.GdkScreen.ptr);
   lib.lazy_bind("gdk_colormap_get_visual", this.GdkVisual.ptr, this.GdkColormap.ptr);
   lib.lazy_bind("gdk_color_parse", gobject.gboolean, gobject.gchar.ptr, this.GdkColor.ptr);
diff --git a/src/modules/ctypes/linux/gio.jsm b/src/modules/ctypes/linux/gio.jsm
index c41aca7..b6547bd 100644
--- a/src/modules/ctypes/linux/gio.jsm
+++ b/src/modules/ctypes/linux/gio.jsm
@@ -11,6 +11,7 @@ const Ci = Components.interfaces;
 
 Cu.import("resource://gre/modules/ctypes.jsm");
 Cu.import("resource://firetray/ctypes/ctypes-utils.jsm");
+Cu.import("resource://firetray/ctypes/linux/gobject.jsm");
 
 function gio_defines(lib) {
   this.GIcon = ctypes.StructType("GIcon");
@@ -18,6 +19,7 @@ function gio_defines(lib) {
 
   lib.lazy_bind("g_themed_icon_new", this.GIcon.ptr, ctypes.char.ptr);
   lib.lazy_bind("g_themed_icon_new_from_names", this.GIcon.ptr, ctypes.char.ptr.ptr, ctypes.int);
+  lib.lazy_bind("g_themed_icon_get_names", gobject.gchar.ptr.ptr, this.GThemedIcon.ptr);
 
 }
 
diff --git a/src/modules/ctypes/linux/gtk.jsm b/src/modules/ctypes/linux/gtk.jsm
index 81769d3..6f7af28 100644
--- a/src/modules/ctypes/linux/gtk.jsm
+++ b/src/modules/ctypes/linux/gtk.jsm
@@ -21,7 +21,15 @@ function gtk_defines(lib) {
   this.FIRETRAY_REQUIRED_GTK_MINOR_VERSION = 20;
   this.FIRETRAY_REQUIRED_GTK_MICRO_VERSION = 0;
 
-  this.GTK_ICON_SIZE_MENU = 1; // enum GtkIconSize
+  this.GtkIconSize = ctypes.int; // enum
+  this.GTK_ICON_SIZE_INVALID = 0;
+  this.GTK_ICON_SIZE_MENU = 1;
+  this.GTK_ICON_SIZE_SMALL_TOOLBAR = 2;
+  this.GTK_ICON_SIZE_LARGE_TOOLBAR = 3;
+  this.GTK_ICON_SIZE_BUTTON = 4;
+  this.GTK_ICON_SIZE_DND = 5;
+  this.GTK_ICON_SIZE_DIALOG = 6;
+
   this.GTK_WINDOW_TOPLEVEL = 0; // enum GtkWindowType
 
   this.GtkStatusIcon = ctypes.StructType("GtkStatusIcon");
@@ -56,6 +64,13 @@ function gtk_defines(lib) {
   this.GtkWindow = ctypes.StructType("GtkWindow");
   this.GtkWindowType = ctypes.int; // enum
   this.GtkSeparatorMenuItem = ctypes.StructType("GtkSeparatorMenuItem");
+  this.GtkIconInfo = ctypes.StructType("GtkIconInfo");
+  this.GtkIconLookupFlags = ctypes.int; // enum
+  this.GTK_ICON_LOOKUP_NO_SVG           = 1 << 0;
+  this.GTK_ICON_LOOKUP_FORCE_SVG        = 1 << 1;
+  this.GTK_ICON_LOOKUP_USE_BUILTIN      = 1 << 2;
+  this.GTK_ICON_LOOKUP_GENERIC_FALLBACK = 1 << 3;
+  this.GTK_ICON_LOOKUP_FORCE_SIZE       = 1 << 4;
 
   this.GtkMenuPositionFunc_t = ctypes.FunctionType(
     ctypes.default_abi, ctypes.void_t,
@@ -88,6 +103,9 @@ function gtk_defines(lib) {
   lib.lazy_bind("gtk_icon_theme_get_for_screen", this.GtkIconTheme.ptr, gdk.GdkScreen.ptr);
   lib.lazy_bind("gtk_icon_theme_append_search_path", ctypes.void_t, this.GtkIconTheme.ptr, gobject.gchar.ptr);
   lib.lazy_bind("gtk_icon_theme_prepend_search_path", ctypes.void_t, this.GtkIconTheme.ptr, gobject.gchar.ptr);
+  lib.lazy_bind("gtk_icon_theme_choose_icon", this.GtkIconInfo.ptr, this.GtkIconTheme.ptr, gobject.gchar.ptr.array(), gobject.gint, this.GtkIconLookupFlags);
+  lib.lazy_bind("gtk_icon_info_load_icon", gdk.GdkPixbuf.ptr, this.GtkIconInfo.ptr, glib.GError.ptr.ptr);
+  lib.lazy_bind("gtk_icon_info_free", ctypes.void_t, this.GtkIconInfo.ptr);
 
   lib.lazy_bind("gtk_status_icon_new", this.GtkStatusIcon.ptr);
   lib.lazy_bind("gtk_status_icon_set_from_file", ctypes.void_t, this.GtkStatusIcon.ptr, ctypes.char.ptr);
@@ -112,6 +130,9 @@ function gtk_defines(lib) {
   lib.lazy_bind("gtk_widget_create_pango_layout", pango.PangoLayout.ptr, this.GtkWidget.ptr, gobject.gchar.ptr);
   lib.lazy_bind("gtk_widget_destroy", ctypes.void_t, this.GtkWidget.ptr);
   lib.lazy_bind("gtk_status_icon_set_from_pixbuf", ctypes.void_t, this.GtkStatusIcon.ptr, gdk.GdkPixbuf.ptr);
+  lib.lazy_bind("gtk_status_icon_get_pixbuf", gdk.GdkPixbuf.ptr, this.GtkStatusIcon.ptr);
+  lib.lazy_bind("gtk_status_icon_get_gicon", gio.GIcon.ptr, this.GtkStatusIcon.ptr);
+  lib.lazy_bind("gtk_status_icon_get_storage_type", ctypes.int, this.GtkStatusIcon.ptr); // TEST
   lib.lazy_bind("gtk_window_list_toplevels", gobject.GList.ptr);
   lib.lazy_bind("gtk_window_get_title", gobject.gchar.ptr, this.GtkWindow.ptr);
   lib.lazy_bind("gtk_window_is_active", gobject.gboolean, this.GtkWindow.ptr);
diff --git a/src/modules/linux/FiretrayChatStatusIcon.jsm b/src/modules/linux/FiretrayChatStatusIcon.jsm
index b5733fb..c67701b 100644
--- a/src/modules/linux/FiretrayChatStatusIcon.jsm
+++ b/src/modules/linux/FiretrayChatStatusIcon.jsm
@@ -16,6 +16,7 @@ Cu.import("resource://firetray/ctypes/linux/gdk.jsm");
 Cu.import("resource://firetray/ctypes/linux/gtk.jsm");
 Cu.import("resource://firetray/linux/FiretrayWindow.jsm");
 Cu.import("resource://firetray/commons.js");
+Cu.import("resource://firetray/promise.js");
 firetray.Handler.subscribeLibsForClosing([gobject, gio, gtk]);
 
 if ("undefined" == typeof(firetray.Handler))
@@ -88,6 +89,95 @@ firetray.ChatStatusIcon = {
     gtk.gtk_status_icon_set_from_pixbuf(this.trayIcon, null);
   },
 
+  /**
+   * 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);
+      }
+    }
+
+    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);
+        let icon_info = gtk.gtk_icon_theme_choose_icon(icon_theme, arry, 22, gtk.GTK_ICON_LOOKUP_FORCE_SIZE);
+
+        // create pixbuf
+        let pixbuf = gdk.gdk_pixbuf_copy(gtk.gtk_icon_info_load_icon(icon_info, null));
+        gtk.gtk_icon_info_free(icon_info);   // gobject.g_object_unref(icon_info) in 3.8
+
+        // checks
+        if (gdk.gdk_pixbuf_get_colorspace(pixbuf) != gdk.GDK_COLORSPACE_RGB)
+          log.error("wrong colorspace for pixbuf");
+        if (gdk.gdk_pixbuf_get_bits_per_sample(pixbuf) != 8)
+          log.error("wrong bits_per_sample for pixbuf");
+        if (!gdk.gdk_pixbuf_get_has_alpha(pixbuf))
+          log.error("pixbuf doesn't have alpha");
+        let n_channels = gdk.gdk_pixbuf_get_n_channels(pixbuf);
+        if (n_channels != 4)
+          log.error("wrong nb of channels for 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);
+        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);
+
+        // backup alpha for later fade-in
+        let buffer = new ArrayBuffer(width*height);
+        let alpha_bak = new Uint8Array(buffer);
+        for (let i=3; i<length; i+=n_channels)
+          alpha_bak[(i-3)/n_channels] = pixels.contents[i];
+
+        const ALPHA_STEP = 5;
+
+        // 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) {
+          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;
+            }
+          gtk.gtk_status_icon_set_from_pixbuf(firetray.ChatStatusIcon.trayIcon, pixbuf);
+          sleep(10);
+        }
+
+        gobject.g_object_unref(pixbuf);
+      });
+  },
+
   startIconBlinking: function() { // gtk_status_icon_set_blinking() deprecated
     this.on = true;
     firetray.ChatStatusIcon.timers['blink'] = firetray.Utils.timer(
diff --git a/src/modules/linux/FiretrayPopupMenu.jsm b/src/modules/linux/FiretrayPopupMenu.jsm
index aa9771e..6f601bc 100644
--- a/src/modules/linux/FiretrayPopupMenu.jsm
+++ b/src/modules/linux/FiretrayPopupMenu.jsm
@@ -26,7 +26,6 @@ firetray.PopupMenu = {
   menu: null,
   menuShell: null,
   menuSeparatorWindows: null,
-  MIN_FONT_SIZE: 4,
 
   init: function() {
     this.menu = gtk.gtk_menu_new();
diff --git a/src/modules/linux/FiretrayStatusIcon.jsm b/src/modules/linux/FiretrayStatusIcon.jsm
index 5378b5f..87d9ea9 100644
--- a/src/modules/linux/FiretrayStatusIcon.jsm
+++ b/src/modules/linux/FiretrayStatusIcon.jsm
@@ -26,6 +26,7 @@ if ("undefined" == typeof(firetray.Handler))
 
 
 firetray.StatusIcon = {
+  MIN_FONT_SIZE: 4,
   FILENAME_BLANK: null,
 
   initialized: false,

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-mozext/firetray.git



More information about the Pkg-mozext-commits mailing list