[Pkg-mozext-commits] [firetray] 26/84: * creation of basic icon with text * load .bmp in addition to .ico (and load them LR_SHARED) * use ctypes pointer.isNull()
David Prévot
taffit at moszumanska.debian.org
Sun Jul 20 01:42:43 UTC 2014
This is an automated email from the git hooks/post-receive script.
taffit pushed a commit to branch master
in repository firetray.
commit 70f0c0a8e06c04c322a0b44db30504baffa3e8a2
Author: foudfou <foudil.newbie+git at gmail.com>
Date: Fri Feb 14 00:22:46 2014 +0100
* creation of basic icon with text
* load .bmp in addition to .ico (and load them LR_SHARED)
* use ctypes pointer.isNull()
---
src/chrome/skin/winnt/blank-icon.bmp | Bin 0 -> 3126 bytes
src/modules/FiretrayMessaging.jsm | 2 +
src/modules/ctypes/winnt/gdi32.jsm | 93 ++++++++++++++++++++
src/modules/ctypes/winnt/user32.jsm | 7 ++
src/modules/ctypes/winnt/win32.jsm | 17 +++-
src/modules/winnt/FiretrayStatusIcon.jsm | 142 ++++++++++++++++++++++---------
6 files changed, 217 insertions(+), 44 deletions(-)
diff --git a/src/chrome/skin/winnt/blank-icon.bmp b/src/chrome/skin/winnt/blank-icon.bmp
new file mode 100644
index 0000000..ce34799
Binary files /dev/null and b/src/chrome/skin/winnt/blank-icon.bmp differ
diff --git a/src/modules/FiretrayMessaging.jsm b/src/modules/FiretrayMessaging.jsm
index a8adfaf..6b06e89 100644
--- a/src/modules/FiretrayMessaging.jsm
+++ b/src/modules/FiretrayMessaging.jsm
@@ -206,6 +206,7 @@ firetray.Messaging = {
},
updateIcon: function(msgCount) {
+ log.debug("updateIcon");
if ("undefined" === typeof(msgCount)) msgCount = this.currentMsgCount;
let localizedTooltip;
@@ -227,6 +228,7 @@ firetray.Messaging = {
} else if (msgCount > 0) {
let prefMailNotification = firetray.Utils.prefService.getIntPref('mail_notification_type');
+ log.debug("msgCount prefMailNotification="+prefMailNotification);
switch (prefMailNotification) {
case FIRETRAY_NOTIFICATION_MESSAGE_COUNT:
let prefIconTextColor = firetray.Utils.prefService.getCharPref("icon_text_color");
diff --git a/src/modules/ctypes/winnt/gdi32.jsm b/src/modules/ctypes/winnt/gdi32.jsm
new file mode 100644
index 0000000..82b8fd0
--- /dev/null
+++ b/src/modules/ctypes/winnt/gdi32.jsm
@@ -0,0 +1,93 @@
+var EXPORTED_SYMBOLS = [ "gdi32" ];
+
+const GDI32_LIBNAME = "gdi32";
+const GDI32_ABIS = [ "dll" ];
+
+const Cu = Components.utils;
+
+Cu.import("resource://gre/modules/ctypes.jsm");
+Cu.import("resource://firetray/ctypes/ctypes-utils.jsm");
+Cu.import("resource://firetray/ctypes/winnt/win32.jsm");
+
+function gdi32_defines(lib) {
+
+ this.BITMAP = ctypes.StructType("BITMAP", [
+ { "bmType": win32.LONG },
+ { "bmWidth": win32.LONG },
+ { "bmHeight": win32.LONG },
+ { "bmWidthBytes": win32.LONG },
+ { "bmPlanes": win32.WORD },
+ { "bmBitsPixel": win32.WORD },
+ { "bmBits": win32.LPVOID }
+ ]);
+ this.PBITMAP = this.BITMAP.ptr;
+
+ lib.lazy_bind("CreateCompatibleDC", win32.HDC, win32.HDC);
+ lib.lazy_bind("DeleteDC", win32.BOOL, win32.HDC);
+ lib.lazy_bind("CreateCompatibleBitmap", win32.HBITMAP, win32.HDC, ctypes.int, ctypes.int);
+ lib.lazy_bind("SelectObject", win32.HGDIOBJ, win32.HDC, win32.HGDIOBJ);
+ lib.lazy_bind("DeleteObject", win32.BOOL, win32.HGDIOBJ);
+ lib.lazy_bind("PatBlt", win32.BOOL, win32.HDC, ctypes.int, ctypes.int, ctypes.int, ctypes.int, win32.DWORD);
+ this.BLACKNESS = win32.DWORD(0x00000042); /* dest = BLACK */
+ this.WHITENESS = win32.DWORD(0x00FF0062); /* dest = WHITE */
+ lib.lazy_bind("CreateFontW", win32.HFONT, ctypes.int, ctypes.int, ctypes.int, ctypes.int, ctypes.int, win32.DWORD, win32.DWORD, win32.DWORD, win32.DWORD, win32.DWORD, win32.DWORD, win32.DWORD, win32.DWORD, win32.LPCWSTR);
+ this.FW_DONTCARE = 0;
+ this.FW_THIN = 100;
+ this.FW_EXTRALIGHT = 200;
+ this.FW_LIGHT = 300;
+ this.FW_NORMAL = 400;
+ this.FW_MEDIUM = 500;
+ this.FW_SEMIBOLD = 600;
+ this.FW_BOLD = 700;
+ this.FW_EXTRABOLD = 800;
+ this.FW_HEAVY = 900;
+ this.FF_DONTCARE = (0<<4); /* Don't care or don't know. */
+ this.FF_ROMAN = (1<<4); /* Variable stroke width, serifed. Times Roman, Century Schoolbook, etc. */
+ this.FF_SWISS = (2<<4); /* Variable stroke width, sans-serifed. Helvetica, Swiss, etc. */
+ this.FF_MODERN = (3<<4); /* Constant stroke width, serifed or sans-serifed. Pica, Elite, Courier, etc. */
+ this.FF_SCRIPT = (4<<4); /* Cursive, etc. */
+ this.FF_DECORATIVE = (5<<4); /* Old English, etc. */
+ this.DEFAULT_PITCH = 0;
+ this.FIXED_PITCH = 1;
+ this.VARIABLE_PITCH = 2;
+ this.MONO_FONT = 8;
+ this.ANSI_CHARSET = 0;
+ this.DEFAULT_CHARSET = 1;
+ this.SYMBOL_CHARSET = 2;
+ this.SHIFTJIS_CHARSET = 128;
+ this.HANGEUL_CHARSET = 129;
+ this.HANGUL_CHARSET = 129;
+ this.GB2312_CHARSET = 134;
+ this.CHINESEBIG5_CHARSET = 136;
+ this.OEM_CHARSET = 255;
+ this.JOHAB_CHARSET = 130;
+ this.HEBREW_CHARSET = 177;
+ this.ARABIC_CHARSET = 178;
+ this.GREEK_CHARSET = 161;
+ this.TURKISH_CHARSET = 162;
+ this.VIETNAMESE_CHARSET = 163;
+ this.THAI_CHARSET = 222;
+ this.EASTEUROPE_CHARSET = 238;
+ this.RUSSIAN_CHARSET = 204;
+ lib.lazy_bind("SetTextColor", win32.COLORREF, win32.HDC, win32.COLORREF);
+ lib.lazy_bind("SetBkMode", ctypes.int, win32.HDC, ctypes.int);
+ this.TRANSPARENT = 1;
+ this.OPAQUE = 2;
+ this.BKMODE_LAST = 2;
+
+ lib.lazy_bind("TextOutW", win32.BOOL, win32.HDC, ctypes.int, ctypes.int, win32.LPCTSTR, ctypes.int);
+
+ lib.lazy_bind("GetTextAlign", win32.UINT, win32.HDC);
+ lib.lazy_bind("SetTextAlign", win32.UINT, win32.HDC, win32.UINT);
+ this.TA_LEFT = 0;
+ this.TA_RIGHT = 2;
+ this.TA_CENTER = 6;
+ this.TA_TOP = 0;
+ this.TA_BOTTOM = 8;
+ this.TA_BASELINE = 24;
+ this.TA_RTLREADING = 256;
+ this.TA_MASK =(this.TA_BASELINE+this.TA_CENTER+this.TA_UPDATECP+this.TA_RTLREADING);
+
+}
+
+new ctypes_library(GDI32_LIBNAME, GDI32_ABIS, gdi32_defines, this);
diff --git a/src/modules/ctypes/winnt/user32.jsm b/src/modules/ctypes/winnt/user32.jsm
index 8b2abbf..6a0702e 100644
--- a/src/modules/ctypes/winnt/user32.jsm
+++ b/src/modules/ctypes/winnt/user32.jsm
@@ -51,6 +51,9 @@ function user32_defines(lib) {
this.IDI_EXCLAMATION = win32.MAKEINTRESOURCE(32515);
this.IDI_ASTERISK = win32.MAKEINTRESOURCE(32516);
lib.lazy_bind("LoadImageW", win32.HANDLE, win32.HINSTANCE, win32.LPCTSTR, win32.UINT, ctypes.int, ctypes.int, win32.UINT);
+ this.IMAGE_BITMAP = 0;
+ this.IMAGE_ICON = 1;
+ this.IMAGE_CURSOR = 2;
this.LR_CREATEDIBSECTION = 0x00002000;
this.LR_DEFAULTCOLOR = 0x00000000;
this.LR_DEFAULTSIZE = 0x00000040;
@@ -241,6 +244,10 @@ function user32_defines(lib) {
this.SPI_GETFOREGROUNDFLASHCOUNT = 0x2004;
lib.lazy_bind("GetForegroundWindow", win32.HWND);
+ lib.lazy_bind("GetDC", win32.HDC, win32.HWND);
+ lib.lazy_bind("ReleaseDC", ctypes.int, win32.HWND, win32.HDC);
+ lib.lazy_bind("CreateIconIndirect", win32.HICON, win32.PICONINFO);
+
}
new ctypes_library(USER32_LIBNAME, USER32_ABIS, user32_defines, this);
diff --git a/src/modules/ctypes/winnt/win32.jsm b/src/modules/ctypes/winnt/win32.jsm
index 05f6234..ecb7266 100644
--- a/src/modules/ctypes/winnt/win32.jsm
+++ b/src/modules/ctypes/winnt/win32.jsm
@@ -41,6 +41,10 @@ var win32 = new function() {
this.HBRUSH = this.HICON;
this.HCURSOR = this.HANDLE;
this.HHOOK = this.HANDLE;
+ this.HDC = this.HANDLE;
+ this.HGDIOBJ = this.HANDLE;
+ this.HBITMAP = this.HANDLE;
+ this.HFONT = this.HANDLE;
this.TCHAR = ctypes.jschar, // Mozilla compiled with UNICODE/_UNICODE macros and wchar_t = jschar
this.LPSTR = ctypes.char.ptr;
this.LPCSTR = ctypes.char.ptr;
@@ -52,6 +56,7 @@ var win32 = new function() {
this.WPARAM = this.UINT_PTR;
this.LPARAM = this.LONG_PTR;
this.FARPROC = ctypes.voidptr_t; // typedef INT_PTR (FAR WINAPI *FARPROC)();
+ this.COLORREF = this.DWORD; // 0x00bbggrr
this.GUID = ctypes.StructType("GUID", [
{ "Data1": ctypes.unsigned_long },
@@ -97,10 +102,18 @@ var win32 = new function() {
this.WM_MOUSELAST = 0x020D;
this.WM_MOUSELAST = 0x020A;
+ this.ICONINFO = ctypes.StructType("ICONINFO", [
+ { "fIcon": this.BOOL },
+ { "xHotspot": this.DWORD },
+ { "yHotspot": this.DWORD },
+ { "hbmMask": this.HBITMAP },
+ { "hbmColor": this.HBITMAP }
+ ]);
+ this.PICONINFO = this.ICONINFO.ptr;
};
// ShellAPI.h
let nin_select = win32.WM_USER + 0;
-win32.NIN_SELECT = nin_select;
-win32.NINF_KEY = 0x1;
+win32.NIN_SELECT = nin_select;
+win32.NINF_KEY = 0x1;
win32.NIN_KEYSELECT = (win32.NIN_SELECT | win32.NINF_KEY);
diff --git a/src/modules/winnt/FiretrayStatusIcon.jsm b/src/modules/winnt/FiretrayStatusIcon.jsm
index 1a8f5fa..8ae1d6a 100644
--- a/src/modules/winnt/FiretrayStatusIcon.jsm
+++ b/src/modules/winnt/FiretrayStatusIcon.jsm
@@ -14,6 +14,7 @@ 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");
@@ -27,6 +28,7 @@ if ("undefined" == typeof(firetray.Handler))
log.error("This module MUST be imported from/after FiretrayHandler !");
FIRETRAY_ICON_CHROME_PATHS = {
+ 'blank-icon': "chrome://firetray/skin/winnt/blank-icon.bmp",
'mail-unread': "chrome://firetray/skin/winnt/mail-unread.ico",
};
@@ -36,11 +38,12 @@ firetray.StatusIcon = {
notifyIconData: null,
hwndProxy: null,
icons: null,
+ bitmaps: null,
WNDCLASS_NAME: "FireTrayHiddenWindowClass",
WNDCLASS_ATOM: null,
init: function() {
- this.loadIcons();
+ this.loadImages();
// this.defineIconNames(); // FIXME: linux-only
this.create();
@@ -52,7 +55,7 @@ firetray.StatusIcon = {
log.debug("Disabling StatusIcon");
this.destroy();
- this.destroyIcons();
+ this.destroyImages();
this.initialized = false;
return true;
@@ -74,8 +77,9 @@ firetray.StatusIcon = {
this.defaultNewMailIconName = "mail-unread";
},
- loadIcons: function() {
+ loadImages: function() {
this.icons = new ctypesMap(win32.HICON);
+ this.bitmaps = new ctypesMap(win32.HBITMAP);
// the Mozilla hidden window has the default Mozilla icon
let hwnd_hidden_moz = user32.FindWindowW("MozillaHiddenWindowClass", null);
@@ -84,39 +88,39 @@ firetray.StatusIcon = {
/* 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 ico_name in FIRETRAY_ICON_CHROME_PATHS) {
- let path = firetray.Utils.chromeToPath(FIRETRAY_ICON_CHROME_PATHS[ico_name]);
- let hicon = shell32.ExtractIconW(null, path, 0);
- // ERROR_INVALID_HANDLE(6) ignored (_Reserved_ HINSTANCE hInst ?)
- this.icons.insert(ico_name, hicon);
- log.debug("icon '"+ico_name+"'="+this.icons.get(ico_name)+" winLastError="+ctypes.winLastError);
+ for (let imgName in FIRETRAY_ICON_CHROME_PATHS) {
+ let path = firetray.Utils.chromeToPath(FIRETRAY_ICON_CHROME_PATHS[imgName]);
+ let imgType = path.substr(-3, 3);
+ let imgTypeDict = {
+ ico: { win_t: win32.HICON, load_const: user32.IMAGE_ICON, map: this.icons },
+ bmp: { win_t: win32.HBITMAP, load_const: user32.IMAGE_BITMAP, map: this.bitmaps }
+ };
+ if (!(imgType in imgTypeDict)) {
+ throw Error("Unrecognized type '"+imgType+"'");
+ }
+ let imgTypeRec = imgTypeDict[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 '"+imgName+"'="+himg+" winLastError="+ctypes.winLastError);
+ continue;
+ }
+ imgTypeRec['map'].insert(imgName, himg);
}
},
- destroyIcons: function() {
- let success = true, errors = [];
- let keys = this.icons.keys;
-
- // 'app' must not get DestroyIcon'd
- var idx_app = keys.indexOf('app');
- if (idx_app > -1) keys.splice(idx_app, 1);
-
- for (let i=0, len=keys.length; i<len; ++i) {
- let ico_name = keys[i];
- let res = user32.DestroyIcon(this.icons.get(ico_name));
- if (res)
- this.icons.remove(ico_name);
- else
- errors.push(ctypes.winLastError);
- success = success && res;
- }
- this.icons.remove('app');
-
- if (!success) {
- log.error("Couldn't destroy all icons: "+errors);
- } else {
- log.debug("Icons destroyed");
- }
+ // 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() {
@@ -190,7 +194,9 @@ firetray.StatusIcon = {
break;
case win32.WM_RBUTTONUP:
log.debug("WM_RBUTTONUP");
- firetray.Handler.windowGetAttention(); // TESTING
+ let hicon = firetray.StatusIcon.createSmallIcon(hWnd, "100", "#990000");
+ log.debug("%%%%%%%%%% ICON="+hicon);
+ firetray.StatusIcon.setImageFromIcon(hicon);
break;
case win32.WM_CONTEXTMENU:
log.debug("WM_CONTEXTMENU");
@@ -212,17 +218,16 @@ firetray.StatusIcon = {
// 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);
- let NULL = win32.HICON(null); // for comparison only
- if (firetray.js.strEquals(icon, NULL)) { // from the window class
+ 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 (firetray.js.strEquals(icon, NULL)) { // from the first resource -> ERROR_RESOURCE_TYPE_NOT_FOUND(1813)
+ 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 (firetray.js.strEquals(icon, NULL)) { // OS default icon
+ if (icon.isNull()) { // OS default icon
icon = user32.LoadIconW(null, win32.MAKEINTRESOURCE(user32.IDI_APPLICATION));
log.debug("LoadIconW default winLastError="+ctypes.winLastError);
}
@@ -247,22 +252,75 @@ firetray.StatusIcon = {
this.destroyProxyWindow();
},
- setImageFromIcon: function(icoName) {
+ setImageFromIcon: function(hicon) {
let nid = firetray.StatusIcon.notifyIconData;
- nid.hIcon = firetray.StatusIcon.icons.get(icoName);
+ nid.hIcon = hicon;
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
+ createSmallIcon: function(hWnd, text, color) {
+ 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 = this.bitmaps.get('blank-icon');
+ let hBitmapMask = gdi32.CreateCompatibleBitmap(hdc, 32, 32);
+ user32.ReleaseDC(hWnd, hdc);
+
+ let hOldBitmap = ctypes.cast(gdi32.SelectObject(hdcMem, hBitmap), // replace bitmap in hdcMem by hBitmap
+ win32.HBITMAP);
+ // gdi32.PatBlt(hdcMem, 0, 0, 16, 16, gdi32.BLACKNESS); // paint black rectangle
+
+ let nHeight = 32, fnWeight = gdi32.FW_BOLD;
+ let hFont = gdi32.CreateFontW(nHeight, 0, 0, 0, fnWeight, 0, 0, 0,
+ gdi32.ANSI_CHARSET, 0, 0, 0, gdi32.FF_SWISS, "Sans"); // get font
+ hFont = ctypes.cast(gdi32.SelectObject(hdcMem, hFont), win32.HFONT); // replace font in bitmap by hFont
+ gdi32.SetTextColor(hdcMem, win32.COLORREF(this.cssColorToCOLORREF(color)));
+ // gdi32.SetBkMode(hdcMem, gdi32.TRANSPARENT); // VERY IMPORTANT
+ // gdi32.SetTextAlign(hdcMem, gdi32.GetTextAlign(hdcMem) & (~gdi32.TA_CENTER));
+ // gdi32.SetTextAlign(hdcMem, gdi32.TA_CENTER);
+ log.debug(" ___ALIGN=(winLastError="+ctypes.winLastError+") "+gdi32.GetTextAlign(hdcMem));
+ gdi32.TextOutW(hdcMem, 0, 0, text, text.length);
+
+ gdi32.SelectObject(hdcMem, hOldBitmap); // always replace new hBitmap with original one
+
+ 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());
+
+ 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)
}
}; // firetray.StatusIcon
firetray.Handler.setIconImageDefault = function() {
log.debug("setIconImageDefault");
- firetray.StatusIcon.setImageFromIcon('app');
+ firetray.StatusIcon.setImageFromIcon(firetray.StatusIcon.icons.get('app'));
};
firetray.Handler.setIconImageNewMail = function() {
- firetray.StatusIcon.setImageFromIcon('mail-unread');
+ log.debug("setIconImageDefault");
+ firetray.StatusIcon.setImageFromIcon(firetray.StatusIcon.icons.get('mail-unread'));
};
// firetray.Handler.setIconImageFromFile = firetray.StatusIcon.setIconImageFromFile;
--
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