[Pkg-mozext-commits] [firetray] 43/84: Add basic popup menu on tray icon.
David Prévot
taffit at moszumanska.debian.org
Sun Jul 20 01:42:44 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 8a3de9e34318565dd167939d26bf5b147d53c648
Author: foudfou <foudil.newbie+git at gmail.com>
Date: Mon Mar 31 23:17:03 2014 +0200
Add basic popup menu on tray icon.
---
src/chrome/skin/winnt/application-exit.bmp | Bin 0 -> 2358 bytes
src/chrome/skin/winnt/document-new.bmp | Bin 0 -> 2358 bytes
src/chrome/skin/winnt/gtk-apply.bmp | Bin 0 -> 1654 bytes
src/chrome/skin/winnt/gtk-edit.bmp | Bin 0 -> 2358 bytes
src/chrome/skin/winnt/gtk-preferences.bmp | Bin 0 -> 2358 bytes
src/modules/ctypes/winnt/user32.jsm | 93 ++++++++++++++++++++++
src/modules/ctypes/winnt/win32.jsm | 22 ++++++
src/modules/winnt/FiretrayPopupMenu.jsm | 121 +++++++++++++++++++++++++++++
src/modules/winnt/FiretrayStatusIcon.jsm | 53 ++++++++++---
9 files changed, 278 insertions(+), 11 deletions(-)
diff --git a/src/chrome/skin/winnt/application-exit.bmp b/src/chrome/skin/winnt/application-exit.bmp
new file mode 100644
index 0000000..99e6f29
Binary files /dev/null and b/src/chrome/skin/winnt/application-exit.bmp differ
diff --git a/src/chrome/skin/winnt/document-new.bmp b/src/chrome/skin/winnt/document-new.bmp
new file mode 100644
index 0000000..e7cf0af
Binary files /dev/null and b/src/chrome/skin/winnt/document-new.bmp differ
diff --git a/src/chrome/skin/winnt/gtk-apply.bmp b/src/chrome/skin/winnt/gtk-apply.bmp
new file mode 100644
index 0000000..7b5681a
Binary files /dev/null and b/src/chrome/skin/winnt/gtk-apply.bmp differ
diff --git a/src/chrome/skin/winnt/gtk-edit.bmp b/src/chrome/skin/winnt/gtk-edit.bmp
new file mode 100644
index 0000000..38b0a87
Binary files /dev/null and b/src/chrome/skin/winnt/gtk-edit.bmp differ
diff --git a/src/chrome/skin/winnt/gtk-preferences.bmp b/src/chrome/skin/winnt/gtk-preferences.bmp
new file mode 100644
index 0000000..4d579e6
Binary files /dev/null and b/src/chrome/skin/winnt/gtk-preferences.bmp differ
diff --git a/src/modules/ctypes/winnt/user32.jsm b/src/modules/ctypes/winnt/user32.jsm
index 96680c8..c1fb5a8 100644
--- a/src/modules/ctypes/winnt/user32.jsm
+++ b/src/modules/ctypes/winnt/user32.jsm
@@ -266,6 +266,99 @@ function user32_defines(lib) {
this.DT_NOPREFIX = 0x00000800;
this.DT_INTERNAL = 0x00001000;
+ lib.lazy_bind("CreatePopupMenu", win32.HMENU);
+ lib.lazy_bind("DestroyMenu", win32.BOOL, win32.HMENU);
+
+ this.MENUITEMINFOW = ctypes.StructType("MENUITEMINFOW", [
+ { "cbSize": win32.UINT },
+ { "fMask": win32.UINT },
+ { "fType": win32.UINT },
+ { "fState": win32.UINT },
+ { "wID": win32.UINT },
+ { "hSubMenu": win32.HMENU },
+ { "hbmpChecked": win32.HBITMAP },
+ { "hbmpUnchecked": win32.HBITMAP },
+ { "dwItemData": win32.ULONG_PTR },
+ { "dwTypeData": win32.LPWSTR },
+ { "cch": win32.UINT },
+ { "hbmpItem": win32.HBITMAP }
+ ]);
+ this.LPCMENUITEMINFO = this.LPMENUITEMINFOW = this.MENUITEMINFOW.ptr;
+
+ lib.lazy_bind("InsertMenuItemW", win32.BOOL, win32.HMENU, win32.UINT, win32.BOOL, this.LPCMENUITEMINFO);
+ lib.lazy_bind("GetMenuItemInfoW", win32.BOOL, win32.HMENU, win32.UINT, win32.BOOL, this.LPCMENUITEMINFO);
+
+ this.MIIM_STATE = 0x00000001;
+ this.MIIM_ID = 0x00000002;
+ this.MIIM_SUBMENU = 0x00000004;
+ this.MIIM_CHECKMARKS = 0x00000008;
+ this.MIIM_TYPE = 0x00000010;
+ this.MIIM_DATA = 0x00000020;
+ this.MIIM_STRING = 0x00000040;
+ this.MIIM_BITMAP = 0x00000080;
+ this.MIIM_FTYPE = 0x00000100;
+
+ lib.lazy_bind("InsertMenuW", win32.BOOL, win32.HMENU, win32.UINT, win32.UINT, win32.UINT_PTR, win32.LPCTSTR);
+
+ this.MF_INSERT = 0x00000000;
+ this.MF_CHANGE = 0x00000080;
+ this.MF_APPEND = 0x00000100;
+ this.MF_DELETE = 0x00000200;
+ this.MF_REMOVE = 0x00001000;
+ this.MF_BYCOMMAND = 0x00000000;
+ this.MF_BYPOSITION = 0x00000400;
+ this.MF_SEPARATOR = 0x00000800;
+ this.MF_ENABLED = 0x00000000;
+ this.MF_GRAYED = 0x00000001;
+ this.MF_DISABLED = 0x00000002;
+ this.MF_UNCHECKED = 0x00000000;
+ this.MF_CHECKED = 0x00000008;
+ this.MF_USECHECKBITMAPS = 0x00000200;
+ this.MF_STRING = 0x00000000;
+ this.MF_BITMAP = 0x00000004;
+ this.MF_OWNERDRAW = 0x00000100;
+ this.MF_POPUP = 0x00000010;
+ this.MF_MENUBARBREAK = 0x00000020;
+ this.MF_MENUBREAK = 0x00000040;
+ this.MF_UNHILITE = 0x00000000;
+ this.MF_HILITE = 0x00000080;
+ this.MF_DEFAULT = 0x00001000;
+ this.MF_RIGHTJUSTIFY = 0x00004000;
+ this.MFT_STRING = this.MF_STRING;
+ this.MFT_BITMAP = this.MF_BITMAP;
+ this.MFT_MENUBARBREAK = this.MF_MENUBARBREAK;
+ this.MFT_MENUBREAK = this.MF_MENUBREAK;
+ this.MFT_OWNERDRAW = this.MF_OWNERDRAW;
+ this.MFT_RADIOCHECK = 0x00000200;
+ this.MFT_SEPARATOR = this.MF_SEPARATOR;
+ this.MFT_RIGHTORDER = 0x00002000;
+ this.MFT_RIGHTJUSTIFY = this.MF_RIGHTJUSTIFY;
+ this.MFS_GRAYED = 0x00000003;
+ this.MFS_DISABLED = this.MFS_GRAYED;
+ this.MFS_CHECKED = this.MF_CHECKED;
+ this.MFS_HILITE = this.MF_HILITE;
+ this.MFS_ENABLED = this.MF_ENABLED;
+ this.MFS_UNCHECKED = this.MF_UNCHECKED;
+ this.MFS_UNHILITE = this.MF_UNHILITE;
+ this.MFS_DEFAULT = this.MF_DEFAULT;
+
+ this.TPM_LEFTBUTTON = 0x0000;
+ this.TPM_RIGHTBUTTON = 0x0002;
+ this.TPM_LEFTALIGN = 0x0000;
+ this.TPM_CENTERALIGN = 0x0004;
+ this.TPM_RIGHTALIGN = 0x0008;
+ this.TPM_TOPALIGN = 0x0000;
+ this.TPM_VCENTERALIGN = 0x0010;
+ this.TPM_BOTTOMALIGN = 0x0020;
+ this.TPM_HORIZONTAL = 0x0000;
+ this.TPM_VERTICAL = 0x0040;
+
+ lib.lazy_bind("CalculatePopupWindowPosition", win32.BOOL, win32.POINT.ptr, win32.SIZE, win32.UINT, win32.RECT.ptr, win32.RECT.ptr);
+ lib.lazy_bind("TrackPopupMenu", win32.BOOL, win32.HMENU, win32.UINT, ctypes.int, ctypes.int, ctypes.int, win32.HWND, win32.RECT.ptr);
+ lib.lazy_bind("SetForegroundWindow", win32.BOOL, win32.HWND);
+ lib.lazy_bind("GetCursorPos", win32.BOOL, win32.LPPOINT);
+ lib.lazy_bind("GetMessagePos", win32.DWORD);
+
}
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 a369106..00be95f 100644
--- a/src/modules/ctypes/winnt/win32.jsm
+++ b/src/modules/ctypes/winnt/win32.jsm
@@ -33,6 +33,7 @@ var win32 = new function() {
this.LONG_PTR = is64bit ? ctypes.int64_t : ctypes.long;
this.ULONG_PTR = is64bit ? ctypes.uint64_t : ctypes.unsigned_long;
this.SIZE_T = this.ULONG_PTR;
+ this.DWORD_PTR = this.ULONG_PTR;
this.ATOM = this.WORD;
this.HANDLE = ctypes.voidptr_t;
this.HWND = this.HANDLE;
@@ -77,6 +78,21 @@ var win32 = new function() {
return ctypes.jschar.array()(str);
};
+ /*
+ * #define LOWORD(l) ((WORD)((DWORD_PTR)(l) & 0xffff))
+ * #define HIWORD(l) ((WORD)((DWORD_PTR)(l) >> 16))
+ * #define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
+ * #define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
+ */
+ this.LOWORD = function(l) {return l & 0x0000ffff;};
+ this.HIWORD = function(l) {return l >> 16;};
+ /* Although we shouldn't use LO-/HIWORD to get coords, because of negative
+ coords on multi-monitor displays, I'm not sure how to express the
+ GET_?_LPARAM macros with ctypes. */
+ this.GET_X_LPARAM = this.LOWORD;
+ this.GET_Y_LPARAM = this.HIWORD;
+
+ this.ERROR_INVALID_PARAMETER = 87;
this.ERROR_INVALID_WINDOW_HANDLE = 1400;
this.ERROR_RESOURCE_TYPE_NOT_FOUND = 1813;
@@ -156,6 +172,12 @@ var win32 = new function() {
]);
this.PICONINFO = this.ICONINFO.ptr;
+ this.POINT = ctypes.StructType("POINT", [
+ { "x": this.LONG },
+ { "y": this.LONG }
+ ]);
+ this.PPOINT = this.LPPOINT =this.POINT.ptr;
+
this.RECT = ctypes.StructType("RECT", [
{ "left": this.LONG },
{ "top": this.LONG },
diff --git a/src/modules/winnt/FiretrayPopupMenu.jsm b/src/modules/winnt/FiretrayPopupMenu.jsm
new file mode 100644
index 0000000..f327779
--- /dev/null
+++ b/src/modules/winnt/FiretrayPopupMenu.jsm
@@ -0,0 +1,121 @@
+/* -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+
+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/winnt/win32.jsm");
+Cu.import("resource://firetray/ctypes/winnt/user32.jsm");
+Cu.import("resource://firetray/commons.js");
+firetray.Handler.subscribeLibsForClosing([user32]);
+
+let log = firetray.Logging.getLogger("firetray.PopupMenu");
+
+if ("undefined" == typeof(firetray.StatusIcon))
+ log.error("This module MUST be imported from/after StatusIcon !");
+
+// popupmenu items
+const IDM_PREF = 100;
+const IDM_QUIT = 200;
+const IDM_NEW_MSG = 300;
+const IDM_NEW_WND = 400;
+const IDM_RESET = 500;
+
+
+firetray.PopupMenu = {
+ initialized: false,
+ menu: null,
+
+ init: function() {
+ this.create();
+
+ this.initialized = true;
+ return true;
+ },
+
+ shutdown: function() {
+ this.destroy();
+
+ log.debug("Disabling PopupMenu");
+ this.initialized = false;
+ },
+
+ create: function() {
+ this.menu = user32.CreatePopupMenu(); // FIXME: destroy
+ log.debug("menu="+this.menu);
+
+ var addMenuSeparator = false;
+
+ this.insertMenuItem('Quit', 'quit', IDM_QUIT);
+ user32.InsertMenuW(this.menu, 0, user32.MF_BYPOSITION|user32.MF_SEPARATOR, 0, null);
+ this.insertMenuItem('Preferences', 'prefs', IDM_PREF);
+
+ if (firetray.Handler.inBrowserApp) {
+ this.insertMenuItem('NewWindow', 'new-wnd', IDM_NEW_WND);
+ addMenuSeparator = true;
+ }
+
+ if (firetray.Handler.inMailApp) {
+ this.insertMenuItem('NewMessage', 'new-msg', IDM_NEW_MSG);
+ this.insertMenuItem('ResetIcon', 'reset', IDM_RESET);
+ addMenuSeparator = true;
+ }
+
+ if (addMenuSeparator) {
+ user32.InsertMenuW(this.menu, 2, user32.MF_BYPOSITION|user32.MF_SEPARATOR, 0, null);
+ }
+
+ // // We'll user InsertMenuW for hidden windows:
+ // user32.InsertMenuW(this.menu, 0, user32.MF_BYPOSITION|user32.MF_STRING, IDM_CLOSE, "Close"); // FIXME: ampersand doesn't work ?
+
+ log.debug("PopupMenu created");
+ },
+
+ destroy: function() {
+ user32.DestroyMenu(this.menu);
+ log.debug("PopupMenu destroyed");
+ },
+
+ insertMenuItem: function(itemName, iconName, actionId) {
+ var menuItemLabel = firetray.Utils.strings.GetStringFromName("popupMenu.itemLabel."+itemName);
+ let mii = new user32.MENUITEMINFOW();
+ // BUG: ctypes doesn't detect wrong field assignments mii.size = ... ('size' undefined)
+ mii.cbSize = user32.MENUITEMINFOW.size;
+ mii.fMask = user32.MIIM_ID | user32.MIIM_STRING | user32.MIIM_DATA;
+ mii.wID = actionId;
+ // mii.dwItemData = win32.ULONG_PTR(actionId);
+ mii.dwTypeData = win32._T(menuItemLabel);
+ /* Under XP, putting a bitmap into hbmpItem results in ugly icons. We
+ should probably use HBMMENU_CALLBACK as explained in
+ http://www.nanoant.com/programming/themed-menus-icons-a-complete-vista-xp-solution.
+ But for now, we just don't display icons in XP-. */
+ if (win32.WINVER >= win32.WIN_VERSIONS["Vista"]) {
+ mii.fMask |= user32.MIIM_BITMAP;
+ mii.hbmpItem = firetray.StatusIcon.bitmaps.get(iconName);
+ }
+ log.debug("mii="+mii);
+ if (!user32.InsertMenuItemW(this.menu, 0, true, mii.address())) {
+ log.error("InsertMenuItemW failed winLastError="+ctypes.winLastError);
+ }
+ },
+
+ processMenuItem: function(itemId) {
+ switch (itemId) {
+ case IDM_PREF: firetray.Handler.openPrefWindow(); break;
+ case IDM_QUIT: firetray.Handler.quitApplication(); break;
+ case IDM_NEW_MSG: firetray.Handler.openMailMessage(); break;
+ case IDM_NEW_WND: firetray.Handler.openBrowserWindow(); break;
+ case IDM_RESET: firetray.Handler.setIconImageDefault(); break;
+ default:
+ log.error("no action for itemId ("+itemId+")");
+ }
+ }
+
+}; // firetray.PopupMenu
+
+firetray.Handler.showHidePopupMenuItems = firetray.PopupMenu.showHideWindowItems;
diff --git a/src/modules/winnt/FiretrayStatusIcon.jsm b/src/modules/winnt/FiretrayStatusIcon.jsm
index 3b79fa7..22397fa 100644
--- a/src/modules/winnt/FiretrayStatusIcon.jsm
+++ b/src/modules/winnt/FiretrayStatusIcon.jsm
@@ -27,18 +27,23 @@ let log = firetray.Logging.getLogger("firetray.StatusIcon");
if ("undefined" == typeof(firetray.Handler))
log.error("This module MUST be imported from/after FiretrayHandler !");
-FIRETRAY_ICON_CHROME_PATHS = {
+const ICON_CHROME_PATHS = {
'blank-icon': "chrome://firetray/skin/winnt/blank-icon.bmp",
- 'mail-unread': "chrome://firetray/skin/winnt/mail-unread.ico"
+ 'mail-unread': "chrome://firetray/skin/winnt/mail-unread.ico",
+ // these are for the popup menu:
+ 'prefs': "chrome://firetray/skin/winnt/gtk-preferences.bmp",
+ 'quit': "chrome://firetray/skin/winnt/application-exit.bmp",
+ 'new-wnd': "chrome://firetray/skin/winnt/document-new.bmp",
+ 'new-msg': "chrome://firetray/skin/winnt/gtk-edit.bmp",
+ 'reset': "chrome://firetray/skin/winnt/gtk-apply.bmp"
};
+
firetray.StatusIcon = {
initialized: false,
callbacks: {}, // pointers to JS functions. MUST LIVE DURING ALL THE EXECUTION
notifyIconData: null,
hwndProxy: null,
- icons: null,
- bitmaps: null,
WNDCLASS_NAME: "FireTrayHiddenWindowClass",
WNDCLASS_ATOM: null,
icons: (function(){return new ctypesMap(win32.HICON);})(),
@@ -57,12 +62,17 @@ firetray.StatusIcon = {
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();
@@ -84,8 +94,8 @@ 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 imgName in FIRETRAY_ICON_CHROME_PATHS) {
- let path = firetray.Utils.chromeToPath(FIRETRAY_ICON_CHROME_PATHS[imgName]);
+ for (let imgName in ICON_CHROME_PATHS) {
+ let path = firetray.Utils.chromeToPath(ICON_CHROME_PATHS[imgName]);
let img = this.loadImageFromFile(path);
if (img)
this[this.IMG_TYPES[img['type']]['map']].insert(imgName, img['himg']);
@@ -225,23 +235,44 @@ firetray.StatusIcon = {
} else if (uMsg === firetray.Win32.WM_TRAYMESSAGE) {
- switch (+lParam) {
+ switch (win32.LOWORD(lParam)) {
case win32.WM_LBUTTONUP:
log.debug("WM_LBUTTONUP");
firetray.Handler.showHideAllWindows();
break;
case win32.WM_RBUTTONUP:
log.debug("WM_RBUTTONUP");
- break;
case win32.WM_CONTEXTMENU:
log.debug("WM_CONTEXTMENU");
- break;
- case win32.NIN_KEYSELECT:
- log.debug("NIN_KEYSELECT");
+ /* 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);
--
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