@@ -7,13 +7,18 @@ const Ci = Components.interfaces;
77const Cu = Components . utils ;
88
99Cu . import ( "resource://gre/modules/ctypes.jsm" ) ;
10+ Cu . import ( "resource://gre/modules/osfile.jsm" )
1011Cu . import ( "resource://firetray/commons.js" ) ; // first for Handler.app !
1112Cu . import ( "resource://firetray/ctypes/linux/gobject.jsm" ) ;
1213// FIXME: can't subscribeLibsForClosing([appind])
1314// https://bugs.launchpad.net/ubuntu/+source/firefox/+bug/1393256
1415Cu . import ( "resource://firetray/ctypes/linux/" + firetray . Handler . app . widgetTk + "/appindicator.jsm" ) ;
16+ Cu . import ( "resource://firetray/ctypes/linux/" + firetray . Handler . app . widgetTk + "/gdk.jsm" ) ;
1517Cu . import ( "resource://firetray/ctypes/linux/" + firetray . Handler . app . widgetTk + "/gtk.jsm" ) ;
16- firetray . Handler . subscribeLibsForClosing ( [ gobject , gtk ] ) ;
18+ Cu . import ( "resource://firetray/ctypes/linux/cairo.jsm" ) ;
19+ Cu . import ( "resource://firetray/ctypes/linux/pango.jsm" ) ;
20+ Cu . import ( "resource://firetray/ctypes/linux/pangocairo.jsm" ) ;
21+ firetray . Handler . subscribeLibsForClosing ( [ gobject , gdk , gtk , cairo , pango , pangocairo ] ) ;
1722
1823let log = firetray . Logging . getLogger ( "firetray.AppIndicator" ) ;
1924
@@ -25,22 +30,19 @@ firetray.AppIndicator = {
2530 initialized : false ,
2631 callbacks : { } ,
2732 indicator : null ,
28-
33+ tempfile : null ,
34+ MIN_FONT_SIZE : 4 ,
35+
2936 init : function ( ) {
3037 this . indicator = appind . app_indicator_new (
3138 FIRETRAY_APPINDICATOR_ID ,
3239 firetray . StatusIcon . defaultAppIconName ,
3340 appind . APP_INDICATOR_CATEGORY_COMMUNICATIONS
3441 ) ;
3542
36-
37- //appind.app_indicator_set_icon_theme_path(this.indicator, firetray.StatusIcon.THEME_ICON_PATH);
38- appind . app_indicator_set_icon_theme_path ( this . indicator ,
39- Components . classes [ "@mozilla.org/file/directory_service;1" ] . getService ( Components . interfaces . nsIProperties ) . get ( "ProfD" , Components . interfaces . nsIFile ) . path
40- + "/extensions/{9533f794-00b4-4354-aa15-c2bbda6989f8}/chrome/skin/icons/"
41- ) ;
42-
43-
43+ this . tempfile = Components . classes [ "@mozilla.org/file/directory_service;1" ] . getService ( Components . interfaces . nsIProperties ) . get ( "TmpD" , Components . interfaces . nsIFile ) . path
44+ + "/thunderbird.png" ;
45+
4446 appind . app_indicator_set_status ( this . indicator ,
4547 appind . APP_INDICATOR_STATUS_ACTIVE ) ;
4648 appind . app_indicator_set_menu ( this . indicator ,
@@ -64,6 +66,7 @@ firetray.AppIndicator = {
6466 log . debug ( "Disabling AppIndicator" ) ;
6567 gobject . g_object_unref ( this . indicator ) ;
6668 this . initialized = false ;
69+ OS . File . remove ( this . tempfile ) ;
6770 } ,
6871
6972 addCallbacks : function ( ) {
@@ -82,11 +85,13 @@ firetray.AppIndicator = {
8285 let pref = firetray . Utils . prefService . getIntPref ( "middle_click" ) ;
8386 let item ;
8487 if ( pref === FIRETRAY_MIDDLE_CLICK_ACTIVATE_LAST ) {
88+ log . debug ( "MiddleClick=Last" ) ;
8589 item = firetray . PopupMenu . menuItem . activateLast ;
86- firetray . PopupMenu . showItem ( firetray . PopupMenu . menuItem . activateLast ) ;
90+ // firetray.PopupMenu.showItem(firetray.PopupMenu.menuItem.activateLast);
8791 } else if ( pref === FIRETRAY_MIDDLE_CLICK_SHOW_HIDE ) {
92+ log . debug ( "MiddleClick=ShowHide" ) ;
8893 item = firetray . PopupMenu . menuItem . showHide ;
89- firetray . PopupMenu . hideItem ( firetray . PopupMenu . menuItem . activateLast ) ;
94+ // firetray.PopupMenu.hideItem(firetray.PopupMenu.menuItem.showHide );
9095 } else {
9196 log . error ( "Unknown pref value for 'middle_click': " + pref ) ;
9297 return false ;
@@ -156,16 +161,152 @@ firetray.Handler.setIconTooltip = function(toolTipStr) {
156161//
157162// sajan
158163firetray . Handler . setIconText = function ( text , color ) {
159- //log.error("NOT SUPPORTED: " + text);
160-
161- if ( text > 99 ) {
162- text = "max" ;
163- }
164-
165- appind . app_indicator_set_icon_full (
166- firetray . AppIndicator . indicator ,
167- "unread-" + text ,
168- firetray . Handler . app . name ) ;
164+ log . debug ( "setIconText: " + text ) ;
165+
166+ log . debug ( "setIconText, Name: " + firetray . StatusIcon . defaultNewMailIconName ) ;
167+
168+ log . debug ( "setIconText, Temp: " + firetray . AppIndicator . tempfile ) ;
169+
170+ let icon_theme = gtk . gtk_icon_theme_get_for_screen ( gdk . gdk_screen_get_default ( ) ) ;
171+ let arry = gobject . gchar . ptr . array ( ) ( 2 ) ;
172+ arry [ 0 ] = gobject . gchar . array ( ) ( firetray . StatusIcon . defaultNewMailIconName ) ;
173+ arry [ 1 ] = null ;
174+ let icon_info = gtk . gtk_icon_theme_choose_icon ( icon_theme , arry , 22 , gtk . GTK_ICON_LOOKUP_FORCE_SIZE ) ;
175+ let dest = gdk . gdk_pixbuf_copy ( gtk . gtk_icon_info_load_icon ( icon_info , null ) ) ;
176+
177+
178+
179+ let w = gdk . gdk_pixbuf_get_width ( dest ) ;
180+ let h = gdk . gdk_pixbuf_get_height ( dest ) ;
181+
182+ // prepare colors/alpha
183+ /* FIXME: draw everything with cairo when dropping gtk2 support. Use
184+ gdk_pixbuf_get_from_surface(). */
185+ if ( firetray . Handler . app . widgetTk == "gtk2" ) {
186+ var colorMap = gdk . gdk_screen_get_system_colormap ( gdk . gdk_screen_get_default ( ) ) ;
187+ var visual = gdk . gdk_colormap_get_visual ( colorMap ) ;
188+ var visualDepth = visual . contents . depth ;
189+ log . debug ( "colorMap=" + colorMap + " visual=" + visual + " visualDepth=" + visualDepth ) ;
190+ }
191+ let fore = new gdk . GdkColor ;
192+ fore . pixel = fore . red = fore . green = fore . blue = 0 ;
193+ let back = new gdk . GdkColor ;
194+ back . pixel = back . red = back . green = back . blue = 0xFEFE ;
195+ let alpha = new gdk . GdkColor ;
196+ alpha . pixel = alpha . red = alpha . green = alpha . blue = 0xFFFF ;
197+ if ( ! fore || ! alpha )
198+ log . warn ( "Undefined fore or alpha GdkColor" ) ;
199+ gdk . gdk_color_parse ( color , fore . address ( ) ) ;
200+ if ( fore . red == alpha . red && fore . green == alpha . green && fore . blue == alpha . blue ) {
201+ alpha . red = 0 ; // make sure alpha is different from fore
202+ }
203+ if ( firetray . Handler . app . widgetTk == "gtk2" ) {
204+ gdk . gdk_colormap_alloc_color ( colorMap , fore . address ( ) , true , true ) ;
205+ gdk . gdk_colormap_alloc_color ( colorMap , back . address ( ) , true , true ) ;
206+ gdk . gdk_colormap_alloc_color ( colorMap , alpha . address ( ) , true , true ) ;
207+ }
208+
209+ // build text rectangle
210+ let cr ;
211+ if ( firetray . Handler . app . widgetTk == "gtk2" ) {
212+ var pm = gdk . gdk_pixmap_new ( null , w , h , visualDepth ) ;
213+ var pmDrawable = ctypes . cast ( pm , gdk . GdkDrawable . ptr ) ;
214+ cr = gdk . gdk_cairo_create ( pmDrawable ) ;
215+ } else {
216+ // FIXME: gtk3 text position is incorrect.
217+ var surface = cairo . cairo_image_surface_create ( cairo . CAIRO_FORMAT_ARGB32 , w , h ) ;
218+ cr = cairo . cairo_create ( surface ) ;
219+ }
220+
221+ gdk . gdk_cairo_set_source_color ( cr , alpha . address ( ) ) ;
222+ cairo . cairo_rectangle ( cr , 0 , 0 , w , h ) ;
223+ cairo . cairo_set_source_rgb ( cr , 1 , 1 , 1 ) ;
224+ cairo . cairo_fill ( cr ) ;
225+
226+ // gdk.gdk_cairo_set_source_color(cr, back.address());
227+ // cairo.cairo_rectangle(cr, 0, 0, w/2, h/2);
228+ // cairo.cairo_fill(cr);
229+
230+ // build text
231+ let scratch = gtk . gtk_window_new ( gtk . GTK_WINDOW_TOPLEVEL ) ;
232+ let layout = gtk . gtk_widget_create_pango_layout ( scratch , null ) ;
233+ gtk . gtk_widget_destroy ( scratch ) ;
234+ let fnt = pango . pango_font_description_from_string ( "Sans 32" ) ;
235+ pango . pango_font_description_set_weight ( fnt , pango . PANGO_WEIGHT_SEMIBOLD ) ;
236+ pango . pango_layout_set_spacing ( layout , 0 ) ;
237+ pango . pango_layout_set_font_description ( layout , fnt ) ;
238+ log . debug ( "layout=" + layout ) ;
239+ log . debug ( "text=" + text ) ;
240+ pango . pango_layout_set_text ( layout , text , - 1 ) ;
241+ let tw = new ctypes . int ;
242+ let th = new ctypes . int ;
243+ let sz ;
244+ let border = 4 ;
245+ pango . pango_layout_get_pixel_size ( layout , tw . address ( ) , th . address ( ) ) ;
246+ log . debug ( "tw=" + tw . value + " th=" + th . value ) ;
247+ // fit text to the icon by decreasing font size
248+ while ( tw . value > ( w - border ) || th . value > ( h - border ) ) {
249+ sz = pango . pango_font_description_get_size ( fnt ) ;
250+ if ( sz < firetray . AppIndicator . MIN_FONT_SIZE ) {
251+ sz = firetray . AppIndicator . MIN_FONT_SIZE ;
252+ break ;
253+ }
254+ sz -= pango . PANGO_SCALE ;
255+ pango . pango_font_description_set_size ( fnt , sz ) ;
256+ pango . pango_layout_set_font_description ( layout , fnt ) ;
257+ pango . pango_layout_get_pixel_size ( layout , tw . address ( ) , th . address ( ) ) ;
258+ }
259+ log . debug ( "tw=" + tw . value + " th=" + th . value + " sz=" + sz ) ;
260+ pango . pango_font_description_free ( fnt ) ;
261+ // center text
262+ let px = ( w - tw . value ) / 2 ;
263+ let py = ( h - th . value ) / 2 ;
264+ log . debug ( "px=" + px + " py=" + py ) ;
265+
266+ // draw text on pixmap
267+ gdk . gdk_cairo_set_source_color ( cr , fore . address ( ) ) ;
268+ cairo . cairo_move_to ( cr , px , py ) ;
269+ pangocairo . pango_cairo_show_layout ( cr , layout ) ;
270+ cairo . cairo_destroy ( cr ) ;
271+ gobject . g_object_unref ( layout ) ;
272+
273+ let buf = null ;
274+ if ( firetray . Handler . app . widgetTk == "gtk2" ) {
275+ buf = gdk . gdk_pixbuf_get_from_drawable ( null , pmDrawable , null , 0 , 0 , 0 , 0 , w , h ) ;
276+ gobject . g_object_unref ( pm ) ;
277+ }
278+ else {
279+ buf = gdk . gdk_pixbuf_get_from_surface ( surface , 0 , 0 , w , h ) ;
280+ cairo . cairo_surface_destroy ( surface ) ;
281+ }
282+ log . debug ( "alpha=" + alpha ) ;
283+ let alphaRed = gobject . guint16 ( alpha . red ) ;
284+ let alphaRed_guchar = ctypes . cast ( alphaRed , gobject . guchar ) ;
285+ let alphaGreen = gobject . guint16 ( alpha . green ) ;
286+ let alphaGreen_guchar = ctypes . cast ( alphaGreen , gobject . guchar ) ;
287+ let alphaBlue = gobject . guint16 ( alpha . blue ) ;
288+ let alphaBlue_guchar = ctypes . cast ( alphaBlue , gobject . guchar ) ;
289+ let bufAlpha = gdk . gdk_pixbuf_add_alpha ( buf , true , alphaRed_guchar , alphaGreen_guchar , alphaBlue_guchar ) ;
290+ gobject . g_object_unref ( buf ) ;
291+
292+ // merge the rendered text on top
293+ gdk . gdk_pixbuf_composite ( bufAlpha , dest , 0 , 0 , w , h , 0 , 0 , 1 , 1 , gdk . GDK_INTERP_BILINEAR , 255 ) ;
294+ gobject . g_object_unref ( bufAlpha ) ;
295+
296+ // Workaround
297+ gdk . gdk_pixbuf_save ( dest , firetray . AppIndicator . tempfile , "png" , null , null ) ;
298+
299+ appind . app_indicator_set_icon_full (
300+ firetray . AppIndicator . indicator ,
301+ firetray . StatusIcon . defaultNewMailIconName ,
302+ firetray . Handler . app . name ) ;
303+
304+ appind . app_indicator_set_icon_full (
305+ firetray . AppIndicator . indicator ,
306+ firetray . AppIndicator . tempfile ,
307+ firetray . Handler . app . name ) ;
308+
309+ return true ;
169310} ;
170311
171312firetray . Handler . setIconVisibility = function ( visible ) {
0 commit comments