504 lines
19 KiB
JavaScript
504 lines
19 KiB
JavaScript
/* -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* The tray icon for the main app. We need a hidden proxy window as (1) we want
|
|
a unique icon, (2) the icon sends notifications to a single window. */
|
|
|
|
var EXPORTED_SYMBOLS = [ "firetray" ];
|
|
|
|
const Cc = Components.classes;
|
|
const Ci = Components.interfaces;
|
|
const Cu = Components.utils;
|
|
|
|
Cu.import("resource://gre/modules/Services.jsm");
|
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
|
Cu.import("resource://gre/modules/ctypes.jsm");
|
|
Cu.import("resource://firetray/ctypes/ctypesMap.jsm");
|
|
Cu.import("resource://firetray/ctypes/winnt/win32.jsm");
|
|
Cu.import("resource://firetray/ctypes/winnt/gdi32.jsm");
|
|
Cu.import("resource://firetray/ctypes/winnt/kernel32.jsm");
|
|
Cu.import("resource://firetray/ctypes/winnt/shell32.jsm");
|
|
Cu.import("resource://firetray/ctypes/winnt/user32.jsm");
|
|
Cu.import("resource://firetray/winnt/FiretrayWin32.jsm");
|
|
Cu.import("resource://firetray/commons.js");
|
|
firetray.Handler.subscribeLibsForClosing([gdi32, kernel32, shell32, user32]);
|
|
|
|
let log = firetray.Logging.getLogger("firetray.StatusIcon");
|
|
|
|
if ("undefined" == typeof(firetray.Handler))
|
|
log.error("This module MUST be imported from/after FiretrayHandler !");
|
|
|
|
const ICON_CHROME_PATH = "chrome://firetray/skin/icons/winnt";
|
|
const ICON_CHROME_FILES = {
|
|
'blank-icon': { use:'tray', path:ICON_CHROME_PATH+"/blank-icon.bmp" },
|
|
'mail-unread': { use:'tray', path:ICON_CHROME_PATH+"/mail-unread.ico" },
|
|
'prefs': { use:'menu', path:ICON_CHROME_PATH+"/gtk-preferences.bmp" },
|
|
'quit': { use:'menu', path:ICON_CHROME_PATH+"/application-exit.bmp" },
|
|
'new-wnd': { use:'menu', path:ICON_CHROME_PATH+"/document-new.bmp" },
|
|
'new-msg': { use:'menu', path:ICON_CHROME_PATH+"/gtk-edit.bmp" },
|
|
'reset': { use:'menu', path:ICON_CHROME_PATH+"/gtk-apply.bmp" },
|
|
};
|
|
|
|
|
|
firetray.StatusIcon = {
|
|
initialized: false,
|
|
callbacks: {}, // pointers to JS functions. MUST LIVE DURING ALL THE EXECUTION
|
|
notifyIconData: null,
|
|
hwndProxy: null,
|
|
WNDCLASS_NAME: "FireTrayHiddenWindowClass",
|
|
WNDCLASS_ATOM: null,
|
|
icons: (function(){return new ctypesMap(win32.HICON);})(),
|
|
bitmaps: (function(){return new ctypesMap(win32.HBITMAP);})(),
|
|
IMG_TYPES: {
|
|
ico: { win_t: win32.HICON, load_const: user32.IMAGE_ICON, map: 'icons' },
|
|
bmp: { win_t: win32.HBITMAP, load_const: user32.IMAGE_BITMAP, map: 'bitmaps' }
|
|
},
|
|
PREF_TO_ICON_NAME: {
|
|
app_icon_custom: 'app-custom',
|
|
mail_icon_custom: 'mail-custom'
|
|
},
|
|
|
|
init: function() {
|
|
this.loadImages();
|
|
this.create();
|
|
firetray.Handler.setIconImageDefault();
|
|
|
|
Cu.import("resource://firetray/winnt/FiretrayPopupMenu.jsm");
|
|
if (!firetray.PopupMenu.init())
|
|
return false;
|
|
|
|
this.initialized = true;
|
|
return true;
|
|
},
|
|
|
|
shutdown: function() {
|
|
log.debug("Disabling StatusIcon");
|
|
firetray.PopupMenu.shutdown();
|
|
|
|
this.destroy();
|
|
this.destroyImages();
|
|
|
|
this.initialized = false;
|
|
return true;
|
|
},
|
|
|
|
loadThemedIcons: function() { },
|
|
|
|
loadImages: function() {
|
|
let topmost = firetray.Handler.getWindowInterface(
|
|
Services.wm.getMostRecentWindow(null), "nsIBaseWindow");
|
|
let hwnd = firetray.Win32.hexStrToHwnd(topmost.nativeHandle);
|
|
log.debug("topmost or hiddenWin hwnd="+hwnd);
|
|
this.icons.insert('app', this.getIconFromWindow(hwnd));
|
|
['app_icon_custom', 'mail_icon_custom'].forEach(function(elt) {
|
|
firetray.StatusIcon.loadImageCustom(elt);
|
|
});
|
|
|
|
/* we'll take the first icon in the .ico file. To get the icon count in the
|
|
file, pass ctypes.cast(ctypes.int(-1), win32.UINT); */
|
|
for (let imgName in ICON_CHROME_FILES) {
|
|
let path = firetray.Utils.chromeToPath(ICON_CHROME_FILES[imgName].path);
|
|
let img = this.loadImageFromFile(path);
|
|
if (img && ICON_CHROME_FILES[imgName].use == 'menu')
|
|
/* Ideally we should rebuild the menu each time it is shown as the menu
|
|
color may change. But, let's just consider it's not worth it for
|
|
now. */
|
|
img.himg = this.makeBitMapTransparent(img.himg);
|
|
if (img)
|
|
this[this.IMG_TYPES[img['type']]['map']].insert(imgName, img['himg']);
|
|
}
|
|
},
|
|
|
|
loadImageCustom: function(prefname) {
|
|
log.debug("loadImageCustom pref="+prefname);
|
|
let filename = firetray.Utils.prefService.getCharPref(prefname);
|
|
if (!filename) return;
|
|
let img = this.loadImageFromFile(filename);
|
|
if (!img) return;
|
|
|
|
log.debug("loadImageCustom img type="+img['type']+" himg="+img['himg']);
|
|
let hicon = img['himg'];
|
|
if (img['type'] === 'bmp')
|
|
hicon = this.HBITMAPToHICON(img['himg']);
|
|
let name = this.PREF_TO_ICON_NAME[prefname];
|
|
log.debug(" name="+name);
|
|
this.icons.insert(name, hicon);
|
|
},
|
|
|
|
loadImageFromFile: function(path) {
|
|
let imgType = path.substr(-3, 3).toLowerCase();
|
|
if (!(imgType in this.IMG_TYPES)) {
|
|
throw Error("Unrecognized type '"+imgType+"'");
|
|
}
|
|
let imgTypeRec = this.IMG_TYPES[imgType];
|
|
let himg = ctypes.cast(
|
|
user32.LoadImageW(null, path, imgTypeRec['load_const'], 0, 0,
|
|
user32.LR_LOADFROMFILE|user32.LR_SHARED),
|
|
imgTypeRec['win_t']);
|
|
if (himg.isNull()) {
|
|
log.error("Could not load '"+path+"'="+himg+" winLastError="+ctypes.winLastError);
|
|
return null;
|
|
}
|
|
return {type:imgType, himg:himg};
|
|
},
|
|
|
|
HBITMAPToHICON: function(hBitmap) {
|
|
log.debug("HBITMAPToHICON hBitmap="+hBitmap);
|
|
let hWnd = null; // firetray.StatusIcon.hwndProxy;
|
|
let hdc = user32.GetDC(hWnd);
|
|
let bitmap = new win32.BITMAP();
|
|
let err = gdi32.GetObjectW(hBitmap, win32.BITMAP.size, bitmap.address()); // get bitmap info
|
|
let hBitmapMask = gdi32.CreateCompatibleBitmap(hdc, bitmap.bmWidth, bitmap.bmHeight);
|
|
user32.ReleaseDC(hWnd, hdc);
|
|
|
|
let iconInfo = win32.ICONINFO();
|
|
iconInfo.fIcon = true;
|
|
iconInfo.xHotspot = 0;
|
|
iconInfo.yHotspot = 0;
|
|
iconInfo.hbmMask = hBitmapMask;
|
|
iconInfo.hbmColor = hBitmap;
|
|
|
|
let hIcon = user32.CreateIconIndirect(iconInfo.address());
|
|
log.debug(" CreateIconIndirect hIcon="+hIcon+" lastError="+ctypes.winLastError);
|
|
|
|
gdi32.DeleteObject(hBitmap);
|
|
gdi32.DeleteObject(hBitmapMask);
|
|
|
|
return hIcon;
|
|
},
|
|
|
|
// images loaded with LR_SHARED need't be destroyed
|
|
destroyImages: function() {
|
|
[this.icons, this.bitmaps].forEach(function(map, idx, ary) {
|
|
let keys = map.keys;
|
|
for (let i=0, len=keys.length; i<len; ++i) {
|
|
let imgName = keys[i];
|
|
map.remove(imgName);
|
|
}
|
|
});
|
|
log.debug("Icons destroyed");
|
|
},
|
|
|
|
create: function() {
|
|
let hwnd_hidden = this.createProxyWindow();
|
|
|
|
nid = new shell32.NOTIFYICONDATAW();
|
|
nid.cbSize = shell32.NOTIFYICONDATAW_SIZE();
|
|
log.debug("SIZE="+nid.cbSize);
|
|
nid.szTip = firetray.Handler.appName;
|
|
nid.hIcon = this.icons.get('app');
|
|
nid.hWnd = hwnd_hidden;
|
|
nid.uCallbackMessage = firetray.Win32.WM_TRAYMESSAGE;
|
|
nid.uFlags = shell32.NIF_ICON | shell32.NIF_MESSAGE | shell32.NIF_TIP;
|
|
nid.uVersion = shell32.NOTIFYICON_VERSION_4;
|
|
|
|
// Install the icon
|
|
rv = shell32.Shell_NotifyIconW(shell32.NIM_ADD, nid.address());
|
|
log.debug("Shell_NotifyIcon ADD="+rv+" winLastError="+ctypes.winLastError); // ERROR_INVALID_WINDOW_HANDLE(1400)
|
|
rv = shell32.Shell_NotifyIconW(shell32.NIM_SETVERSION, nid.address());
|
|
log.debug("Shell_NotifyIcon SETVERSION="+rv+" winLastError="+ctypes.winLastError);
|
|
|
|
this.notifyIconData = nid;
|
|
this.hwndProxy = hwnd_hidden;
|
|
},
|
|
|
|
createProxyWindow: function() {
|
|
this.registerWindowClass();
|
|
|
|
let hwnd_hidden = user32.CreateWindowExW(
|
|
0, win32.LPCTSTR(this.WNDCLASS_ATOM), // lpClassName can also be _T(WNDCLASS_NAME)
|
|
"Firetray Message Window", 0,
|
|
user32.CW_USEDEFAULT, user32.CW_USEDEFAULT, user32.CW_USEDEFAULT, user32.CW_USEDEFAULT,
|
|
null, null, firetray.Win32.hInstance, null);
|
|
log.debug("CreateWindow="+!hwnd_hidden.isNull()+" winLastError="+ctypes.winLastError);
|
|
|
|
this.callbacks.proxyWndProc = user32.WNDPROC(firetray.StatusIcon.proxyWndProc);
|
|
let procPrev = user32.SetWindowLongW(hwnd_hidden, user32.GWLP_WNDPROC,
|
|
ctypes.cast(this.callbacks.proxyWndProc, win32.LONG_PTR));
|
|
log.debug("procPrev="+procPrev+" winLastError="+ctypes.winLastError);
|
|
|
|
firetray.Win32.acceptAllMessages(hwnd_hidden);
|
|
|
|
return hwnd_hidden;
|
|
},
|
|
|
|
registerWindowClass: function() {
|
|
let wndClass = new user32.WNDCLASSEXW();
|
|
wndClass.cbSize = user32.WNDCLASSEXW.size;
|
|
wndClass.lpfnWndProc = ctypes.cast(user32.DefWindowProcW, user32.WNDPROC);
|
|
wndClass.hInstance = firetray.Win32.hInstance;
|
|
wndClass.lpszClassName = win32._T(this.WNDCLASS_NAME);
|
|
this.WNDCLASS_ATOM = user32.RegisterClassExW(wndClass.address());
|
|
log.debug("WNDCLASS_ATOM="+this.WNDCLASS_ATOM);
|
|
},
|
|
|
|
proxyWndProc: function(hWnd, uMsg, wParam, lParam) {
|
|
// log.debug("ProxyWindowProc CALLED: hWnd="+hWnd+", uMsg="+uMsg+", wParam="+wParam+", lParam="+lParam);
|
|
|
|
// FIXME: WM_TASKBARCREATED is needed in case of explorer crash
|
|
// http://twigstechtips.blogspot.fr/2011/02/c-detect-when-windows-explorer-has.html
|
|
if (uMsg === firetray.Win32.WM_TASKBARCREATED) {
|
|
log.info("____________TASKBARCREATED");
|
|
|
|
} else if (uMsg === firetray.Win32.WM_TRAYMESSAGE) {
|
|
|
|
switch (win32.LOWORD(lParam)) {
|
|
case win32.WM_LBUTTONUP:
|
|
log.debug("WM_LBUTTONUP");
|
|
firetray.Handler.showHideAllWindows();
|
|
break;
|
|
case win32.WM_RBUTTONUP:
|
|
log.debug("WM_RBUTTONUP");
|
|
case win32.WM_CONTEXTMENU:
|
|
log.debug("WM_CONTEXTMENU");
|
|
/* Can't determine tray icon position precisely: the mouse cursor can
|
|
move between WM_RBUTTONDOWN and WM_RBUTTONUP, or the icon can have
|
|
been moved inside the notification area... so we opt for the easy
|
|
solution. */
|
|
let pos = user32.GetMessagePos();
|
|
let xPos = win32.GET_X_LPARAM(pos), yPos = win32.GET_Y_LPARAM(pos);
|
|
log.debug(" x="+xPos+" y="+yPos);
|
|
user32.SetForegroundWindow(hWnd);
|
|
user32.TrackPopupMenu(firetray.PopupMenu.menu, user32.TPM_RIGHTALIGN|user32.TPM_BOTTOMALIGN, xPos, yPos, 0, hWnd, null);
|
|
break;
|
|
default:
|
|
}
|
|
|
|
} else {
|
|
switch (uMsg) {
|
|
case win32.WM_SYSCOMMAND:
|
|
log.debug("WM_SYSCOMMAND wParam="+wParam+", lParam="+lParam);
|
|
break;
|
|
case win32.WM_COMMAND:
|
|
log.debug("WM_COMMAND wParam="+wParam+", lParam="+lParam);
|
|
firetray.PopupMenu.processMenuItem(wParam);
|
|
break;
|
|
case win32.WM_MENUCOMMAND:
|
|
log.debug("WM_MENUCOMMAND wParam="+wParam+", lParam="+lParam);
|
|
break;
|
|
case win32.WM_MENUCHAR:
|
|
log.debug("WM_MENUCHAR wParam="+wParam+", lParam="+lParam);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return user32.DefWindowProcW(hWnd, uMsg, wParam, lParam);
|
|
},
|
|
|
|
getIconFromWindow: function(hwnd) {
|
|
let rv = user32.SendMessageW(hwnd, user32.WM_GETICON, user32.ICON_SMALL, 0);
|
|
log.debug("SendMessageW winLastError="+ctypes.winLastError);
|
|
// result is a ctypes.Int64. So we need to create a CData from it before
|
|
// casting it to a HICON.
|
|
let icon = ctypes.cast(win32.LRESULT(rv), win32.HICON);
|
|
if (icon.isNull()) { // from the window class
|
|
rv = user32.GetClassLong(hwnd, user32.GCLP_HICONSM);
|
|
icon = ctypes.cast(win32.ULONG_PTR(rv), win32.HICON);
|
|
log.debug("GetClassLong winLastError="+ctypes.winLastError);
|
|
}
|
|
if (icon.isNull()) { // from the first resource -> ERROR_RESOURCE_TYPE_NOT_FOUND(1813)
|
|
icon = user32.LoadIconW(firetray.Win32.hInstance, win32.MAKEINTRESOURCE(0));
|
|
log.debug("LoadIconW module winLastError="+ctypes.winLastError);
|
|
}
|
|
if (icon.isNull()) { // OS default icon
|
|
icon = user32.LoadIconW(null, win32.MAKEINTRESOURCE(user32.IDI_APPLICATION));
|
|
log.debug("LoadIconW default winLastError="+ctypes.winLastError);
|
|
}
|
|
log.debug("=== icon="+icon);
|
|
return icon;
|
|
},
|
|
|
|
destroyProxyWindow: function() {
|
|
let rv = user32.DestroyWindow(this.hwndProxy);
|
|
|
|
rv = this.unregisterWindowClass();
|
|
log.debug("Hidden window removed");
|
|
},
|
|
|
|
unregisterWindowClass: function() {
|
|
return user32.UnregisterClassW(win32.LPCTSTR(this.WNDCLASS_ATOM), firetray.Win32.hInstance);
|
|
},
|
|
|
|
destroy: function() {
|
|
let rv = shell32.Shell_NotifyIconW(shell32.NIM_DELETE, this.notifyIconData.address());
|
|
log.debug("Shell_NotifyIcon DELETE="+rv+" winLastError="+ctypes.winLastError);
|
|
this.destroyProxyWindow();
|
|
},
|
|
|
|
setIcon: function(iconinfo) {
|
|
let nid = firetray.StatusIcon.notifyIconData;
|
|
if (iconinfo.hicon)
|
|
nid.hIcon = iconinfo.hicon;
|
|
if (iconinfo.tip)
|
|
nid.szTip = iconinfo.tip;
|
|
rv = shell32.Shell_NotifyIconW(shell32.NIM_MODIFY, nid.address());
|
|
log.debug("Shell_NotifyIcon MODIFY="+rv+" winLastError="+ctypes.winLastError);
|
|
},
|
|
|
|
// rgb colors encoded in *bbggrr*
|
|
cssColorToCOLORREF: function(csscolor) {
|
|
let rgb = csscolor.substr(1);
|
|
let rr = rgb.substr(0, 2);
|
|
let gg = rgb.substr(2, 2);
|
|
let bb = rgb.substr(4, 2);
|
|
return parseInt("0x"+bb+gg+rr);
|
|
},
|
|
|
|
// http://stackoverflow.com/questions/457050/how-to-display-text-in-system-tray-icon-with-win32-api
|
|
createTextIcon: function(hWnd, text, color) {
|
|
log.debug("createTextIcon hWnd="+hWnd+" text="+text+" color="+color);
|
|
|
|
let blank = this.bitmaps.get('blank-icon');
|
|
let bitmap = new win32.BITMAP();
|
|
let err = gdi32.GetObjectW(blank, win32.BITMAP.size, bitmap.address()); // get bitmap info
|
|
let width = bitmap.bmWidth, height = bitmap.bmHeight;
|
|
|
|
let hdc = user32.GetDC(hWnd); // get device context (DC) for hWnd
|
|
let hdcMem = gdi32.CreateCompatibleDC(hdc); // creates a memory device context (DC) compatible with hdc (need a bitmap)
|
|
let hBitmap = user32.CopyImage(blank, user32.IMAGE_BITMAP, width, height, 0);
|
|
let hBitmapMask = gdi32.CreateCompatibleBitmap(hdc, width, height);
|
|
user32.ReleaseDC(hWnd, hdc);
|
|
|
|
let hBitmapOrig = gdi32.SelectObject(hdcMem, hBitmap);
|
|
|
|
function getFont(fnHeight) {
|
|
return gdi32.CreateFontW(
|
|
fnHeight, 0, 0, 0, gdi32.FW_SEMIBOLD, 0, 0, 0,
|
|
gdi32.ANSI_CHARSET, gdi32.OUT_OUTLINE_PRECIS, 0, gdi32.ANTIALIASED_QUALITY,
|
|
gdi32.FIXED_PITCH|gdi32.FF_SWISS, "Arial"
|
|
);
|
|
}
|
|
|
|
let fnHeight = firetray.js.floatToInt(height);
|
|
log.debug(" fnHeight initial="+fnHeight);
|
|
let hFont = getFont(fnHeight);
|
|
gdi32.SelectObject(hdcMem, hFont); // replace font in bitmap by hFont
|
|
{ let bufLen = 32, faceName = ctypes.jschar.array()(bufLen); gdi32.GetTextFaceW(hdcMem, bufLen, faceName); log.debug(" font="+faceName); }
|
|
|
|
let size = new gdi32.SIZE();
|
|
gdi32.GetTextExtentPoint32W(hdcMem, text, text.length, size.address()); // more reliable than DrawText(DT_CALCRECT)
|
|
while (size.cx > width - 6 || size.cy > height - 4) {
|
|
fnHeight -= 1;
|
|
hFont = getFont(fnHeight);
|
|
gdi32.SelectObject(hdcMem, hFont);
|
|
gdi32.GetTextExtentPoint32W(hdcMem, text, text.length, size.address());
|
|
log.debug(" fnHeight="+fnHeight+" width="+size.cx);
|
|
}
|
|
|
|
gdi32.SetTextColor(hdcMem, win32.COLORREF(this.cssColorToCOLORREF(color)));
|
|
gdi32.SetBkMode(hdcMem, gdi32.TRANSPARENT); // VERY IMPORTANT
|
|
gdi32.SetTextAlign(hdcMem, gdi32.TA_TOP|gdi32.TA_CENTER);
|
|
log.debug(" ___ALIGN=(winLastError="+ctypes.winLastError+") "+gdi32.GetTextAlign(hdcMem));
|
|
|
|
let nXStart = firetray.js.floatToInt((width - size.cx)/2),
|
|
nYStart = firetray.js.floatToInt((height - size.cy)/2);
|
|
gdi32.TextOutW(hdcMem, width/2, nYStart+2, text, text.length); // ref point for alignment
|
|
|
|
gdi32.SelectObject(hdcMem, hBitmapOrig);
|
|
|
|
let iconInfo = win32.ICONINFO();
|
|
iconInfo.fIcon = true;
|
|
iconInfo.xHotspot = 0;
|
|
iconInfo.yHotspot = 0;
|
|
iconInfo.hbmMask = hBitmapMask;
|
|
iconInfo.hbmColor = hBitmap;
|
|
|
|
let hIcon = user32.CreateIconIndirect(iconInfo.address());
|
|
log.debug(" CreateIconIndirect hIcon="+hIcon+" lastError="+ctypes.winLastError);
|
|
|
|
gdi32.DeleteObject(gdi32.SelectObject(hdcMem, hFont));
|
|
gdi32.DeleteDC(hdcMem);
|
|
// gdi32.DeleteDC(hdc); // already ReleaseDC's
|
|
gdi32.DeleteObject(hBitmap);
|
|
gdi32.DeleteObject(hBitmapMask);
|
|
|
|
return hIcon; // to be destroyed (DestroyIcon)
|
|
},
|
|
|
|
getIconSafe: function(name) {
|
|
let hicon = null;
|
|
try {
|
|
hicon = firetray.StatusIcon.icons.get(name);
|
|
} catch(error) {
|
|
log.error("icon '"+name+"' not defined.");
|
|
}
|
|
return hicon;
|
|
},
|
|
|
|
// http://www.dreamincode.net/forums/topic/281612-how-to-make-bitmaps-on-menus-transparent-in-c-win32/
|
|
makeBitMapTransparent: function(hbmSrc) {
|
|
log.debug("hbmSrc="+hbmSrc);
|
|
let hdcSrc = gdi32.CreateCompatibleDC(null);
|
|
let hdcDst = gdi32.CreateCompatibleDC(null);
|
|
if (!hdcSrc || !hdcSrc) return null;
|
|
|
|
let bm = new win32.BITMAP();
|
|
let err = gdi32.GetObjectW(hbmSrc, win32.BITMAP.size, bm.address());
|
|
let hbmOld = ctypes.cast(gdi32.SelectObject(hdcSrc, hbmSrc), win32.HBITMAP);
|
|
let width = bm.bmWidth, height = bm.bmHeight;
|
|
let hbmNew = gdi32.CreateBitmap(width, height, bm.bmPlanes, bm.bmBitsPixel, null);
|
|
gdi32.SelectObject(hdcDst, hbmNew);
|
|
|
|
gdi32.BitBlt(hdcDst,0,0,width, height,hdcSrc,0,0,gdi32.SRCCOPY);
|
|
|
|
let clrTP = gdi32.GetPixel(hdcDst, 0, 0); // color of first pixel
|
|
let clrBK = user32.GetSysColor(user32.COLOR_MENU); // current background color
|
|
|
|
for (let nRow=0, len=height; nRow<len; ++nRow)
|
|
for (let nCol=0, len=width; nCol<len; ++nCol)
|
|
if (firetray.js.strEquals(gdi32.GetPixel(hdcDst, nCol, nRow), clrTP))
|
|
gdi32.SetPixel(hdcDst, nCol, nRow, clrBK);
|
|
|
|
gdi32.DeleteDC(hdcDst);
|
|
gdi32.DeleteDC(hdcSrc);
|
|
|
|
return hbmNew;
|
|
}
|
|
|
|
}; // firetray.StatusIcon
|
|
|
|
|
|
firetray.Handler.setIconImageDefault = function() {
|
|
log.debug("setIconImageDefault");
|
|
let appIconType = firetray.Utils.prefService.getIntPref("app_icon_type");
|
|
if (appIconType === FIRETRAY_APPLICATION_ICON_TYPE_THEMED)
|
|
firetray.StatusIcon.setIcon({hicon:firetray.StatusIcon.icons.get('app')});
|
|
else if (appIconType === FIRETRAY_APPLICATION_ICON_TYPE_CUSTOM) {
|
|
firetray.StatusIcon.setIcon({hicon:firetray.StatusIcon.getIconSafe('app-custom')});
|
|
}
|
|
};
|
|
|
|
firetray.Handler.setIconImageNewMail = function() {
|
|
log.debug("setIconImageDefault");
|
|
firetray.StatusIcon.setIcon({hicon:firetray.StatusIcon.icons.get('mail-unread')});
|
|
};
|
|
|
|
firetray.Handler.setIconImageCustom = function(prefname) {
|
|
log.debug("setIconImageCustom pref="+prefname);
|
|
let name = firetray.StatusIcon.PREF_TO_ICON_NAME[prefname];
|
|
firetray.StatusIcon.setIcon({hicon:firetray.StatusIcon.getIconSafe(name)});
|
|
};
|
|
|
|
// firetray.Handler.setIconImageFromFile = firetray.StatusIcon.setIconImageFromFile;
|
|
|
|
firetray.Handler.setIconTooltip = function(toolTipStr) {
|
|
log.debug("setIconTooltip");
|
|
firetray.StatusIcon.setIcon({tip:toolTipStr});
|
|
};
|
|
|
|
firetray.Handler.setIconTooltipDefault = function() {
|
|
log.debug("setIconTooltipDefault");
|
|
firetray.StatusIcon.setIcon({tip:this.appName});
|
|
};
|
|
|
|
firetray.Handler.setIconText = function(text, color) {
|
|
let hicon = firetray.StatusIcon.createTextIcon(
|
|
firetray.StatusIcon.hwndProxy, text, color);
|
|
log.debug("setIconText icon="+hicon);
|
|
if (hicon.isNull())
|
|
log.error("Could not create hicon");
|
|
firetray.StatusIcon.setIcon({hicon:hicon});
|
|
};
|
|
|
|
firetray.Handler.setIconVisibility = function(visible) {
|
|
};
|