Index: toolkit/components/Makefile.in
===================================================================
RCS file: /cvsroot/mozilla/toolkit/components/Makefile.in,v
--- toolkit/components/Makefile.in 2007-05-13 01:34:48.000000000 -0700 1.65
+++ toolkit/components/Makefile.in 2007-05-13 01:34:48.000000000 -0700
@@ -53,16 +53,17 @@ DIRS += urlformatter
# These component dirs are built only for XUL apps
ifdef MOZ_XUL_APP
DIRS += \
filepicker \
console \
viewconfig \
typeaheadfind \
+ systray \
$(NULL)
ifneq (,$(filter cocoa, $(MOZ_WIDGET_TOOLKIT)))
TOOL_DIRS += alerts
else
DIRS += alerts
endif
Index: toolkit/components/systray/content/bindings.css
===================================================================
RCS file: /cvsroot/mozilla/toolkit/components/systray/content/bindings.css,v
--- toolkit/components/systray/content/bindings.css 1969-12-31 16:00:00.000000000 -0800
+++ toolkit/components/systray/content/bindings.css 2007-05-13 01:34:48.000000000 -0700
@@ -0,0 +1,3 @@
+trayicon {
+ -moz-binding: url("chrome://systray/content/trayicon.xml#trayicon");
+}
Index: toolkit/components/systray/content/trayicon.xml
===================================================================
RCS file: /cvsroot/mozilla/toolkit/components/systray/content/trayicon.xml,v
--- toolkit/components/systray/content/trayicon.xml 1969-12-31 16:00:00.000000000 -0800
+++ toolkit/components/systray/content/trayicon.xml 2007-05-13 01:34:48.000000000 -0700
@@ -0,0 +1,378 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ "@mozilla.org/system-tray-service;1" in Components.classes &&
+ Components.classes["@mozilla.org/system-tray-service;1"]
+ .getService(Components.interfaces.nsISystemTrayService);
+
+
+
+ "@mozilla.org/window-util;1" in Components.classes &&
+ Components.classes["@mozilla.org/window-util;1"]
+ .createInstance(Components.interfaces.nsIWindowUtil);
+
+
+
+ Components.classes["@mozilla.org/appshell/window-mediator;1"]
+ .getService(Components.interfaces.nsIWindowMediator);
+
+
+ 0
+
+ false
+
+
+ ({ self: this, handleEvent :
+ function handleEvent(e) { this.self.onClosing(e); } })
+
+
+
+ ({ self: this, handleEvent :
+ function handleEvent(e) { this.self.onMinimizing(e); } })
+
+
+
+ ({ self: this, handleEvent :
+ function handleEvent(e) { this.self.onActivating(e); } })
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ this.restoreAll();
+ event.preventDefault();
+
+
+
+ var thePopup = document.getElementById(this.contextMenu);
+ if (thePopup)
+ thePopup.hidePopup();
+
+
+
+ var thePopup = document.getElementById(this.contextMenu);
+
+ var onshown = function(event) {
+ var popup = event.target;
+
+ // prevent infinite recursion (trips bug 174320)
+ popup.removeEventListener("popupshown", onshown, true);
+
+ var box = popup.popupBoxObject;
+ // display on the right so the tooltip and/or edge of screen don't
+ // get in the way
+ var x = popup.targetX - box.width;
+ var y = popup.targetY;
+
+ // show the popup in the right position
+ if (thePopup)
+ popup.hidePopup();
+ document.popupNode = null;
+
+ popup.showPopup(
+ document.documentElement,
+ x, y,
+ "context",
+ "", "");
+ }
+
+ thePopup.addEventListener("popupshown", onshown, true);
+
+ thePopup.targetX = event.screenX;
+ thePopup.targetY = event.screenY;
+
+ thePopup.hidePopup();
+ thePopup.showPopup(
+ document.documentElement, // anchoring element
+ -999999, // x
+ -999999, // y
+ "context", // type
+ "", // popupanchor (ignored)
+ ""); // popupalign (ignored)
+
+ // need to handle rollup ourselves to prevent reentrancy into our
+ // system tray WindowProc
+ // during menu frame cleanup
+ thePopup.enableRollup(false);
+
+ event.stopPropagation();
+ event.preventDefault();
+
+
+
+
Index: toolkit/components/systray/jar.mn
===================================================================
RCS file: /cvsroot/mozilla/toolkit/components/systray/jar.mn,v
--- toolkit/components/systray/jar.mn 1969-12-31 16:00:00.000000000 -0800
+++ toolkit/components/systray/jar.mn 2007-05-13 01:34:48.000000000 -0700
@@ -0,0 +1,4 @@
+toolkit.jar:
+% content systray %content/systray/
+* content/systray/trayicon.xml (content/trayicon.xml)
+* content/systray/bindings.css (content/bindings.css)
Index: toolkit/components/systray/Makefile.in
===================================================================
RCS file: /cvsroot/mozilla/toolkit/components/systray/Makefile.in,v
--- toolkit/components/systray/Makefile.in 1969-12-31 16:00:00.000000000 -0800
+++ toolkit/components/systray/Makefile.in 2007-05-13 01:34:48.000000000 -0700
@@ -0,0 +1,49 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is MinimizeToTray.
+#
+# The Initial Developer of the Original Code are
+# Mark Yen and Brad Peterson.
+# Portions created by the Initial Developer are Copyright (C) 2004
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Mark Yen , Original author
+# Brad Peterson , Original author
+# Daniel Glazman
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+DIRS = public src
+
+include $(topsrcdir)/config/rules.mk
Index: toolkit/components/systray/public/Makefile.in
===================================================================
RCS file: /cvsroot/mozilla/toolkit/components/systray/public/Makefile.in,v
--- toolkit/components/systray/public/Makefile.in 1969-12-31 16:00:00.000000000 -0800
+++ toolkit/components/systray/public/Makefile.in 2007-05-13 01:34:48.000000000 -0700
@@ -0,0 +1,54 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is MinimizeToTray.
+#
+# The Initial Developer of the Original Code are
+# Mark Yen and Brad Peterson.
+# Portions created by the Initial Developer are Copyright (C) 2004
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Mark Yen , Original author
+# Brad Peterson , Original author
+# Daniel Glazman
+# Matthew Gertner
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH=../../../..
+topsrcdir=@top_srcdir@
+srcdir=@srcdir@
+VPATH=@srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = systray
+
+XPIDLSRCS = nsISystemTrayService.idl \
+ nsIWindowUtil.idl \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
Index: toolkit/components/systray/public/nsISystemTrayService.idl
===================================================================
RCS file: /cvsroot/mozilla/toolkit/components/systray/public/nsISystemTrayService.idl,v
--- toolkit/components/systray/public/nsISystemTrayService.idl 1969-12-31 16:00:00.000000000 -0800
+++ toolkit/components/systray/public/nsISystemTrayService.idl 2007-05-13 01:34:48.000000000 -0700
@@ -0,0 +1,53 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is MinimizeToTray.
+ *
+ * The Initial Developer of the Original Code are
+ * Mark Yen and Brad Peterson.
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Yen , Original author
+ * Brad Peterson , Original author
+ * Daniel Glazman
+ * Matthew Gertner
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+interface nsIDOMWindow;
+interface nsIURI;
+
+[scriptable, uuid(2CD7469C-C8EC-48fe-9E9A-88DBECE777FC)]
+interface nsISystemTrayService : nsISupports
+{
+ void showIcon(in AString iconId, in nsIURI imageURI, in nsIDOMWindow window);
+ void hideIcon(in AString iconId);
+
+ void setTitle(in AString iconId, in AString title);
+};
Index: toolkit/components/systray/public/nsIWindowUtil.idl
===================================================================
RCS file: /cvsroot/mozilla/toolkit/components/systray/public/nsIWindowUtil.idl,v
--- toolkit/components/systray/public/nsIWindowUtil.idl 1969-12-31 16:00:00.000000000 -0800
+++ toolkit/components/systray/public/nsIWindowUtil.idl 2007-05-13 01:34:48.000000000 -0700
@@ -0,0 +1,60 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is MinimizeToTray.
+ *
+ * The Initial Developer of the Original Code are
+ * Mark Yen and Brad Peterson.
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Yen , Original author
+ * Brad Peterson , Original author
+ * Daniel Glazman
+ * Matthew Gertner
+*
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+interface nsIDocShell;
+interface nsIDOMWindow;
+interface nsIXULWindow;
+
+[scriptable, uuid(A9C9EE3D-8A13-410a-A1E0-3A14B4734ABD)]
+interface nsIWindowUtil : nsISupports
+{
+ readonly attribute nsIXULWindow xulWindow;
+ readonly attribute nsIDocShell docShell;
+ readonly attribute boolean hidden;
+
+ void init(in nsIDOMWindow win);
+
+ void minimize();
+
+ void watch();
+ void unwatch();
+};
Index: toolkit/components/systray/src/Makefile.in
===================================================================
RCS file: /cvsroot/mozilla/toolkit/components/systray/src/Makefile.in,v
--- toolkit/components/systray/src/Makefile.in 1969-12-31 16:00:00.000000000 -0800
+++ toolkit/components/systray/src/Makefile.in 2007-05-13 01:34:48.000000000 -0700
@@ -0,0 +1,124 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is MinimizeToTray.
+#
+# The Initial Developer of the Original Code are
+# Mark Yen and Brad Peterson.
+# Portions created by the Initial Developer are Copyright (C) 2004
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Mark Yen , Original author
+# Brad Peterson , Original author
+# Daniel Glazman
+# Matthew Gertner
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = systray
+LIBRARY_NAME = systemtray
+SHORT_LIBNAME = systray
+
+MOZILLA_STRICT_API = 1
+MOZILLA_INTERNAL_API = 1
+IS_COMPONENT = 1
+MODULE_NAME = systray
+
+REQUIRES = \
+ xpcom_glue \
+ xpcom \
+ widget \
+ appshell \
+ docshell \
+ dom \
+ string \
+ gfx \
+ imglib2 \
+ necko \
+ content \
+ layout \
+ xuldoc \
+ locale \
+ $(NULL)
+
+CPPSRCS = \
+ trayModule.cpp \
+ $(NULL)
+
+ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
+ CPPSRCS += \
+ nsWindowUtilWin.cpp \
+ nsSystemTrayServiceWin.cpp \
+ trayToolkitWin.cpp \
+ $(NULL)
+endif
+
+ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
+ REQUIRES += \
+ thebes \
+ $(NULL)
+ CPPSRCS += \
+ nsSystemTrayServiceGTK.cpp \
+ nsSystemTrayIconGTK.cpp \
+ $(NULL)
+ CXXFLAGS += $(TK_CFLAGS)
+endif
+
+ifeq (,$(filter $(MOZ_WIDGET_TOOLKIT),windows gtk2))
+ CPPSRCS += \
+ nsSystemTrayService.cpp \
+ $(NULL)
+endif
+
+include $(topsrcdir)/config/config.mk
+
+LIBS += \
+ $(NULL)
+
+SHARED_LIBRARY_LIBS = \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
+
+CXXFLAGS += $(TK_CFLAGS) \
+ $(NULL)
+EXTRA_DSO_LIBS = \
+ $(XPCOM_GLUE_LDOPTS) \
+ $(NULL)
+EXTRA_DSO_LDOPTS = \
+ $(EXTRA_DSO_LIBS) \
+ $(TK_LIBS) \
+ $(MOZ_COMPONENT_LIBS) \
+ $(NULL)
+
+install:: $(TARGETS)
Index: toolkit/components/systray/src/nsSystemTrayIconGTK.cpp
===================================================================
RCS file: /cvsroot/mozilla/toolkit/components/systray/src/nsSystemTrayIconGTK.cpp,v
--- toolkit/components/systray/src/nsSystemTrayIconGTK.cpp 1969-12-31 16:00:00.000000000 -0800
+++ toolkit/components/systray/src/nsSystemTrayIconGTK.cpp 2007-05-13 01:34:48.000000000 -0700
@@ -0,0 +1,279 @@
+/* vim: fileencoding=utf-8 shiftwidth=2 */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is toolkit/components/systray
+ *
+ * The Initial Developer of the Original Code is
+ * Mook .
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Brad Peterson
+ * Daniel Glazman
+ * Matthew Gertner
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsSystemTrayIconGTK.h"
+// headers for SetImageFromURI
+#include "nsServiceManagerUtils.h"
+#include "nsIInterfaceRequestorUtils.h"
+#include "imgILoader.h"
+#include "imgIRequest.h"
+#include "nsIImage.h"
+#include "nsNetError.h" // for NS_BINDING_ABORTED
+#include "gfxIImageFrame.h"
+#include "nsIImageToPixbuf.h"
+// needed for event dispatching
+#include "nsIDOMNode.h"
+#include "nsIDOMDocumentEvent.h"
+#include "nsIDOMDocument.h"
+#include "nsStringGlue.h"
+#include "nsIDOMDocumentView.h"
+#include "nsIDOMMouseEvent.h"
+#include "nsIDOMAbstractView.h"
+
+NS_IMPL_ISUPPORTS2(nsSystemTrayIconGTK,
+ imgIDecoderObserver,
+ imgIContainerObserver)
+
+nsSystemTrayIconGTK::nsSystemTrayIconGTK()
+ :mSigPopup(G_MAXULONG),
+ mSigActivate(G_MAXULONG)
+{
+ // make the new icon (have a default image in case things break later)
+ mIcon = gtk_status_icon_new_from_stock(GTK_STOCK_MISSING_IMAGE);
+}
+
+nsSystemTrayIconGTK::~nsSystemTrayIconGTK()
+{
+ if (mIcon) {
+ g_object_unref(mIcon);
+ mIcon = nsnull;
+ }
+ if (mRequest) {
+ mRequest->Cancel(NS_BINDING_ABORTED);
+ }
+}
+
+nsresult nsSystemTrayIconGTK::SetImageFromURI(nsIURI* aURI)
+{
+ nsresult rv;
+
+ nsCOMPtr imgloader =
+ do_GetService("@mozilla.org/image/loader;1", &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (mRequest) {
+ mRequest->Cancel(NS_BINDING_ABORTED);
+ }
+ rv = imgloader->LoadImage(aURI, aURI, aURI, nsnull, this, nsnull,
+ nsIRequest::LOAD_BACKGROUND, nsnull, nsnull,
+ getter_AddRefs(mRequest));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return NS_OK;
+}
+
+nsresult nsSystemTrayIconGTK::SetEventTarget(nsIDOMEventTarget *aEventTarget)
+{
+ if (!mIcon) {
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+
+ mEventTarget = aEventTarget;
+
+ if (G_MAXULONG == mSigPopup) {
+ // popup signal not connected yet, do so now
+ mSigPopup = g_signal_connect(G_OBJECT(mIcon), "popup-menu",
+ G_CALLBACK(OnPopupMenu), this);
+ }
+
+ if (G_MAXULONG == mSigActivate) {
+ // connect the activate signal
+ mSigActivate = g_signal_connect(G_OBJECT(mIcon), "activate",
+ G_CALLBACK(OnActivate), this);
+ }
+
+ return NS_OK;
+}
+
+void nsSystemTrayIconGTK::OnPopupMenu(GtkStatusIcon *status_icon,
+ guint button,
+ guint activate_time,
+ gpointer user_data)
+{
+ // we got a "popup menu" signal, tell Gecko to dispatch a context menu event
+ nsSystemTrayIconGTK *self =
+ NS_REINTERPRET_CAST(nsSystemTrayIconGTK*, user_data);
+ self->DispatchEvent(NS_LITERAL_STRING("contextmenu"), 2 /* right button */);
+}
+
+void nsSystemTrayIconGTK::OnActivate(GtkStatusIcon *status_icon,
+ gpointer user_data)
+{
+ nsSystemTrayIconGTK *self =
+ NS_REINTERPRET_CAST(nsSystemTrayIconGTK*, user_data);
+ self->DispatchEvent(NS_LITERAL_STRING("mousedown"), 0 /* left button */);
+ self->DispatchEvent(NS_LITERAL_STRING("mouseup"), 0 /* left button */);
+ self->DispatchEvent(NS_LITERAL_STRING("click"), 0 /* left button */);
+}
+
+void nsSystemTrayIconGTK::DispatchEvent(const nsAString& aType, PRUint16 aButton)
+{
+ nsresult rv;
+
+ // first, create an event...
+ nsCOMPtr node(do_QueryInterface(mEventTarget, &rv));
+ if (NS_FAILED(rv)) return;
+
+ nsCOMPtr doc;
+ rv = node->GetOwnerDocument(getter_AddRefs(doc));
+ if (NS_FAILED(rv)) return;
+
+ nsCOMPtr docEvent(do_QueryInterface(doc, &rv));
+ if (NS_FAILED(rv)) return;
+
+ nsCOMPtr event;
+ rv = docEvent->CreateEvent(NS_LITERAL_STRING("mouseevent"),
+ getter_AddRefs(event));
+ if (NS_FAILED(rv)) return;
+
+ nsCOMPtr mouseEvent(do_QueryInterface(event, &rv));
+ if (NS_FAILED(rv)) return;
+
+ // get the view the event occurred on
+ nsCOMPtr documentView(do_QueryInterface(doc, &rv));
+ if (NS_FAILED(rv)) return;
+
+ nsCOMPtr view;
+ rv = documentView->GetDefaultView(getter_AddRefs(view));
+ if (NS_FAILED(rv)) return;
+
+ // figure out where to position the popup
+ GdkRectangle rect;
+ gboolean hasRect;
+ hasRect = gtk_status_icon_get_geometry(mIcon, NULL, &rect, NULL);
+ if (!hasRect) {
+ rect.x = rect.y = 0;
+ }
+
+ // initialize the event
+ // TODO: give useful arguments here
+ rv = mouseEvent->InitMouseEvent(aType,
+ PR_FALSE, PR_TRUE, view, 1 /*single click*/,
+ rect.x, rect.y, rect.x, rect.y,
+ 0, 0, 0, 0, aButton, nsnull);
+ if (NS_FAILED(rv)) return;
+
+ // and dispatch it. (yes, return value is ignored; we can't do anything)
+ PRBool result;
+ mEventTarget->DispatchEvent(event, &result);
+}
+
+///// imgIDecoderObserver
+/* void onStartRequest (in imgIRequest aRequest); */
+NS_IMETHODIMP nsSystemTrayIconGTK::OnStartRequest(imgIRequest *aRequest)
+{
+ return NS_OK;
+}
+
+/* void onStartDecode (in imgIRequest aRequest); */
+NS_IMETHODIMP nsSystemTrayIconGTK::OnStartDecode(imgIRequest *aRequest)
+{
+ return NS_OK;
+}
+
+/* void onStartContainer (in imgIRequest aRequest, in imgIContainer aContainer); */
+NS_IMETHODIMP nsSystemTrayIconGTK::OnStartContainer(imgIRequest *aRequest, imgIContainer *aContainer)
+{
+ return NS_OK;
+}
+
+/* void onStartFrame (in imgIRequest aRequest, in gfxIImageFrame aFrame); */
+NS_IMETHODIMP nsSystemTrayIconGTK::OnStartFrame(imgIRequest *aRequest, gfxIImageFrame *aFrame)
+{
+ return NS_OK;
+}
+
+/* [noscript] void onDataAvailable (in imgIRequest aRequest, in gfxIImageFrame aFrame, [const] in nsIntRect aRect); */
+NS_IMETHODIMP nsSystemTrayIconGTK::OnDataAvailable(imgIRequest *aRequest, gfxIImageFrame *aFrame, const nsIntRect * aRect)
+{
+ return NS_OK;
+}
+
+/* void onStopFrame (in imgIRequest aRequest, in gfxIImageFrame aFrame); */
+NS_IMETHODIMP nsSystemTrayIconGTK::OnStopFrame(imgIRequest *aRequest, gfxIImageFrame *aFrame)
+{
+ // the frame is done; put it in the tray
+ nsresult rv;
+
+ if (!mIcon) {
+ // ... our icon went away somewhere, oops
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ nsCOMPtr img(do_GetInterface(aFrame, &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr imgToPixbuf =
+ do_GetService("@mozilla.org/widget/image-to-gdk-pixbuf;1", &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ GdkPixbuf* pixbuf = imgToPixbuf->ConvertImageToPixbuf(img);
+ if (!pixbuf) {
+ return NS_ERROR_FAILURE;
+ }
+
+ gtk_status_icon_set_from_pixbuf(mIcon, pixbuf);
+ return NS_OK;
+}
+
+/* void onStopContainer (in imgIRequest aRequest, in imgIContainer aContainer); */
+NS_IMETHODIMP nsSystemTrayIconGTK::OnStopContainer(imgIRequest *aRequest, imgIContainer *aContainer)
+{
+ return NS_OK;
+}
+
+/* void onStopDecode (in imgIRequest aRequest, in nsresult status, in wstring statusArg); */
+NS_IMETHODIMP nsSystemTrayIconGTK::OnStopDecode(imgIRequest *aRequest, nsresult status, const PRUnichar *statusArg)
+{
+ return NS_OK;
+}
+
+/* void onStopRequest (in imgIRequest aRequest, in boolean aIsLastPart); */
+NS_IMETHODIMP nsSystemTrayIconGTK::OnStopRequest(imgIRequest *aRequest, PRBool aIsLastPart)
+{
+ return NS_OK;
+}
+
+///// imgIContainerObserver
+/* [noscript] void frameChanged (in imgIContainer aContainer, in gfxIImageFrame aFrame, in nsIntRect aDirtyRect); */
+NS_IMETHODIMP nsSystemTrayIconGTK::FrameChanged(imgIContainer *aContainer, gfxIImageFrame *aFrame, nsIntRect * aDirtyRect)
+{
+ return NS_OK;
+}
Index: toolkit/components/systray/src/nsSystemTrayIconGTK.h
===================================================================
RCS file: /cvsroot/mozilla/toolkit/components/systray/src/nsSystemTrayIconGTK.h,v
--- toolkit/components/systray/src/nsSystemTrayIconGTK.h 1969-12-31 16:00:00.000000000 -0800
+++ toolkit/components/systray/src/nsSystemTrayIconGTK.h 2007-05-13 01:34:48.000000000 -0700
@@ -0,0 +1,82 @@
+/* vim: fileencoding=utf-8 shiftwidth=2 */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is toolkit/components/systray
+ *
+ * The Initial Developer of the Original Code is
+ * Mook .
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Brad Peterson
+ * Daniel Glazman
+ * Matthew Gertner
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.h"
+#include
+#include "nsIDOMEventTarget.h"
+// for SetImageFromURI
+#include "imgIDecoderObserver.h"
+#include "imgIRequest.h"
+#include "nsCOMPtr.h"
+
+class nsIURI;
+class nsIDOMEventTarget;
+
+// this is a private class; it maps to a actual icon in the tray
+class nsSystemTrayIconGTK : public imgIDecoderObserver
+{
+ NS_DECL_ISUPPORTS
+ NS_DECL_IMGIDECODEROBSERVER
+ NS_DECL_IMGICONTAINEROBSERVER
+public:
+ nsSystemTrayIconGTK();
+ ~nsSystemTrayIconGTK();
+ nsresult SetImageFromURI(nsIURI* aURI);
+ nsresult SetEventTarget(nsIDOMEventTarget* aEventTarget);
+
+ // this class owns an instance to the icon
+ // the icon has a non-owning refence back.
+ GtkStatusIcon *mIcon;
+
+protected:
+ // for SetImageFromURI
+ nsCOMPtr mRequest;
+ nsCOMPtr mEventTarget;
+
+ static void OnPopupMenu(GtkStatusIcon *status_icon,
+ guint button,
+ guint activate_time,
+ gpointer user_data);
+ static void OnActivate(GtkStatusIcon *status_icon,
+ gpointer user_data);
+ void DispatchEvent(const nsAString& aType, PRUint16 aButton);
+ gulong mSigPopup;
+ gulong mSigActivate;
+};
Index: toolkit/components/systray/src/nsSystemTrayService.cpp
===================================================================
RCS file: /cvsroot/mozilla/toolkit/components/systray/src/nsSystemTrayService.cpp,v
--- toolkit/components/systray/src/nsSystemTrayService.cpp 1969-12-31 16:00:00.000000000 -0800
+++ toolkit/components/systray/src/nsSystemTrayService.cpp 2007-05-13 01:34:48.000000000 -0700
@@ -0,0 +1,69 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is MinimizeToTray.
+ *
+ * The Initial Developer of the Original Code are
+ * Mark Yen and Brad Peterson.
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Yen , Original author
+ * Brad Peterson , Original author
+ * Daniel Glazman
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsSystemTrayService.h"
+
+NS_IMPL_ISUPPORTS1(nsSystemTrayService, nsISystemTrayService)
+
+nsSystemTrayService::nsSystemTrayService()
+{
+}
+
+nsSystemTrayService::~nsSystemTrayService()
+{
+}
+
+NS_IMETHODIMP
+nsSystemTrayService::ShowIcon(const nsAString& aIconId,
+ nsIURI* imageURI, nsIDOMWindow* aDOMWindow)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsSystemTrayService::HideIcon(const nsAString& iconId)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsSystemTrayService::SetTitle(const nsAString& iconId, const nsAString& title)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
Index: toolkit/components/systray/src/nsSystemTrayServiceGTK.cpp
===================================================================
RCS file: /cvsroot/mozilla/toolkit/components/systray/src/nsSystemTrayServiceGTK.cpp,v
--- toolkit/components/systray/src/nsSystemTrayServiceGTK.cpp 1969-12-31 16:00:00.000000000 -0800
+++ toolkit/components/systray/src/nsSystemTrayServiceGTK.cpp 2007-05-13 01:34:48.000000000 -0700
@@ -0,0 +1,124 @@
+/* vim: fileencoding=utf-8 shiftwidth=2 */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is toolkit/components/systray
+ *
+ * The Initial Developer of the Original Code is
+ * Mook .
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Brad Peterson
+ * Daniel Glazman
+ * Matthew Gertner
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsSystemTrayServiceGTK.h"
+#include "nsIURI.h"
+#include "nsIDOMDocument.h"
+#include "nsIDOMWindow.h"
+#include "nsIDOMXULElement.h"
+#include "nsStringGlue.h"
+#include "nsIDOMEventTarget.h"
+
+NS_IMPL_ISUPPORTS1(nsSystemTrayService,
+ nsISystemTrayService)
+
+nsSystemTrayService::nsSystemTrayService()
+{
+ mIconDataMap.Init();
+}
+
+nsSystemTrayService::~nsSystemTrayService()
+{
+ // no need to clean up the icons, because the hashtable will delete the
+ // wrappers, which will remove the icons for us
+}
+
+/* void showIcon (in AString iconId, in nsIURI imageURI, in nsIDOMWindow window); */
+NS_IMETHODIMP nsSystemTrayService::ShowIcon(const nsAString & aIconId, nsIURI *aImageURI, nsIDOMWindow *aDOMWindow)
+{
+ nsresult rv;
+ nsCOMPtr icon;
+ if (mIconDataMap.Get(aIconId, getter_AddRefs(icon))) {
+ // we are updating an old icon
+ return icon->SetImageFromURI(aImageURI);
+ }
+
+ // first make sure that we can find the element associated with the
+ // element
+ nsCOMPtr document;
+ rv = aDOMWindow->GetDocument(getter_AddRefs(document));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr iconElement;
+ rv = document->GetElementById(aIconId, getter_AddRefs(iconElement));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr eventTarget =
+ do_QueryInterface(iconElement, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // okay, make a new icon and tell it about the event target
+ icon = new nsSystemTrayIconGTK();
+ if (!icon || !icon->mIcon) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ rv = icon->SetEventTarget(eventTarget);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ mIconDataMap.Put(aIconId, icon);
+ return icon->SetImageFromURI(aImageURI);
+}
+
+/* void hideIcon (in AString iconId); */
+NS_IMETHODIMP nsSystemTrayService::HideIcon(const nsAString & aIconId)
+{
+ if (!mIconDataMap.Get(aIconId, nsnull)) {
+ // we don't know about this icon in the first place
+ return NS_ERROR_INVALID_ARG;
+ }
+ // destructing the icon removes it for us
+ mIconDataMap.Remove(aIconId);
+ return NS_OK;
+}
+
+/* void setTitle (in AString iconId, in AString title); */
+NS_IMETHODIMP nsSystemTrayService::SetTitle(const nsAString & aIconId, const nsAString & aTitle)
+{
+ nsCOMPtr icon;
+ mIconDataMap.Get(aIconId, getter_AddRefs(icon));
+ if (!icon) {
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ // XXX Mook: OOM
+ gtk_status_icon_set_tooltip(icon->mIcon, NS_ConvertUTF16toUTF8(aTitle).get());
+ return NS_OK;
+}
Index: toolkit/components/systray/src/nsSystemTrayServiceGTK.h
===================================================================
RCS file: /cvsroot/mozilla/toolkit/components/systray/src/nsSystemTrayServiceGTK.h,v
--- toolkit/components/systray/src/nsSystemTrayServiceGTK.h 1969-12-31 16:00:00.000000000 -0800
+++ toolkit/components/systray/src/nsSystemTrayServiceGTK.h 2007-05-13 01:34:48.000000000 -0700
@@ -0,0 +1,76 @@
+/* vim: fileencoding=utf-8 shiftwidth=2 */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is toolkit/components/systray
+ *
+ * The Initial Developer of the Original Code is
+ * Mook .
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Brad Peterson
+ * Daniel Glazman
+ * Matthew Gertner
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsSystemTrayServiceGTK_h__
+#define nsSystemTrayServiceGTK_h__
+
+#include "nsISystemTrayService.h"
+#include "gtk/gtk.h"
+#include "nsInterfaceHashtable.h"
+#include "nsSystemTrayIconGTK.h"
+
+class nsIURI;
+
+class nsSystemTrayService : public nsISystemTrayService
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISYSTEMTRAYSERVICE
+
+ nsSystemTrayService();
+
+private:
+ ~nsSystemTrayService();
+
+protected:
+ nsInterfaceHashtable mIconDataMap;
+};
+
+#define NS_SYSTEMTRAYSERVICE_CONTRACTID \
+ "@mozilla.org/system-tray-service;1"
+
+#define NS_SYSTEMTRAYSERVICE_CLASSNAME "GTK System Tray Service"
+
+// 1a2bca5e-c624-491c-af6e-23a19d7f7479
+#define NS_SYSTEMTRAYSERVICE_CID \
+ { 0x1a2bca5e, 0xc624, 0x491c, \
+ { 0xaf, 0x6e, 0x23, 0xa1, 0x9d, 0x7f, 0x74, 0x79 } }
+
+#endif /* nsSystemTrayServiceGTK_h__ */
Index: toolkit/components/systray/src/nsSystemTrayService.h
===================================================================
RCS file: /cvsroot/mozilla/toolkit/components/systray/src/nsSystemTrayService.h,v
--- toolkit/components/systray/src/nsSystemTrayService.h 1969-12-31 16:00:00.000000000 -0800
+++ toolkit/components/systray/src/nsSystemTrayService.h 2007-05-13 01:34:48.000000000 -0700
@@ -0,0 +1,72 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is MinimizeToTray.
+ *
+ * The Initial Developer of the Original Code are
+ * Mark Yen and Brad Peterson.
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Yen , Original author
+ * Brad Peterson , Original author
+ * Daniel Glazman
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef ULONG_PTR
+#define ULONG_PTR DWORD
+#endif
+
+#ifndef nsSystemTrayService_h__
+#define nsSystemTrayService_h__
+
+#include "nsISystemTrayService.h"
+
+// {F53FCEFA-2F53-40cf-BBAF-2F5896A56E82}
+#define NS_SYSTEMTRAYSERVICE_CID \
+ { 0xf53fcefa, 0x2f53, 0x40cf, \
+ { 0xbb, 0xaf, 0x2f, 0x58, 0x96, 0xa5, 0x6e, 0x82 } }
+
+#define NS_SYSTEMTRAYSERVICE_CONTRACTID \
+ "@mozilla.org/system-tray-service;1"
+
+#define NS_SYSTEMTRAYSERVICE_CLASSNAME "System Tray Service"
+
+class nsSystemTrayService : public nsISystemTrayService
+{
+public:
+ NS_DECL_NSISYSTEMTRAYSERVICE
+
+ nsSystemTrayService();
+
+private:
+ ~nsSystemTrayService();
+
+protected:
+};
+
+#endif // nsSystemTrayService_h__
Index: toolkit/components/systray/src/nsSystemTrayServiceWin.cpp
===================================================================
RCS file: /cvsroot/mozilla/toolkit/components/systray/src/nsSystemTrayServiceWin.cpp,v
--- toolkit/components/systray/src/nsSystemTrayServiceWin.cpp 1969-12-31 16:00:00.000000000 -0800
+++ toolkit/components/systray/src/nsSystemTrayServiceWin.cpp 2007-05-13 01:34:48.000000000 -0700
@@ -0,0 +1,1130 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is MinimizeToTray.
+ *
+ * The Initial Developer of the Original Code are
+ * Mark Yen and Brad Peterson.
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Yen , Original author
+ * Brad Peterson , Original author
+ * Daniel Glazman
+ * Matthew Gertner
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsSystemTrayServiceWin.h"
+#include "gfxIImageFrame.h"
+#include "imgIContainer.h"
+#include "imgIDecoder.h"
+#include "nsAutoPtr.h"
+#include "nsComponentManagerUtils.h"
+#include "nsMemory.h"
+#include "nsIBaseWindow.h"
+#include "nsIBufferedStreams.h"
+#include "nsIChannel.h"
+#include "nsIContent.h"
+#include "nsIDocShell.h"
+#include "nsIDocument.h"
+#include "nsIDOMAbstractView.h"
+#include "nsIDOMDocument.h"
+#include "nsIDOMDocumentEvent.h"
+#include "nsIDOMDocumentView.h"
+#include "nsIDOMDOMImplementation.h"
+#include "nsIDOMDocumentType.h"
+#include "nsIDOMElement.h"
+#include "nsIDOMEvent.h"
+#include "nsIDOMEventTarget.h"
+#include "nsIDOMMouseEvent.h"
+#include "nsIDOMNodeList.h"
+#include "nsIDOMWindow.h"
+#include "nsIDOMXULElement.h"
+#include "nsIFrame.h"
+#include "nsIInterfaceRequestor.h"
+#include "nsIInterfaceRequestorUtils.h"
+#include "nsIIOService.h"
+#include "nsIMenuParent.h"
+#include "nsIPresShell.h"
+#include "nsIWidget.h"
+#include "nsIWindowUtil.h"
+#include "nsIURI.h"
+#include "nsIXULDocument.h"
+#include "nsIXULWindow.h"
+#include "nsServiceManagerUtils.h"
+#include "nsString.h"
+#include "trayToolkitWin.h"
+
+#ifdef MOZILLA_1_8_BRANCH
+#define ICON_WIDTH 16
+#define ICON_HEIGHT 16
+#else
+#include "nsIImageToBitmap.h"
+#endif
+
+#pragma comment(lib, "shell32.lib")
+
+const TCHAR* nsSystemTrayService::S_PROPINST =
+ TEXT("_SYSTEMTRAYSERVICE_INST");
+const TCHAR* nsSystemTrayService::S_PROPPROC =
+ TEXT("_SYSTEMTRAYSERVICE_PROC");
+
+ATOM nsSystemTrayService::s_wndClass = NULL;
+
+#define MK_ERROR_OFFSET (0xE0000000 + (__LINE__ * 0x10000))
+
+#define MK_ENSURE_NATIVE(res) \
+ PR_BEGIN_MACRO \
+ NS_ENSURE_TRUE(0 != res || 0 == ::GetLastError(), \
+ ::GetLastError() + MK_ERROR_OFFSET); \
+ PR_END_MACRO
+
+// this can be WM_USER + anything
+#define WM_TRAYICON (WM_USER + 0x17b6)
+
+NS_IMPL_ISUPPORTS5(nsSystemTrayService, nsISystemTrayService,
+ nsIDOMEventListener, imgILoad, imgIContainerObserver,
+ imgIDecoderObserver)
+
+nsSystemTrayService::nsSystemTrayService()
+{
+ /* member initializers and constructor code */
+ mIconDataMap.Init();
+
+ trayToolkit::Init();
+}
+
+nsSystemTrayService::~nsSystemTrayService()
+{
+ BOOL windowClassUnregistered = ::UnregisterClass(
+ (LPCTSTR)nsSystemTrayService::s_wndClass,
+ ::GetModuleHandle(NULL));
+ if (windowClassUnregistered)
+ nsSystemTrayService::s_wndClass = NULL;
+}
+
+NS_IMETHODIMP
+nsSystemTrayService::ShowIcon(const nsAString& aIconId,
+ nsIURI* imageURI, nsIDOMWindow* aDOMWindow)
+{
+ nsresult rv;
+
+ NOTIFYICONDATAW notifyIconData;
+ if (mIconDataMap.Get(aIconId, ¬ifyIconData))
+ // Already have an entry so just change the image
+ {
+ HICON hicon;
+ rv = GetIconForURI(imageURI, hicon);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ notifyIconData.hIcon = hicon;
+ MK_ENSURE_NATIVE(trayToolkit::pShell_NotifyIcon(NIM_MODIFY,
+ ¬ifyIconData));
+
+ return NS_OK;
+ }
+
+ // first make sure that we can find the element associated with the
+ // element
+ nsCOMPtr document;
+ rv = aDOMWindow->GetDocument(getter_AddRefs(document));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr iconElement;
+ rv = document->GetElementById(aIconId, getter_AddRefs(iconElement));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // register listeners for the popup window (if any) so we can subclass it
+ nsCOMPtr xulElement(do_QueryInterface(iconElement, &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoString contextMenu;
+ rv = xulElement->GetContextMenu(contextMenu);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (!contextMenu.IsEmpty())
+ {
+ nsCOMPtr popupElement;
+ rv = document->GetElementById(contextMenu, getter_AddRefs(popupElement));
+ if (NS_SUCCEEDED(rv))
+ {
+ nsCOMPtr eventTarget(do_QueryInterface(popupElement,
+ &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = eventTarget->AddEventListener(NS_LITERAL_STRING("popupshown"),
+ this, PR_TRUE);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = eventTarget->AddEventListener(NS_LITERAL_STRING("popuphiding"),
+ this, PR_TRUE);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+ }
+
+ nsCOMPtr
+ windowUtil(do_CreateInstance("@mozilla.org/window-util;1", &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = windowUtil->Init(aDOMWindow);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr docShell;
+ rv = windowUtil->GetDocShell(getter_AddRefs(docShell));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr baseWindow(do_QueryInterface(docShell, &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nativeWindow theNativeWindow;
+ rv = baseWindow->GetParentNativeWindow( &theNativeWindow );
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ HWND hWnd = NS_REINTERPRET_CAST(HWND, theNativeWindow);
+ NS_ENSURE_TRUE(hWnd, NS_ERROR_UNEXPECTED);
+
+ // yay, we succeeded so we can add the icon
+ rv = AddTrayIcon(hWnd, imageURI, aIconId, iconElement);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsSystemTrayService::HideIcon(const nsAString& iconId)
+{
+ NOTIFYICONDATAW notifyIconData;
+ if (!mIconDataMap.Get(iconId, ¬ifyIconData))
+ // can't find the icon data
+ return NS_ERROR_NOT_AVAILABLE;
+
+ if (notifyIconData.hWnd)
+ ::DestroyWindow(notifyIconData.hWnd);
+
+ trayToolkit::pShell_NotifyIcon(NIM_DELETE, ¬ifyIconData);
+
+ mIconDataMap.Remove(iconId);
+
+ return NS_OK;
+}
+
+nsresult
+nsSystemTrayService::AddTrayIcon(HWND hwnd, nsIURI* iconURI,
+ const nsAString& iconId,
+ nsIDOMElement* targetElement)
+{
+ nsresult rv;
+
+ NOTIFYICONDATAW notifyIconData;
+ memset(¬ifyIconData, 0, sizeof(NOTIFYICONDATAW));
+ notifyIconData.cbSize = sizeof(NOTIFYICONDATAW);
+ notifyIconData.uCallbackMessage = WM_TRAYICON;
+ notifyIconData.uID = 1;
+ notifyIconData.uFlags = NIF_MESSAGE | NIF_ICON;
+
+ HICON hicon = NULL;
+ if (iconURI)
+ {
+ rv = GetIconForURI(iconURI, hicon);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ if (!hicon)
+ {
+ // just use the window icon
+ rv = GetIconForWnd(hwnd, hicon);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ notifyIconData.hIcon = hicon;
+
+ HWND listenerWindow;
+ rv = CreateListenerWindow(&listenerWindow, targetElement);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ //::SetTimer(listenerWindow, 1, 100, NULL);
+
+// add the icon
+ notifyIconData.hWnd = listenerWindow;
+ MK_ENSURE_NATIVE(trayToolkit::pShell_NotifyIcon(NIM_ADD, ¬ifyIconData));
+
+ mIconDataMap.Put(iconId, notifyIconData);
+
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsSystemTrayService::SetTitle(const nsAString& iconId, const nsAString& title)
+{
+ NOTIFYICONDATAW notifyIconData;
+ if (!mIconDataMap.Get(iconId, ¬ifyIconData))
+ return NS_ERROR_NOT_AVAILABLE;
+
+ notifyIconData.uFlags = NIF_TIP;
+ PRUint32 length = title.Length();
+ if (length > 64)
+ length = 64;
+
+ wcsncpy(notifyIconData.szTip, PromiseFlatString(title).get(), length);
+
+ MK_ENSURE_NATIVE(trayToolkit::pShell_NotifyIcon(NIM_MODIFY, ¬ifyIconData));
+
+ return NS_OK;
+}
+
+nsresult
+nsSystemTrayService::GetIconForURI(nsIURI* iconURI, HICON& result)
+{
+ nsresult rv;
+
+ // get a channel to read the data from
+ nsCOMPtr
+ ioService(do_GetService("@mozilla.org/network/io-service;1", &rv));
+ nsCOMPtr channel;
+ rv = ioService->NewChannelFromURI(iconURI, getter_AddRefs(channel));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr inputStream;
+ rv = channel->Open(getter_AddRefs(inputStream));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // get the source MIME type
+ nsCAutoString sourceMimeType;
+ rv = channel->GetContentType(sourceMimeType);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // get the decoder
+ nsCAutoString decoderContractId =
+ NS_LITERAL_CSTRING("@mozilla.org/image/decoder;2?type=") + sourceMimeType;
+ nsCOMPtr
+ decoder(do_CreateInstance(decoderContractId.get(), &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // decode into our image container
+ rv = decoder->Init(this);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ PRUint32 available;
+ rv = inputStream->Available(&available);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // need to wrap the stream so that the decoder can ReadSegments
+ nsCOMPtr bufferedStream(
+ do_CreateInstance("@mozilla.org/network/buffered-input-stream;1", &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = bufferedStream->Init(inputStream, 4096);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ PRUint32 written;
+ rv = decoder->WriteFrom(bufferedStream, available, &written);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = decoder->Close();
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr imageFrame;
+ rv = mImage->GetFrameAt(0, getter_AddRefs(imageFrame));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+#ifdef MOZILLA_1_8_BRANCH
+ // Remove the mutable flag from the frame (set for some reason by the
+ // decoder) so that we don't get warnings when we retrieve the alpha data
+ rv = imageFrame->SetMutable(PR_TRUE);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ PRUint8 *alphaData, *rgbData;
+ PRUint32 alphaLen, rgbLen, alphaBits;
+ PRUint32 alphaStride, rgbStride;
+ PRInt32 width, height;
+ gfx_format format;
+
+ alphaData = rgbData = 0;
+
+ imageFrame->GetWidth(&width);
+ imageFrame->GetHeight(&height);
+ imageFrame->GetFormat(&format);
+
+ alphaBits = format > 3 ? 8 : format > 1 ? 1 : 0;
+
+ rv = imageFrame->LockImageData();
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (alphaBits) {
+ rv = imageFrame->LockAlphaData();
+ if (NS_FAILED(rv))
+ goto clean1;
+ rv = imageFrame->GetAlphaBytesPerRow(&alphaStride);
+ rv |= imageFrame->GetAlphaData(&alphaData, &alphaLen);
+ if (NS_FAILED(rv)) {
+ imageFrame->UnlockAlphaData();
+ goto clean1;
+ }
+ }
+
+ rv = imageFrame->GetImageBytesPerRow(&rgbStride);
+ rv |= imageFrame->GetImageData(&rgbData, &rgbLen);
+ if (NS_FAILED(rv))
+ goto clean2;
+
+ rv = ProcessImageData(width, height, rgbData, rgbStride, rgbLen,
+ alphaData, alphaStride, alphaBits, result);
+
+clean2:
+ if (alphaData)
+ imageFrame->UnlockAlphaData();
+clean1:
+ imageFrame->UnlockImageData();
+
+ return rv;
+
+#else
+ nsCOMPtr imageToBitmap(
+ do_GetService("@mozilla.org/widget/image-to-win-bitmap;1", &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return imageToBitmap->ConvertImageToIcon(imageFrame, result);
+#endif
+}
+
+nsresult
+nsSystemTrayService::GetIconForWnd(HWND hwnd, HICON& result)
+{
+ result = (HICON)::SendMessage(hwnd, WM_GETICON, ICON_SMALL, NULL);
+ if (!result) {
+ // can't find icon; try GetClassLong
+ result = (HICON)::GetClassLongPtr(hwnd, GCLP_HICONSM);
+ }
+ if (!result) {
+ // still no icon - use generic windows icon
+ result = ::LoadIcon(NULL, IDI_WINLOGO);
+ }
+ if (!result)
+ return NS_ERROR_FAILURE;
+ return NS_OK;
+}
+
+nsresult
+nsSystemTrayService::CreateListenerWindow(HWND* listenerWindow,
+ nsIDOMElement* targetElement)
+{
+ ::SetLastError(0);
+ HINSTANCE hInst = ::GetModuleHandle(NULL);
+ MK_ENSURE_NATIVE(hInst);
+
+ if (!nsSystemTrayService::s_wndClass) {
+ WNDCLASS wndClassDef;
+ wndClassDef.style = CS_NOCLOSE | CS_GLOBALCLASS;
+ wndClassDef.lpfnWndProc = nsSystemTrayService::WindowProc;
+ wndClassDef.cbClsExtra = 0;
+ wndClassDef.cbWndExtra = 0;
+ wndClassDef.hInstance = hInst;
+ wndClassDef.hIcon = NULL;
+ wndClassDef.hCursor = NULL;
+ wndClassDef.hbrBackground = NULL;
+ wndClassDef.lpszMenuName = NULL;
+ wndClassDef.lpszClassName = TEXT("MinimizeToTray:MessageWindowClass");
+
+ nsSystemTrayService::s_wndClass = ::RegisterClass(&wndClassDef);
+ MK_ENSURE_NATIVE(nsSystemTrayService::s_wndClass);
+ }
+
+ *listenerWindow =
+ ::CreateWindow(
+ (LPCTSTR)nsSystemTrayService::s_wndClass, //class
+ TEXT("MinimizeToTray:MessageWindow"), //caption
+ WS_MINIMIZE, //style
+ CW_USEDEFAULT , //x
+ CW_USEDEFAULT , //y
+ CW_USEDEFAULT, //width
+ CW_USEDEFAULT, //height
+ ::GetDesktopWindow(), //parent
+ NULL, //menu
+ hInst, //hInst
+ NULL); //param
+
+ if (!*listenerWindow) {
+ if (::UnregisterClass((LPCTSTR)nsSystemTrayService::s_wndClass, hInst))
+ nsSystemTrayService::s_wndClass = NULL;
+ MK_ENSURE_NATIVE(*listenerWindow);
+ }
+
+ MK_ENSURE_NATIVE(::SetProp(
+ *listenerWindow,
+ S_PROPINST,
+ (HANDLE) targetElement)
+ );
+
+ return NS_OK;
+}
+
+// a little helper class to automatically manage our reentrancy counter
+// if we reenter WindowProc very bad things happen
+class AutoReentryBlocker
+{
+public:
+ AutoReentryBlocker(PRUint32* counter) { mCounter = counter; (*mCounter)++; }
+ ~AutoReentryBlocker() { (*mCounter)--; }
+
+protected:
+ PRUint32* mCounter;
+};
+
+static PRUint32 numberOfCallsIntoWindowProc = 0;
+
+LRESULT CALLBACK
+nsSystemTrayService::PopupWindowProc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ WNDPROC oldProc = (WNDPROC) ::GetProp(hwnd, S_PROPPROC);
+ if (!oldProc)
+ oldProc = DefWindowProc;
+
+ if (uMsg == WM_MOUSEACTIVATE)
+ return MA_NOACTIVATE;
+
+ return ::CallWindowProc(
+ oldProc,
+ hwnd,
+ uMsg,
+ wParam,
+ lParam);
+}
+
+LRESULT CALLBACK
+nsSystemTrayService::WindowProc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ if (numberOfCallsIntoWindowProc > 0)
+ // don't reenter this function ever or we could crash (if the popup
+ // frame is still being destroyed)
+ return FALSE;
+
+ AutoReentryBlocker blocker(&numberOfCallsIntoWindowProc);
+
+ bool handled = true;
+
+ PRUint32 message = 0;
+ PRUint32 mask = 0;
+ POINT mousePos;
+
+ PRUint16 button;
+ PRInt32 detail;
+ nsAutoString typeArg;
+
+ switch(uMsg) {
+ case WM_TRAYICON:
+ break;
+ case WM_CREATE:
+ return 0;
+ case WM_NCCREATE:
+ return true;
+ case WM_ACTIVATE:
+ if (LOWORD(wParam) == WA_INACTIVE)
+ {
+ // if we are activating the popup menu then it will hide itself after
+ // command selection, so we just ignore this
+ // I don't suppose that using the Window class name is the cleanest
+ // way to do this, but it's hopefully a temporary hack anyway until
+ // the issues with popups are solved
+ // (see https://bugzilla.mozilla.org/show_bug.cgi?id=279703) and I
+ // can't see a way to get at the HWND of the popup to remember it
+ char classname[256];
+ HWND hNewWnd = (HWND) lParam;
+ ::GetClassName(hNewWnd, classname, 256);
+ if (strcmp(classname, "MozillaDropShadowWindowClass") == 0)
+ return FALSE;
+
+ typeArg = NS_LITERAL_STRING("blur");
+ detail = -1;
+ break;
+ }
+ default:
+ handled = false;
+ }
+
+ // convert the Win32 event into a DOM event
+ // screaming to be encapsulated somewhere else (utility class?)
+ // only supporting click events for the time being
+
+ nsCOMPtr targetElement;
+ nsCOMPtr eventTarget;
+ if (handled)
+ {
+ targetElement = (nsIDOMElement *) GetProp(hwnd, S_PROPINST);
+ eventTarget = do_QueryInterface(targetElement);
+ }
+
+ if (!eventTarget)
+ handled = false;
+
+ nsAutoString syntheticEvent;
+
+ if (uMsg == WM_TRAYICON && handled) {
+ switch (lParam) {
+ case WM_LBUTTONDOWN:
+ button = 0;
+ detail = 1;
+ typeArg = NS_LITERAL_STRING("mousedown");
+ break;
+ case WM_RBUTTONDOWN:
+ button = 2;
+ detail = 1;
+ typeArg = NS_LITERAL_STRING("mousedown");
+ break;
+ case WM_MBUTTONDOWN:
+ button = 1;
+ detail = 1;
+ typeArg = NS_LITERAL_STRING("mousedown");
+ break;
+ case WM_LBUTTONUP:
+ button = 0;
+ detail = 1;
+ typeArg = NS_LITERAL_STRING("mouseup");
+ syntheticEvent = NS_LITERAL_STRING("click");
+ break;
+ case WM_RBUTTONUP:
+ button = 2;
+ detail = 1;
+ typeArg = NS_LITERAL_STRING("mouseup");
+ syntheticEvent = NS_LITERAL_STRING("click");
+ break;
+ case WM_MBUTTONUP:
+ button = 1;
+ detail = 1;
+ typeArg = NS_LITERAL_STRING("mouseup");
+ syntheticEvent = NS_LITERAL_STRING("click");
+ break;
+ case WM_CONTEXTMENU:
+ button = 2;
+ detail = 1;
+ typeArg = NS_LITERAL_STRING("contextmenu");
+ break;
+ case WM_LBUTTONDBLCLK:
+ button = 0;
+ detail = 2;
+ typeArg = NS_LITERAL_STRING("click");
+ break;
+ case WM_MBUTTONDBLCLK:
+ button = 1;
+ detail = 2;
+ typeArg = NS_LITERAL_STRING("click");
+ break;
+ case WM_RBUTTONDBLCLK:
+ button = 2;
+ detail = 2;
+ typeArg = NS_LITERAL_STRING("click");
+ break;
+ default:
+ handled = false;
+ break;
+ }
+ }
+
+ PRBool shiftArg = PR_FALSE;
+ PRBool ctrlArg = PR_FALSE;
+ PRBool altArg = PR_FALSE;
+
+ if (handled) {
+ GetCursorPos(&mousePos);
+ // check modifier key states
+ if (::GetKeyState(VK_CONTROL) & 0x8000)
+ ctrlArg = PR_TRUE;
+ if (::GetKeyState(VK_MENU) & 0x8000)
+ altArg = PR_TRUE;
+ if (::GetKeyState(VK_SHIFT) & 0x8000)
+ shiftArg = PR_TRUE;
+
+ // set the hidden window to foreground so the popup
+ // menu can go away when we lose focus
+ ::SetForegroundWindow(hwnd);
+
+ POINT clientPos;
+ clientPos.x = mousePos.x;
+ clientPos.y = mousePos.y;
+
+ nsresult rv;
+ nsCOMPtr element(do_QueryInterface(eventTarget, &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr document;
+ rv = element->GetOwnerDocument(getter_AddRefs(document));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr
+ documentEvent(do_QueryInterface(document, &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr
+ documentView(do_QueryInterface(document, &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr abstractView;
+ rv = documentView->GetDefaultView(getter_AddRefs(abstractView));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ PRBool ret = PR_TRUE;
+ nsCOMPtr event;
+ if (detail == -1)
+ // not a mouse event
+ rv = CreateEvent(documentEvent, typeArg, getter_AddRefs(event));
+ else
+ rv = CreateMouseEvent(documentEvent, typeArg, abstractView, detail,
+ mousePos.x, mousePos.y, clientPos.x, clientPos.y, ctrlArg, altArg,
+ shiftArg, PR_FALSE, button, getter_AddRefs(event));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = eventTarget->DispatchEvent(event, &ret);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (!syntheticEvent.IsEmpty())
+ {
+ rv = CreateMouseEvent(documentEvent, syntheticEvent, abstractView, detail,
+ mousePos.x, mousePos.y, clientPos.x, clientPos.y, ctrlArg, altArg,
+ shiftArg, PR_FALSE, button, getter_AddRefs(event));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = eventTarget->DispatchEvent(event, &ret);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+ if (!ret)
+ {
+ // handler called preventDefault, so we're done
+ PostMessage(hwnd, WM_NULL, 0, 0);
+ return FALSE;
+ }
+ }
+
+ return ::CallWindowProc(
+ DefWindowProc,
+ hwnd,
+ uMsg,
+ wParam,
+ lParam);
+}
+
+nsresult
+nsSystemTrayService::CreateEvent(nsIDOMDocumentEvent* documentEvent,
+ const nsAString& typeArg,
+ nsIDOMEvent** _retval)
+{
+ nsresult rv;
+ nsCOMPtr event;
+ rv = documentEvent->CreateEvent(NS_LITERAL_STRING("events"),
+ getter_AddRefs(event));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = event->InitEvent(typeArg, PR_FALSE, PR_TRUE);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ *_retval = event;
+ NS_ADDREF(*_retval);
+ return NS_OK;
+}
+
+nsresult
+nsSystemTrayService::CreateMouseEvent(nsIDOMDocumentEvent* documentEvent,
+ const nsAString& typeArg,
+ nsIDOMAbstractView* viewArg,
+ PRInt32 detailArg,
+ PRInt32 screenXArg, PRInt32 screenYArg,
+ PRInt32 clientXArg, PRInt32 clientYArg,
+ PRBool ctrlKeyArg, PRBool altKeyArg,
+ PRBool shiftKeyArg, PRBool metaKeyArg,
+ PRUint16 buttonArg,
+ nsIDOMEvent** _retval)
+{
+ nsresult rv;
+ nsCOMPtr event;
+ rv = documentEvent->CreateEvent(NS_LITERAL_STRING("mouseevent"), getter_AddRefs(event));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr mouseEvent(do_QueryInterface(event, &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = mouseEvent->InitMouseEvent(typeArg, PR_FALSE, PR_TRUE, viewArg,
+ detailArg, screenXArg, screenYArg, clientXArg, clientYArg, ctrlKeyArg, altKeyArg,
+ shiftKeyArg, metaKeyArg, buttonArg, nsnull);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return CallQueryInterface(mouseEvent, _retval);
+}
+
+nsresult
+nsSystemTrayService::GetDOMWindow(nsIXULWindow* xulWindow,
+ nsIDOMWindow** _retval)
+{
+ nsresult rv;
+ nsCOMPtr docShell;
+ rv = xulWindow->GetDocShell(getter_AddRefs(docShell));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr requestor(do_QueryInterface(docShell, &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = requestor->GetInterface(NS_GET_IID(nsIDOMWindow), (void **) _retval);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return NS_OK;
+}
+
+nsresult
+nsSystemTrayService::GetHwndForEvent(nsIDOMEvent* event, HWND& hwnd)
+{
+ nsresult rv;
+ nsCOMPtr eventTarget;
+
+ rv = event->GetCurrentTarget(getter_AddRefs(eventTarget));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr xulElement(do_QueryInterface(eventTarget, &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr domDocument;
+ rv = xulElement->GetOwnerDocument(getter_AddRefs(domDocument));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr document(do_QueryInterface(domDocument, &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr presShell = document->GetShellAt(0);
+ NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
+
+ nsIFrame* frame;
+ rv = presShell->GetEventTargetFrame(&frame);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (frame)
+ {
+ nsCOMPtr menuParent;
+ rv = frame->QueryInterface(NS_GET_IID(nsIMenuParent), getter_AddRefs(menuParent));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr widget;
+ rv = menuParent->GetWidget(getter_AddRefs(widget));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ hwnd = (HWND) widget->GetNativeData(NS_NATIVE_WINDOW);
+ return NS_OK;
+ }
+
+ return NS_ERROR_NOT_AVAILABLE;
+}
+
+nsresult
+nsSystemTrayService::HandleEvent(nsIDOMEvent* event)
+{
+ nsresult rv;
+ nsAutoString eventType;
+ rv = event->GetType(eventType);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (eventType == NS_LITERAL_STRING("popupshown"))
+ {
+ HWND hwnd;
+ rv = GetHwndForEvent(event, hwnd);
+ if (NS_SUCCEEDED(rv))
+ {
+ // install our own WindowProc to prevent WM_MOUSEACTIVATE from bringing
+ // the browser window to the foreground
+ WNDPROC oldProc = (WNDPROC) trayToolkit::pGetWindowLongPtr(hwnd,
+ GWLP_WNDPROC);
+ MK_ENSURE_NATIVE(::SetProp(hwnd, S_PROPPROC, (HANDLE) oldProc));
+ MK_ENSURE_NATIVE(trayToolkit::pSetWindowLongPtr(
+ hwnd,
+ GWLP_WNDPROC,
+ (LONG_PTR)PopupWindowProc
+ ));
+ }
+ }
+ else if (eventType == NS_LITERAL_STRING("popuphiding"))
+ {
+ // probably not necessary since the window is going away, but just in case
+ // lets put back the original WindowProc... because we can!
+ HWND hwnd;
+ rv = GetHwndForEvent(event, hwnd);
+ if (NS_SUCCEEDED(rv))
+ {
+ // Remove the special WindowProc
+ WNDPROC oldProc = (WNDPROC) ::GetProp(hwnd, S_PROPPROC);
+ MK_ENSURE_NATIVE(trayToolkit::pSetWindowLongPtr(
+ hwnd,
+ GWLP_WNDPROC,
+ (LONG_PTR)oldProc
+ ));
+ }
+ }
+
+ return NS_OK;
+}
+
+/* attribute imgIContainer image; */
+NS_IMETHODIMP
+nsSystemTrayService::GetImage(imgIContainer * *aImage)
+{
+ *aImage = mImage;
+ NS_IF_ADDREF(*aImage);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsSystemTrayService::SetImage(imgIContainer * aImage)
+{
+ mImage = aImage;
+ return NS_OK;
+}
+
+/* readonly attribute PRBool isMultiPartChannel; */
+NS_IMETHODIMP
+nsSystemTrayService::GetIsMultiPartChannel(PRBool *aIsMultiPartChannel)
+{
+ *aIsMultiPartChannel = PR_FALSE;
+ return NS_OK;
+}
+
+#ifndef MOZILLA_1_8_BRANCH
+/* void onStartRequest(in imgIRequest aRequest); */
+NS_IMETHODIMP
+nsSystemTrayService::OnStartRequest(imgIRequest* aRequest)
+{
+ return NS_OK;
+}
+#endif
+
+/* void onStartDecode (in imgIRequest aRequest); */
+NS_IMETHODIMP
+nsSystemTrayService::OnStartDecode(imgIRequest *aRequest)
+{
+ return NS_OK;
+}
+
+/* void onStartContainer (in imgIRequest aRequest,
+ in imgIContainer aContainer); */
+NS_IMETHODIMP
+nsSystemTrayService::OnStartContainer(imgIRequest *aRequest,
+ imgIContainer *aContainer)
+{
+ return NS_OK;
+}
+
+/* void onStartFrame (in imgIRequest aRequest, in gfxIImageFrame aFrame); */
+NS_IMETHODIMP
+nsSystemTrayService::OnStartFrame(imgIRequest *aRequest,
+ gfxIImageFrame *aFrame)
+{
+ return NS_OK;
+}
+
+/* [noscript] void onDataAvailable (in imgIRequest aRequest,
+ in gfxIImageFrame aFrame, [const] in nsIntRect aRect); */
+NS_IMETHODIMP
+nsSystemTrayService::OnDataAvailable(imgIRequest *aRequest,
+ gfxIImageFrame *aFrame,
+ const nsIntRect * aRect)
+{
+ return NS_OK;
+}
+
+/* void onStopFrame (in imgIRequest aRequest, in gfxIImageFrame aFrame); */
+NS_IMETHODIMP
+nsSystemTrayService::OnStopFrame(imgIRequest *aRequest,
+ gfxIImageFrame *aFrame)
+{
+ return NS_OK;
+}
+
+/* void onStopContainer (in imgIRequest aRequest,
+ in imgIContainer aContainer); */
+NS_IMETHODIMP
+nsSystemTrayService::OnStopContainer(imgIRequest *aRequest,
+ imgIContainer *aContainer)
+{
+ return NS_OK;
+}
+
+/* void onStopDecode (in imgIRequest aRequest, in nsresult status,
+ in wstring statusArg); */
+NS_IMETHODIMP
+nsSystemTrayService::OnStopDecode(imgIRequest *aRequest,
+ nsresult status, const PRUnichar *statusArg)
+{
+ return NS_OK;
+}
+
+#ifndef MOZILLA_1_8_BRANCH
+/* void onStopRequest(in imgIRequest aRequest, in boolean aIsLastPart); */
+NS_IMETHODIMP
+nsSystemTrayService::OnStopRequest(imgIRequest* aRequest,
+ PRBool aIsLastPart)
+{
+ return NS_OK;
+}
+#endif
+
+/* [noscript] void frameChanged (in imgIContainer aContainer,
+ in gfxIImageFrame aFrame, in nsIntRect aDirtyRect); */
+NS_IMETHODIMP
+nsSystemTrayService::FrameChanged(imgIContainer *aContainer,
+ gfxIImageFrame *aFrame,
+ nsIntRect * aDirtyRect)
+{
+ return NS_OK;
+}
+
+#ifdef MOZILLA_1_8_BRANCH
+nsresult
+nsSystemTrayService::ProcessImageData(PRInt32 width, PRInt32 height,
+ PRUint8 *rgbData, PRUint32 rgbStride,
+ PRUint32 rgbLen, PRUint8 *alphaData,
+ PRUint32 alphaStride, PRUint32 alphaBits,
+ HICON& outIcon)
+{
+ ICONINFO ii;
+ HBITMAP hColorBmp, hMaskBmp;
+ PRUint8 *colorBits, *maskBits, *rgbPixel, *alphaPixel;
+ PRInt32 x, y, ssx, ssy, dsx, dsy, dex, dey, w;
+ PRInt16 mask;
+ struct {
+ BITMAPINFOHEADER bmiHeader;
+ RGBQUAD bmiColors[2];
+ } bmi, bmi2;
+
+ memset(&bmi, 0, sizeof(bmi));
+ bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
+ bmi.bmiHeader.biWidth = ICON_WIDTH;
+ bmi.bmiHeader.biHeight = ICON_HEIGHT;
+ bmi.bmiHeader.biPlanes = 1;
+ bmi.bmiHeader.biCompression = BI_RGB;
+ bmi.bmiHeader.biBitCount = alphaBits < 8 ? 24 : 32;
+
+ hColorBmp = CreateDIBSection(nsnull, (BITMAPINFO*)&bmi, DIB_RGB_COLORS,
+ (void**)&colorBits, nsnull, 0);
+
+ if (!hColorBmp)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ memset(&bmi2, 0, sizeof(bmi2));
+ bmi2.bmiHeader.biSize = sizeof(bmi2.bmiHeader);
+ bmi2.bmiHeader.biWidth = ICON_WIDTH;
+ bmi2.bmiHeader.biHeight = ICON_HEIGHT;
+ bmi2.bmiHeader.biPlanes = 1;
+ bmi2.bmiHeader.biCompression = BI_RGB;
+ bmi2.bmiHeader.biBitCount = 1;
+ bmi2.bmiColors[1].rgbBlue = bmi2.bmiColors[1].rgbGreen =
+ bmi2.bmiColors[1].rgbRed = 255;
+ hMaskBmp = CreateDIBSection(nsnull, (BITMAPINFO*)&bmi2, DIB_RGB_COLORS,
+ (void**)&maskBits, nsnull, 0);
+
+ if (!hMaskBmp) {
+ DeleteObject(hColorBmp);
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ if (width > ICON_WIDTH) {
+ dsx = 0; dex = ICON_WIDTH;
+ ssx = (width - ICON_WIDTH)/2;
+ } else {
+ dsx = (ICON_WIDTH - width)/2; dex = dsx + width;
+ ssx = 0;
+ }
+ if (height > ICON_HEIGHT) {
+ dsy = 0; dey = ICON_HEIGHT;
+ ssy = (height - ICON_HEIGHT)/2;
+ } else {
+ dsy = (ICON_HEIGHT - height)/2; dey = dsy + height;
+ ssy = 0;
+ }
+
+ w = dex - dsx;
+
+ rgbPixel = rgbData + rgbStride*ssy + ssx*3;
+
+ if (alphaBits == 8) {
+ colorBits += (ICON_WIDTH*dsy + dsx)*4;
+ alphaPixel = alphaData + alphaStride*ssy + ssx;
+ for (y = dsy; y < dey; ++y) {
+ for (x = dsx; x < dex; ++x) {
+ colorBits[0] = rgbPixel[0];
+ colorBits[1] = rgbPixel[1];
+ colorBits[2] = rgbPixel[2];
+ colorBits[3] = alphaPixel[0];
+ rgbPixel+=3;
+ alphaPixel++;
+ colorBits+=4;
+ }
+ rgbPixel += rgbStride - w*3;
+ alphaPixel += alphaStride - w;
+ colorBits += ICON_WIDTH*4 - w*4;
+ }
+ } else {
+ colorBits += (ICON_WIDTH*dsy + dsx)*3;
+ for (y = dsy; y < dey; ++y) {
+ memcpy(colorBits, rgbPixel, w*3);
+ colorBits += ICON_WIDTH*3;
+ rgbPixel += rgbStride;
+ }
+ if (alphaBits == 1) {
+ memset(maskBits, 0xff, ICON_WIDTH*ICON_HEIGHT/8*2);
+ w = ssx-dsx;
+ alphaPixel = alphaData + alphaStride*ssy + w/8;
+ w = 8-(w&7);
+ for (y = dsy; y < dey; ++y) {
+ mask = alphaPixel[0];
+ for (x = dsx/8; x < (dex+7)/8; ++x) {
+ mask = mask << 8;
+ mask |= alphaPixel[x+1-dsx/8];
+
+ maskBits[x] = (~(mask>>w)) & 0xff;
+ }
+ // Why windows requires needs to multiply that by two?
+ maskBits += ICON_WIDTH/8 * 2;
+ alphaPixel += alphaStride;
+ }
+ }
+ }
+ GdiFlush();
+
+ ii.fIcon = TRUE;
+ ii.hbmMask = hMaskBmp;
+ ii.hbmColor = hColorBmp;
+
+ outIcon = CreateIconIndirect(&ii);
+ DeleteObject(hColorBmp);
+ DeleteObject(hMaskBmp);
+
+ if (!outIcon)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ return NS_OK;
+}
+#endif /* MOZILLA_1_8_BRANCH */
Index: toolkit/components/systray/src/nsSystemTrayServiceWin.h
===================================================================
RCS file: /cvsroot/mozilla/toolkit/components/systray/src/nsSystemTrayServiceWin.h,v
--- toolkit/components/systray/src/nsSystemTrayServiceWin.h 1969-12-31 16:00:00.000000000 -0800
+++ toolkit/components/systray/src/nsSystemTrayServiceWin.h 2007-05-13 01:34:48.000000000 -0700
@@ -0,0 +1,151 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is MinimizeToTray.
+ *
+ * The Initial Developer of the Original Code are
+ * Mark Yen and Brad Peterson.
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Yen , Original author
+ * Brad Peterson , Original author
+ * Daniel Glazman
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef ULONG_PTR
+#define ULONG_PTR DWORD
+#endif
+
+#ifndef nsSystemTrayService_h__
+#define nsSystemTrayService_h__
+
+// needed for QueueUserAPC
+#ifdef _WIN32_WINNT
+#undef _WIN32_WINNT
+#endif
+#define _WIN32_WINNT 0x0400
+
+#include
+#include
+
+#include "nsISystemTrayService.h"
+#include "imgIDecoderObserver.h"
+#include "imgILoad.h"
+#include "nsIDOMEventListener.h"
+#include "nsCOMPtr.h"
+#include "nsDataHashtable.h"
+
+class nsIDOMWindow;
+class nsIURI;
+class nsIXULWindow;
+
+// {F53FCEFA-2F53-40cf-BBAF-2F5896A56E82}
+#define NS_SYSTEMTRAYSERVICE_CID \
+ { 0xf53fcefa, 0x2f53, 0x40cf, \
+ { 0xbb, 0xaf, 0x2f, 0x58, 0x96, 0xa5, 0x6e, 0x82 } }
+
+#define NS_SYSTEMTRAYSERVICE_CONTRACTID \
+ "@mozilla.org/system-tray-service;1"
+
+#define NS_SYSTEMTRAYSERVICE_CLASSNAME "System Tray Service"
+
+class nsIDOMAbstractView;
+class nsIDOMDocumentEvent;
+class nsIDOMElement;
+class nsIDOMEvent;
+class nsIDOMEventTarget;
+class nsIURI;
+
+class nsSystemTrayService : public nsISystemTrayService,
+ public nsIDOMEventListener, public imgILoad, public imgIDecoderObserver
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISYSTEMTRAYSERVICE
+ NS_DECL_NSIDOMEVENTLISTENER
+ NS_DECL_IMGICONTAINEROBSERVER
+ NS_DECL_IMGIDECODEROBSERVER
+ NS_DECL_IMGILOAD
+
+ nsSystemTrayService();
+
+ nsresult Init();
+
+private:
+ ~nsSystemTrayService();
+
+protected:
+ nsresult AddTrayIcon(HWND hwnd, nsIURI* iconURI, const nsAString& iconId,
+ nsIDOMElement* targetElement);
+ nsresult GetIconForWnd(HWND hwnd, HICON& result);
+ nsresult GetIconForURI(nsIURI* iconURI, HICON& result);
+ nsresult CreateListenerWindow(HWND* listenerWindow,
+ nsIDOMElement* targetElement);
+ nsresult GetDOMWindow(nsIXULWindow* xulWindow, nsIDOMWindow** _retval);
+ nsresult GetHwndForEvent(nsIDOMEvent* event, HWND& hwnd);
+
+ static nsresult CreateEvent(nsIDOMDocumentEvent* documentEvent,
+ const nsAString& typeArg, nsIDOMEvent** _retval);
+ static nsresult CreateMouseEvent(nsIDOMDocumentEvent* documentEvent,
+ const nsAString& typeArg, nsIDOMAbstractView* viewArg, PRInt32 detailArg,
+ PRInt32 screenXArg, PRInt32 screenYArg, PRInt32 clientXArg,
+ PRInt32 clientYArg, PRBool ctrlKeyArg, PRBool altKeyArg,
+ PRBool shiftKeyArg, PRBool metkeyArg, PRUint16 buttonArg,
+ nsIDOMEvent** _retval);
+
+#ifdef MOZILLA_1_8_BRANCH
+ nsresult ProcessImageData(PRInt32 width, PRInt32 height,
+ PRUint8 *rgbData, PRUint32 rgbStride,
+ PRUint32 rgbLen, PRUint8 *alphaData,
+ PRUint32 alphaStride, PRUint32 alphaBits, HICON& outIcon);
+#endif
+
+ static LRESULT CALLBACK WindowProc(
+ HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam
+ );
+ static LRESULT CALLBACK PopupWindowProc(
+ HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam
+ );
+
+ /* additional members */
+ static ATOM s_wndClass;
+ nsDataHashtable mIconDataMap;
+ nsCOMPtr mImage;
+
+ /* window property constants */
+ static const TCHAR* S_PROPINST;
+ static const TCHAR* S_PROPPROC;
+};
+
+#endif // nsSystemTrayService_h__
Index: toolkit/components/systray/src/nsWindowUtilWin.cpp
===================================================================
RCS file: /cvsroot/mozilla/toolkit/components/systray/src/nsWindowUtilWin.cpp,v
--- toolkit/components/systray/src/nsWindowUtilWin.cpp 1969-12-31 16:00:00.000000000 -0800
+++ toolkit/components/systray/src/nsWindowUtilWin.cpp 2007-05-13 01:34:48.000000000 -0700
@@ -0,0 +1,359 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is MinimizeToTray.
+ *
+ * The Initial Developer of the Original Code are
+ * Mark Yen and Brad Peterson.
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Yen , Original author
+ * Brad Peterson , Original author
+ * Daniel Glazman
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsWindowUtilWin.h"
+#include "nsString.h"
+#include "nsIBaseWindow.h"
+#include "nsIDocShell.h"
+#include "nsIDocShellTreeItem.h"
+#include "nsIDocShellTreeOwner.h"
+#include "nsIDOMAbstractView.h"
+#include "nsIDOMDocument.h"
+#include "nsIDOMDocumentEvent.h"
+#include "nsIDOMDocumentView.h"
+#include "nsIDOMEventTarget.h"
+#include "nsIDOMMouseEvent.h"
+#include "nsIDOMWindow.h"
+#include "nsIInterfaceRequestor.h"
+#include "nsIWebNavigation.h"
+#include "nsIXULWindow.h"
+#include "trayToolkitWin.h"
+
+#define S_PROPINST TEXT("_NS_WINDOWUTIL_INST")
+#define S_PROPPROC TEXT("_NS_WINDOWUTIL_PROC")
+
+#define MK_ENSURE_NATIVE(res) \
+ PR_BEGIN_MACRO \
+ NS_ENSURE_TRUE(0 != res || 0 == ::GetLastError(), \
+ ::GetLastError() + MK_ERROR_OFFSET); \
+ PR_END_MACRO
+
+#define MK_ERROR_OFFSET (0xD0000000 + (__LINE__ * 0x10000))
+
+NS_IMPL_ISUPPORTS1(nsWindowUtil, nsIWindowUtil)
+
+nsWindowUtil::nsWindowUtil()
+{
+ mOldProc = NULL;
+}
+
+nsWindowUtil::~nsWindowUtil()
+{
+ if (mOldProc)
+ {
+ ::RemoveProp(this->mWnd, S_PROPINST);
+ ::SetProp(this->mWnd, S_PROPPROC, (HANDLE)this->mOldProc);
+ }
+}
+
+/* void init (in nsIDOMWindow win); */
+NS_IMETHODIMP
+nsWindowUtil::Init(nsIDOMWindow *win)
+{
+ nsresult rv;
+ mDOMWindow = win;
+
+ nsCOMPtr docShell;
+ rv = GetDocShell(getter_AddRefs(docShell));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr baseWindow(do_QueryInterface(docShell, &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nativeWindow theNativeWindow;
+ rv = baseWindow->GetParentNativeWindow( &theNativeWindow );
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ mWnd = NS_REINTERPRET_CAST(HWND, theNativeWindow);
+ NS_ENSURE_TRUE(mWnd, NS_ERROR_UNEXPECTED);
+
+ return NS_OK;
+}
+
+/* readonly attribute nsIXULWindow xulWindow */
+NS_IMETHODIMP
+nsWindowUtil::GetXulWindow(nsIXULWindow **_retval)
+{
+ NS_ENSURE_STATE(mDOMWindow);
+
+ nsresult rv;
+ nsCOMPtr
+ requestor(do_QueryInterface(mDOMWindow, &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr nav;
+ rv = requestor->GetInterface(NS_GET_IID(nsIWebNavigation),
+ getter_AddRefs(nav));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr treeItem(do_QueryInterface(nav, &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr treeOwner;
+ rv = treeItem->GetTreeOwner(getter_AddRefs(treeOwner));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ requestor = do_QueryInterface(treeOwner, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return requestor->GetInterface(NS_GET_IID(nsIXULWindow), (void **) _retval);
+}
+
+/* readonly attribute nsIDocShell docShell */
+NS_IMETHODIMP
+nsWindowUtil::GetDocShell(nsIDocShell **_retval)
+{
+ nsresult rv;
+ nsCOMPtr xulWindow;
+ rv = GetXulWindow(getter_AddRefs(xulWindow));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return xulWindow->GetDocShell(_retval);
+}
+
+/* void minimize(); */
+NS_IMETHODIMP
+nsWindowUtil::Minimize()
+{
+ ::ShowWindow(mWnd, SW_MINIMIZE);
+ return NS_OK;
+}
+
+/* readonly attribute boolean hidden; */
+NS_IMETHODIMP
+nsWindowUtil::GetHidden(PRBool* _retval)
+{
+ NS_ENSURE_STATE(mWnd);
+
+ if (::IsWindowVisible(mWnd))
+ *_retval = PR_FALSE;
+ else
+ *_retval = PR_TRUE;
+
+ return NS_OK;
+}
+
+/* void watch() */
+NS_IMETHODIMP
+nsWindowUtil::Watch()
+{
+ NS_ENSURE_STATE(mWnd);
+
+ // subclass the window (need to intercept WM_TRAYICON)
+ ::SetLastError(0);
+
+ if (::GetProp(mWnd, S_PROPINST))
+ return NS_ERROR_ALREADY_INITIALIZED;
+ MK_ENSURE_NATIVE(::SetProp(mWnd, S_PROPINST, (HANDLE)this));
+ mOldProc = (WNDPROC)trayToolkit::pGetWindowLongPtr(mWnd, GWLP_WNDPROC);
+ ::SetLastError(0);
+ MK_ENSURE_NATIVE(trayToolkit::pSetWindowLongPtr(
+ mWnd,
+ GWLP_WNDPROC,
+ (LONG_PTR)nsWindowUtil::WindowProc
+ ));
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWindowUtil::Unwatch()
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+LRESULT CALLBACK
+nsWindowUtil::WindowProc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ bool handled = true;
+ WNDPROC proc;
+ nsWindowUtil* self =
+ (nsWindowUtil*)GetProp(hwnd, S_PROPINST);
+
+ if (self && self->mOldProc && self->mDOMWindow) {
+ proc = self->mOldProc;
+ } else {
+ // property not found - we don't exist anymore
+ // use the original window proc
+ proc = (WNDPROC)GetProp(hwnd, S_PROPPROC);
+ if (!proc)
+ // can't find the right process... skip over to the default
+ // (this will, at the minimum, totally break the app)
+ proc = DefWindowProc;
+ handled = false;
+ }
+
+ /*
+ * For this next section, including all the switches, we are simply
+ * collecting messages we feel are important to collect. Once we collect
+ * all the windows messages that may be important to us, then these messages
+ * are dispatched as DOM events to the window.
+ */
+
+ nsAutoString typeArg;
+
+ POINT clientPos = { 0, 0};
+ POINT screenPos = { 0, 0};
+
+ if (handled) {
+ switch (uMsg) {
+ case WM_NCLBUTTONDOWN:
+ switch(wParam) {
+ // these are the min, max, and close buttons for
+ case HTMINBUTTON:
+ typeArg = NS_LITERAL_STRING("minimizing");
+ break;
+ case HTMAXBUTTON:
+ typeArg = NS_LITERAL_STRING("maximizing");
+ break;
+ case HTCLOSE:
+ typeArg = NS_LITERAL_STRING("closing");
+ break;
+ default:
+ handled = false;
+ }
+ clientPos.x = screenPos.x = LOWORD(lParam);
+ clientPos.y = screenPos.y = LOWORD(lParam);
+ ::ClientToScreen(hwnd, &screenPos);
+ break;
+ case WM_ACTIVATE:
+ switch (LOWORD(wParam)) {
+ case WA_ACTIVE:
+ case WA_CLICKACTIVE:
+ // window is being activated
+ typeArg = NS_LITERAL_STRING("activating");
+ break;
+ default:
+ handled = false;
+ }
+ break;
+ case WM_SIZE:
+ switch (wParam) {
+ case SIZE_MINIMIZED:
+ typeArg = NS_LITERAL_STRING("minimizing");
+ break;
+ default:
+ // for some reason this message is received with wParam ==
+ // SIZE_MAXIMIZED when the browser is shutting down, and calling
+ // Restore() results in the maximized window being "restored"
+ // (returned to non-maximized) size. This size is preserved
+ // after restarting, which is annoying, so I'm commenting it out
+ // until someone can prove that this is actually useful.
+ //
+ // we're resizing, but not minimized, so some part must be visible
+ //typeArg = NS_LITERAL_STRING("activating");
+ break;
+ }
+ break;
+ case WM_SYSCOMMAND:
+ switch (wParam) {
+ case SC_CLOSE:
+ //The user has clicked on the top left window icon and selected close...
+ //Or the user typed Alt+F4.
+ typeArg = NS_LITERAL_STRING("closing");
+ break;
+ default:
+ handled = false;
+ }
+ break;
+ default:
+ handled = false;
+ break;
+ }
+ }
+
+ PRBool ctrlArg = PR_FALSE;
+ PRBool altArg = PR_FALSE;
+ PRBool shiftArg = PR_FALSE;
+
+ if (handled) {
+ // check modifier key states
+ if (::GetKeyState(VK_CONTROL) & 0x8000)
+ ctrlArg = PR_TRUE;
+ if (::GetKeyState(VK_MENU) & 0x8000)
+ altArg = PR_TRUE;
+ if (::GetKeyState(VK_SHIFT) & 0x8000)
+ shiftArg = PR_TRUE;
+
+ // dispatch the event
+ PRBool ret = TRUE;
+ nsresult rv;
+
+ nsCOMPtr eventTarget(do_QueryInterface(self->mDOMWindow, &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr document;
+ rv = self->mDOMWindow->GetDocument(getter_AddRefs(document));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr documentEvent(do_QueryInterface(document, &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr documentView(do_QueryInterface(document, &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr abstractView;
+ rv = documentView->GetDefaultView(getter_AddRefs(abstractView));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr event;
+ rv = documentEvent->CreateEvent(NS_LITERAL_STRING("mouseevent"), getter_AddRefs(event));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr mouseEvent(do_QueryInterface(event, &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = mouseEvent->InitMouseEvent(typeArg, PR_TRUE, PR_TRUE, abstractView,
+ 1, screenPos.x, screenPos.y, clientPos.x, clientPos.y, ctrlArg, altArg,
+ shiftArg, PR_FALSE, 0, nsnull);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = eventTarget->DispatchEvent(mouseEvent, &ret);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (!ret)
+ // event was hooked
+ return FALSE;
+ }
+
+ return CallWindowProc(proc, hwnd, uMsg, wParam, lParam);
+}
Index: toolkit/components/systray/src/nsWindowUtilWin.h
===================================================================
RCS file: /cvsroot/mozilla/toolkit/components/systray/src/nsWindowUtilWin.h,v
--- toolkit/components/systray/src/nsWindowUtilWin.h 1969-12-31 16:00:00.000000000 -0800
+++ toolkit/components/systray/src/nsWindowUtilWin.h 2007-05-13 01:34:48.000000000 -0700
@@ -0,0 +1,77 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is MinimizeToTray.
+ *
+ * The Initial Developer of the Original Code are
+ * Mark Yen and Brad Peterson.
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Yen , Original author
+ * Brad Peterson , Original author
+ * Daniel Glazman
+ * Matthew Gertner
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsIWindowUtil_h__
+#define nsIWindowUtil_h__
+
+#include
+
+#include "nsIWindowUtil.h"
+#include "nsCOMPtr.h"
+
+// {2657AFF1-65D6-4913-A561-8FC1859348BF}
+#define NS_WINDOWUTIL_CID \
+ { 0x2657aff1, 0x65d6, 0x4913, \
+ { 0xa5, 0x61, 0x8f, 0xc1, 0x85, 0x93, 0x48, 0xbf } }
+
+#define NS_WINDOWUTIL_CONTRACTID "@mozilla.org/window-util;1"
+#define NS_WINDOWUTIL_CLASSNAME "Window Util"
+
+class nsWindowUtil : public nsIWindowUtil
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIWINDOWUTIL
+
+ nsWindowUtil();
+
+private:
+ ~nsWindowUtil();
+
+protected:
+ static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
+ LPARAM lParam);
+
+ nsCOMPtr mDOMWindow;
+ HWND mWnd;
+ WNDPROC mOldProc;
+};
+
+#endif // nsIWindowUtil_h__
Index: toolkit/components/systray/src/trayModule.cpp
===================================================================
RCS file: /cvsroot/mozilla/toolkit/components/systray/src/trayModule.cpp,v
--- toolkit/components/systray/src/trayModule.cpp 1969-12-31 16:00:00.000000000 -0800
+++ toolkit/components/systray/src/trayModule.cpp 2007-05-13 01:34:48.000000000 -0700
@@ -0,0 +1,78 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is MinimizeToTray.
+ *
+ * The Initial Developer of the Original Code are
+ * Mark Yen and Brad Peterson.
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Yen , Original author
+ * Brad Peterson , Original author
+ * Daniel Glazman
+ * Matthew Gertner
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsICategoryManager.h"
+#include "nsIGenericFactory.h"
+#include "nsServiceManagerUtils.h"
+
+#if XP_WIN
+#include "nsSystemTrayServiceWin.h"
+#include "nsWindowUtilWin.h"
+#elif MOZ_WIDGET_GTK2
+#include "nsSystemTrayServiceGTK.h"
+#else
+#include "nsSystemTrayService.h"
+#endif
+
+#ifdef XP_WIN
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsWindowUtil)
+#endif
+
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsSystemTrayService)
+
+static nsModuleComponentInfo components[] =
+{
+#ifdef XP_WIN
+ {
+ NS_WINDOWUTIL_CLASSNAME,
+ NS_WINDOWUTIL_CID,
+ NS_WINDOWUTIL_CONTRACTID,
+ nsWindowUtilConstructor
+ },
+#endif
+ {
+ NS_SYSTEMTRAYSERVICE_CLASSNAME,
+ NS_SYSTEMTRAYSERVICE_CID,
+ NS_SYSTEMTRAYSERVICE_CONTRACTID,
+ nsSystemTrayServiceConstructor
+ }
+};
+
+NS_IMPL_NSGETMODULE(systrayModule, components)
Index: toolkit/components/systray/src/trayToolkitWin.cpp
===================================================================
RCS file: /cvsroot/mozilla/toolkit/components/systray/src/trayToolkitWin.cpp,v
--- toolkit/components/systray/src/trayToolkitWin.cpp 1969-12-31 16:00:00.000000000 -0800
+++ toolkit/components/systray/src/trayToolkitWin.cpp 2007-05-13 01:34:48.000000000 -0700
@@ -0,0 +1,164 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is MinimizeToTray.
+ *
+ * The Initial Developer of the Original Code are
+ * Mark Yen and Brad Peterson.
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Yen , Original author
+ * Brad Peterson , Original author
+ * Daniel Glazman
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "trayToolkitWin.h"
+
+// these two are copied from /mozilla/widget/src/windows/nsToolkit.cpp
+int ConvertAtoW(LPCSTR aStrInA, int aBufferSize, LPWSTR aStrOutW)
+{
+ return MultiByteToWideChar(CP_ACP, 0, aStrInA, -1, aStrOutW, aBufferSize);
+}
+
+int ConvertWtoA(LPCWSTR aStrInW, int aBufferSizeOut, LPSTR aStrOutA)
+{
+ if ((!aStrInW) || (!aStrOutA) || (aBufferSizeOut <= 0))
+ return 0;
+
+ int numCharsConverted = WideCharToMultiByte(CP_ACP, 0, aStrInW, -1,
+ aStrOutA, aBufferSizeOut, "?", NULL);
+
+ if (!numCharsConverted) {
+ if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
+ // Overflow, add missing null termination but return 0
+ aStrOutA[aBufferSizeOut-1] = '\0';
+ }
+ else {
+ // Other error, clear string and return 0
+ aStrOutA[0] = '\0';
+ }
+ }
+ else if (numCharsConverted < aBufferSizeOut) {
+ // Add 2nd null (really necessary?)
+ aStrOutA[numCharsConverted] = '\0';
+ }
+
+ return numCharsConverted;
+}
+
+PRBool trayToolkit::m_isInitialized = PR_FALSE;
+PRBool trayToolkit::m_isNT = PR_FALSE;
+
+TT_GetWindowLongPtr trayToolkit::pGetWindowLongPtr = ::GetWindowLongPtrA;
+TT_SetWindowLongPtr trayToolkit::pSetWindowLongPtr = ::SetWindowLongPtrA;
+TT_GetWindowText trayToolkit::pGetWindowText = trayToolkit::GetWindowTextA;
+TT_Shell_NotifyIcon trayToolkit::pShell_NotifyIcon = trayToolkit::Shell_NotifyIconA;
+
+void trayToolkit::Init()
+{
+ if (trayToolkit::m_isInitialized)
+ return;
+ trayToolkit::m_isInitialized = PR_TRUE;
+
+ OSVERSIONINFOEX osversion;
+ BOOL osVersionInfoEx;
+
+ ::ZeroMemory(&osversion, sizeof(OSVERSIONINFOEX));
+ osversion.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+
+ if (!(osVersionInfoEx = GetVersionEx((OSVERSIONINFO *)&osversion))) {
+ // if OSVERSIONINFOEX doesn't work, try OSVERSIONINFO.
+ osversion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ if (!GetVersionEx((OSVERSIONINFO *)&osversion)) {
+ // maybe we are running on very old Windows OS. Assign FALSE.
+ }
+ }
+
+ trayToolkit::m_isNT = (osversion.dwPlatformId == VER_PLATFORM_WIN32_NT);
+ if (trayToolkit::m_isNT) {
+ trayToolkit::pGetWindowLongPtr = GetWindowLongPtrW;
+ trayToolkit::pSetWindowLongPtr = SetWindowLongPtrW;
+ trayToolkit::pGetWindowText = GetWindowTextW;
+ trayToolkit::pShell_NotifyIcon = Shell_NotifyIconW;
+ }
+}
+
+int WINAPI trayToolkit::GetWindowTextA(HWND hWnd, LPWSTR lpString, int nMaxCount) {
+ LPSTR buffer = new CHAR[nMaxCount + 1];
+ buffer[nMaxCount] = 0;
+ lpString[0] = 0;
+ int rv = ::GetWindowTextA(hWnd, buffer, nMaxCount);
+ if (rv) {
+ // the call to ::GetWindowTextA succeeded
+ rv = ConvertAtoW(buffer, nMaxCount, lpString);
+ }
+ delete[] buffer;
+ return rv;
+}
+
+BOOL WINAPI trayToolkit::Shell_NotifyIconA(DWORD dwMessage, PNOTIFYICONDATAW lpdata) {
+ NOTIFYICONDATAA data;
+ int version = 0;
+
+ // try to figure out which version of NOTIFYICONDATA the client is using
+ if (NOTIFYICONDATAW_V1_SIZE == lpdata->cbSize) {
+ data.cbSize = NOTIFYICONDATAA_V1_SIZE;
+ version = 1;
+ } else if (NOTIFYICONDATAW_V2_SIZE == lpdata->cbSize) {
+ data.cbSize = NOTIFYICONDATAA_V2_SIZE;
+ version = 2;
+ } else if (sizeof(NOTIFYICONDATAW) == lpdata->cbSize) {
+ data.cbSize = sizeof(NOTIFYICONDATAA);
+ version = 3;
+ } else {
+ ::SetLastError(E_NOTIMPL);
+ return FALSE;
+ }
+
+ // now copy the data over (note that everything falls through)
+ switch(version) {
+#if _MSC_VER >= 1300
+ case 3:
+ data.guidItem = lpdata->guidItem;
+ case 2:
+ data.dwState = lpdata->dwState;
+ data.dwStateMask = lpdata->dwStateMask;
+ ConvertWtoA(lpdata->szInfoTitle, sizeof(data.szInfoTitle), data.szInfoTitle);
+ data.dwInfoFlags = lpdata->dwInfoFlags;
+#endif
+ case 1:
+ data.hWnd = lpdata->hWnd;
+ data.uID = lpdata->uID;
+ data.uFlags = lpdata->uFlags;
+ data.uCallbackMessage = lpdata->uCallbackMessage;
+ data.hIcon = lpdata->hIcon;
+ ConvertWtoA(lpdata->szTip, sizeof(data.szTip), data.szTip);
+ }
+
+ return ::Shell_NotifyIconA(dwMessage, &data);
+}
\ No newline at end of file
Index: toolkit/components/systray/src/trayToolkitWin.h
===================================================================
RCS file: /cvsroot/mozilla/toolkit/components/systray/src/trayToolkitWin.h,v
--- toolkit/components/systray/src/trayToolkitWin.h 1969-12-31 16:00:00.000000000 -0800
+++ toolkit/components/systray/src/trayToolkitWin.h 2007-05-13 01:34:48.000000000 -0700
@@ -0,0 +1,95 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is MinimizeToTray.
+ *
+ * The Initial Developer of the Original Code are
+ * Mark Yen and Brad Peterson.
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Yen , Original author
+ * Brad Peterson , Original author
+ * Daniel Glazman
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef trayToolkit_h__
+#define trayToolkit_h__
+
+#include "nspr.h"
+
+#ifdef _WIN32_IE
+#undef _WIN32_IE
+#endif
+#define _WIN32_IE 0x0600
+#include
+#include
+
+/*
+ * A small duplication of the code from nsToolkit.h
+ * So we can work on Win9x (ANSI) and WinNT (Unicode)
+ * Unfortunately, nsToolkit is too deep in Mozilla for us to use
+ */
+
+#if _MSC_VER < 1300
+#define LONG_PTR LONG
+#define GWLP_WNDPROC GWL_WNDPROC
+#define GCLP_HICONSM GCL_HICONSM
+#define GetClassLongPtr GetClassLong
+#define GetWindowLongPtrA GetWindowLongA
+#define SetWindowLongPtrA SetWindowLongA
+#define GetWindowLongPtrW GetWindowLongW
+#define SetWindowLongPtrW SetWindowLongW
+#define NOTIFYICONDATAA_V1_SIZE sizeof(NOTIFYICONDATAA)
+#define NOTIFYICONDATAA_V2_SIZE (-1)
+#define NOTIFYICONDATAW_V1_SIZE sizeof(NOTIFYICONDATAW)
+#define NOTIFYICONDATAW_V2_SIZE (-1)
+#endif
+
+typedef LONG_PTR (WINAPI *TT_GetWindowLongPtr)(HWND, int);
+typedef LONG_PTR (WINAPI *TT_SetWindowLongPtr)(HWND, int, LONG_PTR);
+typedef int (WINAPI *TT_GetWindowText) (HWND, LPWSTR, int);
+typedef BOOL (WINAPI *TT_Shell_NotifyIcon)(DWORD, PNOTIFYICONDATAW);
+
+class trayToolkit {
+public:
+ static void Init();
+
+ static PRBool m_isInitialized;
+ static PRBool m_isNT;
+
+ static TT_GetWindowLongPtr pGetWindowLongPtr;
+ static TT_SetWindowLongPtr pSetWindowLongPtr;
+ static TT_GetWindowText pGetWindowText;
+ static TT_Shell_NotifyIcon pShell_NotifyIcon;
+
+ static int WINAPI GetWindowTextA(HWND, LPWSTR, int);
+ static BOOL WINAPI Shell_NotifyIconA(DWORD, PNOTIFYICONDATAW);
+
+};
+
+#endif // trayToolkit_h__
\ No newline at end of file
Index: widget/src/build/nsWinWidgetFactory.cpp
===================================================================
RCS file: /cvsroot/mozilla/widget/src/build/nsWinWidgetFactory.cpp,v
--- widget/src/build/nsWinWidgetFactory.cpp 2007-05-13 01:34:48.000000000 -0700 1.76
+++ widget/src/build/nsWinWidgetFactory.cpp 2007-05-13 01:34:48.000000000 -0700
@@ -46,16 +46,17 @@
#include "nsLookAndFeel.h"
#include "nsToolkit.h"
#include "nsWindow.h"
#include "nsAppShell.h"
#include "nsAppShellSingleton.h"
#include "nsIServiceManager.h"
#include "nsSound.h"
#include "nsIdleServiceWin.h"
+#include "nsImageToBitmap.h"
#include "nsBidiKeyboard.h"
// Drag & Drop, Clipboard
#include "nsClipboard.h"
#include "nsClipboardHelper.h"
#include "nsTransferable.h"
#include "nsHTMLFormatConverter.h"
@@ -70,16 +71,17 @@
#include "nsPrintSession.h"
NS_GENERIC_FACTORY_CONSTRUCTOR(nsWindow)
NS_GENERIC_FACTORY_CONSTRUCTOR(ChildWindow)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboard)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboardHelper)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsNativeThemeWin)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsFilePicker)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsImageToBitmap)
#ifndef WINCE
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSound)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsDragService)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsBidiKeyboard)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsIdleServiceWin)
#endif
@@ -112,16 +114,20 @@ static const nsModuleComponentInfo compo
{ "Clipboard Helper",
NS_CLIPBOARDHELPER_CID,
"@mozilla.org/widget/clipboardhelper;1",
nsClipboardHelperConstructor },
{ "File Picker",
NS_FILEPICKER_CID,
"@mozilla.org/filepicker;1",
nsFilePickerConstructor },
+ { "Image to Bitmap Converter",
+ NS_IMAGE_TO_BITMAP_CID,
+ "@mozilla.org/widget/image-to-win-bitmap;1",
+ nsImageToBitmapConstructor },
#ifndef WINCE
{ "Sound",
NS_SOUND_CID,
"@mozilla.org/sound;1",
nsSoundConstructor },
{ "Drag Service",
NS_DRAGSERVICE_CID,
"@mozilla.org/widget/dragservice;1",
Index: widget/src/windows/Makefile.in
===================================================================
RCS file: /cvsroot/mozilla/widget/src/windows/Makefile.in,v
--- widget/src/windows/Makefile.in 2007-05-13 01:34:48.000000000 -0700 3.48
+++ widget/src/windows/Makefile.in 2007-05-13 01:34:48.000000000 -0700
@@ -88,16 +88,17 @@ CPPSRCS = \
nsClipboard.cpp \
nsNativeThemeWin.cpp \
nsFilePicker.cpp \
nsScreenWin.cpp \
nsScreenManagerWin.cpp \
nsPrintOptionsWin.cpp \
nsPrintSettingsWin.cpp \
nsDeviceContextSpecWin.cpp \
+ nsImageToBitmap.cpp \
$(NULL)
ifneq ($(OS_ARCH), WINCE)
CPPSRCS += \
nsNativeDragTarget.cpp \
nsNativeDragSource.cpp \
nsDragService.cpp \
nsImageClipboard.cpp \
@@ -110,17 +111,19 @@ endif
DEFINES += -D_IMPL_NS_WIDGET -DMOZ_UNICODE
ifdef BUILD_STATIC_LIBS
DEFINES += -DMOZ_STATIC_COMPONENT_LIBS
endif # BUILD_STATIC_LIBS
-EXPORTS = nsdefs.h
+EXPORTS = nsdefs.h \
+ nsIImageToBitmap.h \
+ $(NULL)
LOCAL_INCLUDES = \
-I. \
-I$(srcdir)/../xpwidgets \
-I$(srcdir) \
$(NULL)
FORCE_STATIC_LIB = 1
Index: widget/src/windows/nsIImageToBitmap.h
===================================================================
RCS file: /cvsroot/mozilla/widget/src/windows/nsIImageToBitmap.h,v
--- widget/src/windows/nsIImageToBitmap.h 1969-12-31 16:00:00.000000000 -0800
+++ widget/src/windows/nsIImageToBitmap.h 2007-05-13 01:34:48.000000000 -0700
@@ -0,0 +1,73 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org widget code.
+ *
+ * The Initial Developer of the Original Code is
+ * Matthew Gertner .
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * AllPeers Ltd. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef NSIIMAGETOBITMAP_H_
+#define NSIIMAGETOBITMAP_H_
+
+#include "nsISupports.h"
+
+// {337D3FFB-F15F-4df5-83E5-4C7C3D595392}
+#define NSIIMAGETOBITMAP_IID \
+{ 0x337d3ffb, 0xf15f, 0x4df5, \
+ { 0x83, 0xe5, 0x4c, 0x7c, 0x3d, 0x59, 0x53, 0x92 } }
+
+class gfxIImageFrame;
+
+struct HBITMAP__;
+struct HICON__;
+
+typedef struct HBITMAP__ *HBITMAP;
+typedef struct HICON__ *HICON;
+typedef HICON HCURSOR;
+
+/**
+ * An interface that allows converting an nsIImage to a Windows bitmap.
+ */
+class nsIImageToBitmap : public nsISupports {
+ public:
+ NS_DECLARE_STATIC_IID_ACCESSOR(NSIIMAGETOBITMAP_IID)
+
+ NS_IMETHOD ConvertImageToBitmap(gfxIImageFrame* aFrame,
+ HBITMAP& outBitmap) = 0;
+ NS_IMETHOD ConvertImageToIcon(gfxIImageFrame* aFrame,
+ HICON& outIcon) = 0;
+ NS_IMETHOD ConvertImageToCursor(gfxIImageFrame* aFrame,
+ PRUint32 aHotspotX, PRUint32 aHotspotY, HCURSOR& outCursor) = 0;
+};
+
+NS_DEFINE_STATIC_IID_ACCESSOR(nsIImageToBitmap, NSIIMAGETOBITMAP_IID)
+
+#endif
Index: widget/src/windows/nsImageToBitmap.cpp
===================================================================
RCS file: /cvsroot/mozilla/widget/src/windows/nsImageToBitmap.cpp,v
--- widget/src/windows/nsImageToBitmap.cpp 1969-12-31 16:00:00.000000000 -0800
+++ widget/src/windows/nsImageToBitmap.cpp 2007-05-13 01:34:48.000000000 -0700
@@ -0,0 +1,156 @@
+/* vim:set sw=4 sts=4 et cin: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org widget code.
+ *
+ * The Initial Developer of the Original Code is
+ * Matthew Gertner .
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * AllPeers Ltd. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsImageToBitmap.h"
+#include "gfxIImageFrame.h"
+#include "nsIInterfaceRequestor.h"
+#include "nsWindow.h"
+
+#include
+
+NS_IMPL_ISUPPORTS1(nsImageToBitmap, nsIImageToBitmap)
+
+nsImageToBitmap::nsImageToBitmap()
+{
+}
+
+nsImageToBitmap::~nsImageToBitmap()
+{
+}
+
+NS_IMETHODIMP nsImageToBitmap::ConvertImageToBitmap(gfxIImageFrame* frame,
+ HBITMAP& outBitmap)
+{
+ nsresult rv;
+
+ rv = frame->SetMutable(PR_TRUE);
+ if (NS_FAILED(rv))
+ return rv;
+
+ PRInt32 width, height;
+ frame->GetWidth(&width);
+ frame->GetHeight(&height);
+
+ PRUint32 bpr;
+ gfx_format format;
+ frame->GetImageBytesPerRow(&bpr);
+ frame->GetFormat(&format);
+
+ frame->LockImageData();
+
+ PRUint32 dataLen;
+ PRUint8 *data;
+ rv = frame->GetImageData(&data, &dataLen);
+ if (NS_FAILED(rv)) {
+ frame->UnlockImageData();
+ return rv;
+ }
+
+ /* flip the image so that it is stored bottom-up */
+ PRUint8 *bottomUpData = (PRUint8*)malloc(dataLen);
+ if (!bottomUpData) {
+ frame->UnlockImageData();
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ if (format == gfxIFormats::RGB_A8 || format == gfxIFormats::BGR_A8) {
+ for (PRInt32 i = 0; i < height; ++i) {
+ PRUint32 srcOffset = i * bpr;
+ PRUint32 dstOffset = dataLen - (bpr * (i + 1));
+ PRUint32 *srcRow = (PRUint32*)(data + srcOffset);
+ PRUint32 *dstRow = (PRUint32*)(bottomUpData + dstOffset);
+ memcpy(dstRow, srcRow, bpr);
+ }
+ } else {
+ for (PRInt32 i = 0; i < height; ++i) {
+ PRUint32 srcOffset = i * bpr;
+ PRUint32 dstOffset = dataLen - (bpr * (i + 1));
+ PRUint32 *srcRow = (PRUint32*)(data + srcOffset);
+ PRUint32 *dstRow = (PRUint32*)(bottomUpData + dstOffset);
+ for (PRInt32 x = 0; x < width; ++x) {
+ dstRow[x] = (srcRow[x] & 0xFFFFFF) | (0xFF << 24);
+ }
+ }
+ }
+ outBitmap = nsWindow::DataToBitmap(bottomUpData, width, height, 32);
+
+ free(bottomUpData);
+
+ frame->UnlockImageData();
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsImageToBitmap::ConvertImageToIcon(gfxIImageFrame* aFrame,
+ HICON& outIcon)
+{
+ return FrameToIcon(aFrame, PR_TRUE, 0, 0, outIcon);
+}
+
+NS_IMETHODIMP nsImageToBitmap::ConvertImageToCursor(gfxIImageFrame* aFrame,
+ PRUint32 aHotspotX, PRUint32 aHotspotY, HCURSOR& outCursor)
+{
+ return FrameToIcon(aFrame, PR_FALSE, aHotspotX, aHotspotY, outCursor);
+}
+
+nsresult nsImageToBitmap::FrameToIcon(gfxIImageFrame* aFrame,
+ PRBool aIcon, PRUint32 aHotspotX, PRUint32 aHotspotY,
+ HICON& _retval)
+{
+ nsresult rv;
+
+ HBITMAP hBMP;
+ rv = ConvertImageToBitmap(aFrame, hBMP);
+ if (NS_FAILED(rv))
+ return rv;
+
+ ICONINFO info = {0};
+ info.fIcon = aIcon;
+ info.xHotspot = aHotspotX;
+ info.yHotspot = aHotspotY;
+ info.hbmMask = hBMP;
+ info.hbmColor = hBMP;
+
+ _retval = ::CreateIconIndirect(&info);
+ ::DeleteObject(hBMP);
+
+ if (_retval == NULL) {
+ return NS_ERROR_FAILURE;
+ }
+
+ return NS_OK;
+}
Index: widget/src/windows/nsImageToBitmap.h
===================================================================
RCS file: /cvsroot/mozilla/widget/src/windows/nsImageToBitmap.h,v
--- widget/src/windows/nsImageToBitmap.h 1969-12-31 16:00:00.000000000 -0800
+++ widget/src/windows/nsImageToBitmap.h 2007-05-13 01:34:48.000000000 -0700
@@ -0,0 +1,69 @@
+/* vim:set sw=4 sts=4 et cin: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org widget code.
+ *
+ * The Initial Developer of the Original Code is
+ * Matthew Gertner .
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * AllPeers Ltd. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef NSIMAGETOBITMAP_H_
+#define NSIMAGETOBITMAP_H_
+
+#include "nsIImageToBitmap.h"
+
+class nsImageToBitmap : public nsIImageToBitmap {
+ public:
+ NS_DECL_ISUPPORTS
+
+ nsImageToBitmap();
+ ~nsImageToBitmap();
+
+ NS_IMETHOD ConvertImageToBitmap(gfxIImageFrame* aFrame,
+ HBITMAP& outBitmap);
+ NS_IMETHOD ConvertImageToIcon(gfxIImageFrame* aFrame,
+ HICON& outIcon);
+ NS_IMETHOD ConvertImageToCursor(gfxIImageFrame* aFrame,
+ PRUint32 aHotspotX, PRUint32 aHotspotY, HCURSOR& outCursor);
+
+ protected:
+ nsresult FrameToIcon(gfxIImageFrame* aFrame,
+ PRBool aIcon, PRUint32 aHotspotX, PRUint32 aHotspotY,
+ HICON& _retval);
+};
+
+
+// {7CA6DC5F-F216-421d-AD8F-30C6E8FCC3E3}
+#define NS_IMAGE_TO_BITMAP_CID \
+{ 0x7ca6dc5f, 0xf216, 0x421d, \
+ { 0xad, 0x8f, 0x30, 0xc6, 0xe8, 0xfc, 0xc3, 0xe3 } }
+
+#endif
Index: widget/src/windows/nsWindow.cpp
===================================================================
RCS file: /cvsroot/mozilla/widget/src/windows/nsWindow.cpp,v
--- widget/src/windows/nsWindow.cpp 2007-05-13 01:34:48.000000000 -0700 3.688
+++ widget/src/windows/nsWindow.cpp 2007-05-13 01:34:48.000000000 -0700
@@ -55,16 +55,17 @@
//#define DEBUG_IME2
//#define DEBUG_KBSTATE
#endif
#include "nsWindow.h"
#include "nsIAppShell.h"
#include "nsIFontMetrics.h"
#include "nsIFontEnumerator.h"
+#include "nsIImageToBitmap.h"
#include "nsIPrefBranch.h"
#include "nsIPrefService.h"
#include "nsFont.h"
#include "nsGUIEvent.h"
#include "nsIRenderingContext.h"
#include "nsIDeviceContext.h"
#include "nsIScreenManager.h"
#include "nsRect.h"
@@ -194,16 +195,17 @@ WINUSERAPI
BOOL WINAPI UpdateLayeredWindow(HWND hWnd, HDC hdcDst, POINT *pptDst,
SIZE *psize, HDC hdcSrc, POINT *pptSrc,
COLORREF crKey, BLENDFUNCTION *pblend,
DWORD dwFlags);
#endif
#endif
+static nsCOMPtr gImageToBitmap;
#ifdef WINCE
static PRBool gSoftKeyMenuBar = PR_FALSE;
static PRBool gOverrideHWKeys = PR_TRUE;
typedef BOOL (__stdcall *UnregisterFunc1Proc)( UINT, UINT );
static UnregisterFunc1Proc gProcUnregisterFunc = NULL;
static HINSTANCE gCoreDll = NULL;
@@ -2803,224 +2805,48 @@ NS_IMETHODIMP nsWindow::SetCursor(imgICo
nsCOMPtr frame;
aCursor->GetFrameAt(0, getter_AddRefs(frame));
if (!frame)
return NS_ERROR_NOT_AVAILABLE;
PRInt32 width, height;
frame->GetWidth(&width);
frame->GetHeight(&height);
-
+
// Reject cursors greater than 128 pixels in some direction, to prevent
// spoofing.
// XXX ideally we should rescale. Also, we could modify the API to
// allow trusted content to set larger cursors.
if (width > 128 || height > 128)
return NS_ERROR_NOT_AVAILABLE;
-#ifdef MOZ_CAIRO_GFX
- PRUint32 bpr;
- gfx_format format;
- frame->GetImageBytesPerRow(&bpr);
- frame->GetFormat(&format);
-
- frame->LockImageData();
-
- PRUint32 dataLen;
- PRUint8 *data;
- nsresult rv = frame->GetImageData(&data, &dataLen);
- if (NS_FAILED(rv)) {
- frame->UnlockImageData();
- return rv;
- }
-
- /* flip the image so that it is stored bottom-up */
- PRUint8 *bottomUpData = (PRUint8*)malloc(dataLen);
- if (!bottomUpData) {
- frame->UnlockImageData();
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- if (format == gfxIFormats::RGB_A8 || format == gfxIFormats::BGR_A8) {
- for (PRInt32 i = 0; i < height; ++i) {
- PRUint32 srcOffset = i * bpr;
- PRUint32 dstOffset = dataLen - (bpr * (i + 1));
- PRUint32 *srcRow = (PRUint32*)(data + srcOffset);
- PRUint32 *dstRow = (PRUint32*)(bottomUpData + dstOffset);
- memcpy(dstRow, srcRow, bpr);
- }
- } else {
- for (PRInt32 i = 0; i < height; ++i) {
- PRUint32 srcOffset = i * bpr;
- PRUint32 dstOffset = dataLen - (bpr * (i + 1));
- PRUint32 *srcRow = (PRUint32*)(data + srcOffset);
- PRUint32 *dstRow = (PRUint32*)(bottomUpData + dstOffset);
- for (PRInt32 x = 0; x < width; ++x) {
- dstRow[x] = (srcRow[x] & 0xFFFFFF) | (0xFF << 24);
- }
- }
- }
- HBITMAP bmp = DataToBitmap(bottomUpData, width, height, 32);
-
- free(bottomUpData);
-
- frame->UnlockImageData();
-
- ICONINFO info = {0};
- info.fIcon = FALSE;
- info.xHotspot = aHotspotX;
- info.yHotspot = aHotspotY;
- info.hbmMask = bmp;
- info.hbmColor = bmp;
-
- HCURSOR cursor = ::CreateIconIndirect(&info);
- ::DeleteObject(bmp);
- if (cursor == NULL) {
- return NS_ERROR_FAILURE;
- }
-
- mCursor = nsCursor(-1);
- ::SetCursor(cursor);
-
- NS_IF_RELEASE(gCursorImgContainer);
- gCursorImgContainer = aCursor;
- NS_ADDREF(gCursorImgContainer);
-
- if (gHCursor != NULL)
- ::DestroyIcon(gHCursor);
- gHCursor = cursor;
-
-#else
-
- gfx_format format;
- nsresult rv = frame->GetFormat(&format);
- if (NS_FAILED(rv))
- return rv;
-
- if (format != gfxIFormats::BGR_A1 && format != gfxIFormats::BGR_A8 &&
- format != gfxIFormats::BGR)
- return NS_ERROR_UNEXPECTED;
-
- // On Win2k with nVidia video drivers 71.84 at 32 bit color, cursors that
- // have 8 bit alpha are truncated to 64x64. Skip cursors larger than that.
- // This is redundant with checks above, but we'll leave it in as a reminder
- // in case we start accepting larger cursors again
- if (IsWin2k() && (format == gfxIFormats::BGR_A8) &&
- (width > 64 || height > 64))
- return NS_ERROR_FAILURE;
-
- PRUint32 bpr;
- rv = frame->GetImageBytesPerRow(&bpr);
- if (NS_FAILED(rv))
- return rv;
-
- frame->LockImageData();
- PRUint32 dataLen;
- PRUint8* data;
- rv = frame->GetImageData(&data, &dataLen);
- if (NS_FAILED(rv)) {
- frame->UnlockImageData();
- return rv;
- }
-
- HBITMAP hBMP = NULL;
- if (format != gfxIFormats::BGR_A8) {
- hBMP = DataToBitmap(data, width, height, 24);
- if (hBMP == NULL) {
- frame->UnlockImageData();
- return NS_ERROR_FAILURE;
- }
- }
-
- HBITMAP hAlpha = NULL;
- if (format == gfxIFormats::BGR) {
- hAlpha = CreateOpaqueAlphaChannel(width, height);
- } else {
- PRUint32 abpr;
- rv = frame->GetAlphaBytesPerRow(&abpr);
- if (NS_FAILED(rv)) {
- frame->UnlockImageData();
- if (hBMP != NULL)
- ::DeleteObject(hBMP);
- return rv;
- }
-
- PRUint8* adata;
- frame->LockAlphaData();
- rv = frame->GetAlphaData(&adata, &dataLen);
- if (NS_FAILED(rv)) {
- if (hBMP != NULL)
- ::DeleteObject(hBMP);
- frame->UnlockImageData();
- frame->UnlockAlphaData();
- return rv;
- }
-
- if (format == gfxIFormats::BGR_A8) {
- // Convert BGR_A8 to BGRA.
- // Some platforms (or video cards?) on 32bit color mode will ignore
- // hAlpha. For them, we could speed up things by creating an opaque alpha
- // channel, but since we don't know how to determine whether hAlpha is
- // ignored, create a proper 1 bit alpha channel to supplement the RGBA.
- // Plus, on non-32bit color and possibly other platforms, the alpha
- // of RGBA is ignored.
- PRUint8* bgra8data = DataToAData(data, bpr, adata, abpr, width, height);
- if (bgra8data) {
- hBMP = DataToBitmap(bgra8data, width, height, 32);
- if (hBMP != NULL) {
- PRUint8* a1data = Data8BitTo1Bit(adata, abpr, width, height);
- if (a1data) {
- hAlpha = DataToBitmap(a1data, width, height, 1);
- delete [] a1data;
- }
- }
- delete [] bgra8data;
- }
- } else {
- hAlpha = DataToBitmap(adata, width, height, 1);
- }
-
- frame->UnlockAlphaData();
- }
- frame->UnlockImageData();
- if (hBMP == NULL) {
- return NS_ERROR_FAILURE;
- }
- if (hAlpha == NULL) {
- ::DeleteObject(hBMP);
- return NS_ERROR_FAILURE;
+ nsresult rv;
+ if (!gImageToBitmap)
+ {
+ gImageToBitmap =
+ do_GetService("@mozilla.org/widget/image-to-win-bitmap;1", &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
}
- ICONINFO info = {0};
- info.fIcon = FALSE;
- info.xHotspot = aHotspotX;
- info.yHotspot = aHotspotY;
- info.hbmMask = hAlpha;
- info.hbmColor = hBMP;
-
- HCURSOR cursor = ::CreateIconIndirect(&info);
- ::DeleteObject(hBMP);
- ::DeleteObject(hAlpha);
- if (cursor == NULL) {
- return NS_ERROR_FAILURE;
- }
+ HCURSOR cursor;
+ rv = gImageToBitmap->ConvertImageToCursor(frame, aHotspotX, aHotspotY,
+ cursor);
+ NS_ENSURE_SUCCESS(rv, rv);
mCursor = nsCursor(-1);
::SetCursor(cursor);
NS_IF_RELEASE(gCursorImgContainer);
gCursorImgContainer = aCursor;
NS_ADDREF(gCursorImgContainer);
if (gHCursor != NULL)
::DestroyIcon(gHCursor);
gHCursor = cursor;
-#endif
-
return NS_OK;
}
NS_IMETHODIMP nsWindow::HideWindowChrome(PRBool aShouldHide)
{
HWND hwnd = GetTopLevelHWND(mWnd, PR_TRUE);
if (!GetNSWindowPtr(hwnd))
{
Index: widget/src/windows/nsWindow.h
===================================================================
RCS file: /cvsroot/mozilla/widget/src/windows/nsWindow.h,v
--- widget/src/windows/nsWindow.h 2007-05-13 01:34:48.000000000 -0700 3.232
+++ widget/src/windows/nsWindow.h 2007-05-13 01:34:48.000000000 -0700
@@ -258,16 +258,67 @@ public:
PRInt32 GetNewCmdMenuId() { mMenuCmdId++; return mMenuCmdId; }
void InitEvent(nsGUIEvent& event, nsPoint* aPoint = nsnull);
void SuppressBlurEvents(PRBool aSuppress);
PRBool BlurEventsSuppressed();
+ /**
+ * Create a 1 bit mask out of a 8 bit alpha layer.
+ *
+ * @param aAlphaData 8 bit alpha data
+ * @param aAlphaBytesPerRow How many bytes one row of data is
+ * @param aWidth Width of the alpha data, in pixels
+ * @param aHeight Height of the alpha data, in pixels
+ *
+ * @return 1 bit mask. Must be delete[]d. On failure, NULL will be returned.
+ */
+ static PRUint8* Data8BitTo1Bit(PRUint8* aAlphaData, PRUint32 aAlphaBytesPerRow,
+ PRUint32 aWidth, PRUint32 aHeight);
+
+ /**
+ * Combine the given image data with a separate alpha channel to image data
+ * with the alpha channel interleaved with the image data (BGRA).
+ *
+ * @return BGRA data. Must be delete[]d. On failure, NULL will be returned.
+ */
+ static PRUint8* DataToAData(PRUint8* aImageData, PRUint32 aImageBytesPerRow,
+ PRUint8* aAlphaData, PRUint32 aAlphaBytesPerRow,
+ PRUint32 aWidth, PRUint32 aHeight);
+ /**
+ * Convert the given image data to a HBITMAP. If the requested depth is
+ * 32 bit and the OS supports translucency, a bitmap with an alpha channel
+ * will be returned.
+ *
+ * @param aImageData The image data to convert. Must use the format accepted
+ * by CreateDIBitmap.
+ * @param aWidth With of the bitmap, in pixels.
+ * @param aHeight Height of the image, in pixels.
+ * @param aDepth Image depth, in bits. Should be one of 1, 24 and 32.
+ *
+ * @return The HBITMAP representing the image. Caller should call
+ * DeleteObject when done with the bitmap.
+ * On failure, NULL will be returned.
+ */
+ static HBITMAP DataToBitmap(PRUint8* aImageData,
+ PRUint32 aWidth,
+ PRUint32 aHeight,
+ PRUint32 aDepth);
+
+ /**
+ * Create a bitmap representing an opaque alpha channel (filled with 0xff).
+ * @param aWidth Desired with of the bitmap
+ * @param aHeight Desired height of the bitmap
+ * @return The bitmap. Caller should call DeleteObject when done with
+ * the bitmap. On failure, NULL will be returned.
+ */
+ static HBITMAP CreateOpaqueAlphaChannel(PRUint32 aWidth, PRUint32 aHeight);
+
protected:
#ifndef WINCE
// special callback hook methods for pop ups
static LRESULT CALLBACK MozSpecialMsgFilter(int code, WPARAM wParam, LPARAM lParam);
static LRESULT CALLBACK MozSpecialWndProc(int code, WPARAM wParam, LPARAM lParam);
static LRESULT CALLBACK MozSpecialMouseProc(int code, WPARAM wParam, LPARAM lParam);
@@ -481,68 +532,16 @@ protected:
// Heap dump
static UINT uWM_HEAP_DUMP; // Dump heap to a file
// Cursor caching
static HCURSOR gHCursor;
static imgIContainer* gCursorImgContainer;
- /**
- * Create a 1 bit mask out of a 8 bit alpha layer.
- *
- * @param aAlphaData 8 bit alpha data
- * @param aAlphaBytesPerRow How many bytes one row of data is
- * @param aWidth Width of the alpha data, in pixels
- * @param aHeight Height of the alpha data, in pixels
- *
- * @return 1 bit mask. Must be delete[]d. On failure, NULL will be returned.
- */
- static PRUint8* Data8BitTo1Bit(PRUint8* aAlphaData, PRUint32 aAlphaBytesPerRow,
- PRUint32 aWidth, PRUint32 aHeight);
-
- /**
- * Combine the given image data with a separate alpha channel to image data
- * with the alpha channel interleaved with the image data (BGRA).
- *
- * @return BGRA data. Must be delete[]d. On failure, NULL will be returned.
- */
- static PRUint8* DataToAData(PRUint8* aImageData, PRUint32 aImageBytesPerRow,
- PRUint8* aAlphaData, PRUint32 aAlphaBytesPerRow,
- PRUint32 aWidth, PRUint32 aHeight);
- /**
- * Convert the given image data to a HBITMAP. If the requested depth is
- * 32 bit and the OS supports translucency, a bitmap with an alpha channel
- * will be returned.
- *
- * @param aImageData The image data to convert. Must use the format accepted
- * by CreateDIBitmap.
- * @param aWidth With of the bitmap, in pixels.
- * @param aHeight Height of the image, in pixels.
- * @param aDepth Image depth, in bits. Should be one of 1, 24 and 32.
- *
- * @return The HBITMAP representing the image. Caller should call
- * DeleteObject when done with the bitmap.
- * On failure, NULL will be returned.
- */
- static HBITMAP DataToBitmap(PRUint8* aImageData,
- PRUint32 aWidth,
- PRUint32 aHeight,
- PRUint32 aDepth);
-
- /**
- * Create a bitmap representing an opaque alpha channel (filled with 0xff).
- * @param aWidth Desired with of the bitmap
- * @param aHeight Desired height of the bitmap
- * @return The bitmap. Caller should call DeleteObject when done with
- * the bitmap. On failure, NULL will be returned.
- */
- static HBITMAP CreateOpaqueAlphaChannel(PRUint32 aWidth, PRUint32 aHeight);
-
-
#ifdef ACCESSIBILITY
static BOOL gIsAccessibilityOn;
static HINSTANCE gmAccLib;
static LPFNLRESULTFROMOBJECT gmLresultFromObject;
static STDMETHODIMP_(LRESULT) LresultFromObject(REFIID riid, WPARAM wParam, LPUNKNOWN pAcc);
#endif
static BOOL CALLBACK BroadcastMsgToChildren(HWND aWnd, LPARAM aMsg);