nsSystemTrayServiceWin.cpp
Go to the documentation of this file.
1 /* ***** BEGIN LICENSE BLOCK *****
2  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3  *
4  * The contents of this file are subject to the Mozilla Public License Version
5  * 1.1 (the "License"); you may not use this file except in compliance with
6  * the License. You may obtain a copy of the License at
7  * http://www.mozilla.org/MPL/
8  *
9  * Software distributed under the License is distributed on an "AS IS" basis,
10  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11  * for the specific language governing rights and limitations under the
12  * License.
13  *
14  * The Original Code is MinimizeToTray.
15  *
16  * The Initial Developer of the Original Code are
17  * Mark Yen and Brad Peterson.
18  * Portions created by the Initial Developer are Copyright (C) 2004
19  * the Initial Developer. All Rights Reserved.
20  *
21  * Contributor(s):
22  * Mark Yen <mook.moz+cvs.mozilla.org@gmail.com>, Original author
23  * Brad Peterson <b_peterson@yahoo.com>, Original author
24  * Daniel Glazman <daniel.glazman@disruptive-innovations.com>
25  * Matthew Gertner <matthew@allpeers.com>
26  *
27  * Alternatively, the contents of this file may be used under the terms of
28  * either the GNU General Public License Version 2 or later (the "GPL"), or
29  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30  * in which case the provisions of the GPL or the LGPL are applicable instead
31  * of those above. If you wish to allow use of your version of this file only
32  * under the terms of either the GPL or the LGPL, and not to allow others to
33  * use your version of this file under the terms of the MPL, indicate your
34  * decision by deleting the provisions above and replace them with the notice
35  * and other provisions required by the GPL or the LGPL. If you do not delete
36  * the provisions above, a recipient may use your version of this file under
37  * the terms of any one of the MPL, the GPL or the LGPL.
38  *
39  * ***** END LICENSE BLOCK ***** */
40 
41 #include "nsStringGlue.h"
42 #include "nsSystemTrayServiceWin.h"
43 #include "gfxImageSurface.h"
44 #include "imgIContainer.h"
45 #include "imgIDecoder.h"
46 #include "nsAutoPtr.h"
47 #include "nsComponentManagerUtils.h"
48 #include "nsMemory.h"
49 #include "nsIBaseWindow.h"
50 #include "nsIBufferedStreams.h"
51 #include "nsIChannel.h"
52 #include "nsIContent.h"
53 #include "nsIDocShell.h"
54 #include "nsIDocument.h"
55 #include "nsIDOMAbstractView.h"
56 #include "nsIDOMDocument.h"
57 #include "nsIDOMDocumentEvent.h"
58 #include "nsIDOMDocumentView.h"
59 #include "nsIDOMDOMImplementation.h"
60 #include "nsIDOMDocumentType.h"
61 #include "nsIDOMElement.h"
62 #include "nsIDOMEvent.h"
63 #include "nsIDOMEventTarget.h"
64 #include "nsIDOMMouseEvent.h"
65 #include "nsIDOMNodeList.h"
66 #include "nsIDOMWindow.h"
67 #include "nsIInterfaceRequestor.h"
68 #include "nsIInterfaceRequestorUtils.h"
69 #include "nsIIOService.h"
70 #include "nsIPresShell.h"
71 #include "nsIWidget.h"
72 #include "nsIWindowUtil.h"
73 #include "nsIURI.h"
74 #include "nsIXULDocument.h"
75 #include "nsIXULWindow.h"
76 #include "nsServiceManagerUtils.h"
77 
78 #include "nsIImageToBitmap.h"
79 
80 #include <tchar.h>
81 
82 #pragma comment(lib, "shell32.lib")
83 
85  TEXT("_SYSTEMTRAYSERVICE_INST");
87  TEXT("_SYSTEMTRAYSERVICE_PROC");
88 
90 
91 #define MK_ERROR_OFFSET (0xE0000000 + (__LINE__ * 0x10000))
92 
93 #define MK_ENSURE_NATIVE(res) \
94  PR_BEGIN_MACRO \
95  NS_ENSURE_TRUE(0 != res || 0 == ::GetLastError(), \
96  ::GetLastError() + MK_ERROR_OFFSET); \
97  PR_END_MACRO
98 
99 // this can be WM_USER + anything
100 #define WM_TRAYICON (WM_USER + 0x17b6)
101 
103  imgILoad, imgIContainerObserver, imgIDecoderObserver)
104 
106 {
107  /* member initializers and constructor code */
108  mIconDataMap.Init();
109 }
110 
111 nsSystemTrayService::~nsSystemTrayService()
112 {
113  BOOL windowClassUnregistered = ::UnregisterClass(
115  ::GetModuleHandle(NULL));
116  if (windowClassUnregistered)
117  nsSystemTrayService::s_wndClass = NULL;
118 }
119 
120 NS_IMETHODIMP
121 nsSystemTrayService::ShowIcon(const nsAString& aIconId,
122  nsIURI* imageURI,
123  nsIDOMWindow* aDOMWindow)
124 {
125  nsresult rv;
126 
127  NOTIFYICONDATAW notifyIconData;
128  if (mIconDataMap.Get(aIconId, &notifyIconData))
129  // Already have an entry so just change the image
130  {
131  HICON hicon;
132  rv = GetIconForURI(imageURI, hicon);
133  NS_ENSURE_SUCCESS(rv, rv);
134 
135  notifyIconData.hIcon = hicon;
136  MK_ENSURE_NATIVE(::Shell_NotifyIcon(NIM_MODIFY,
137  &notifyIconData));
138 
139  return NS_OK;
140  }
141 
142  // first make sure that we can find the element associated with the
143  // <trayicon> element
144  nsCOMPtr<nsIDOMDocument> document;
145  rv = aDOMWindow->GetDocument(getter_AddRefs(document));
146  NS_ENSURE_SUCCESS(rv, rv);
147 
148  nsCOMPtr<nsIDOMElement> iconElement;
149  rv = document->GetElementById(aIconId, getter_AddRefs(iconElement));
150  NS_ENSURE_SUCCESS(rv, rv);
151 
152  nsCOMPtr<nsIWindowUtil>
153  windowUtil(do_CreateInstance("@mozilla.org/window-util;1", &rv));
154  NS_ENSURE_SUCCESS(rv, rv);
155  rv = windowUtil->Init(aDOMWindow);
156  NS_ENSURE_SUCCESS(rv, rv);
157 
158  nsCOMPtr<nsIDocShell> docShell;
159  rv = windowUtil->GetDocShell(getter_AddRefs(docShell));
160  NS_ENSURE_SUCCESS(rv, rv);
161  nsCOMPtr<nsIBaseWindow> baseWindow(do_QueryInterface(docShell, &rv));
162  NS_ENSURE_SUCCESS(rv, rv);
163  nativeWindow theNativeWindow;
164  rv = baseWindow->GetParentNativeWindow( &theNativeWindow );
165  NS_ENSURE_SUCCESS(rv, rv);
166 
167  HWND hWnd = reinterpret_cast<HWND>(theNativeWindow);
168  NS_ENSURE_TRUE(hWnd, NS_ERROR_UNEXPECTED);
169 
170  // yay, we succeeded so we can add the icon
171  rv = AddTrayIcon(hWnd, imageURI, aIconId, iconElement);
172  NS_ENSURE_SUCCESS(rv, rv);
173 
174  return NS_OK;
175 }
176 
177 NS_IMETHODIMP
178 nsSystemTrayService::HideIcon(const nsAString& iconId)
179 {
180  NOTIFYICONDATAW notifyIconData;
181  if (!mIconDataMap.Get(iconId, &notifyIconData))
182  // can't find the icon data
183  return NS_ERROR_NOT_AVAILABLE;
184 
185  if (notifyIconData.hWnd)
186  ::DestroyWindow(notifyIconData.hWnd);
187 
188  Shell_NotifyIcon(NIM_DELETE, &notifyIconData);
189 
190  mIconDataMap.Remove(iconId);
191 
192  return NS_OK;
193 }
194 
195 nsresult
196 nsSystemTrayService::AddTrayIcon(HWND hwnd, nsIURI* iconURI,
197  const nsAString& iconId,
198  nsIDOMElement* targetElement)
199 {
200  nsresult rv;
201 
202  NOTIFYICONDATAW notifyIconData;
203  memset(&notifyIconData, 0, sizeof(NOTIFYICONDATAW));
204  notifyIconData.cbSize = sizeof(NOTIFYICONDATAW);
205  notifyIconData.uCallbackMessage = WM_TRAYICON;
206  notifyIconData.uID = 1;
207  notifyIconData.uFlags = NIF_MESSAGE | NIF_ICON;
208 
209  HICON hicon = NULL;
210  if (iconURI)
211  {
212  rv = GetIconForURI(iconURI, hicon);
213  // ignore errors, we have fallback
214  //NS_ENSURE_SUCCESS(rv, rv);
215  }
216 
217  if (NS_FAILED(rv) || !hicon)
218  {
219  // just use the window icon
220  rv = GetIconForWnd(hwnd, hicon);
221  NS_ENSURE_SUCCESS(rv, rv);
222  }
223 
224  notifyIconData.hIcon = hicon;
225 
226  HWND listenerWindow;
227  rv = CreateListenerWindow(&listenerWindow, targetElement);
228  NS_ENSURE_SUCCESS(rv, rv);
229 
230  //::SetTimer(listenerWindow, 1, 100, NULL);
231 
232 // add the icon
233  notifyIconData.hWnd = listenerWindow;
234  MK_ENSURE_NATIVE(Shell_NotifyIcon(NIM_ADD, &notifyIconData));
235 
236  mIconDataMap.Put(iconId, notifyIconData);
237 
238  return NS_OK;
239 }
240 
241 
242 NS_IMETHODIMP
243 nsSystemTrayService::SetTitle(const nsAString& iconId, const nsAString& title)
244 {
245  NOTIFYICONDATAW notifyIconData;
246  if (!mIconDataMap.Get(iconId, &notifyIconData))
247  return NS_ERROR_NOT_AVAILABLE;
248 
249  notifyIconData.uFlags = NIF_TIP;
250  PRUint32 length = title.Length();
251  if (length > 64)
252  length = 64;
253 
254  wcsncpy(notifyIconData.szTip, PromiseFlatString(title).get(), length);
255 
256  MK_ENSURE_NATIVE(Shell_NotifyIcon(NIM_MODIFY, &notifyIconData));
257 
258  return NS_OK;
259 }
260 
261 nsresult
262 nsSystemTrayService::GetIconForURI(nsIURI* iconURI, HICON& result)
263 {
264  nsresult rv;
265 
266  // get a channel to read the data from
267  nsCOMPtr<nsIIOService>
268  ioService(do_GetService("@mozilla.org/network/io-service;1", &rv));
269  nsCOMPtr<nsIChannel> channel;
270  rv = ioService->NewChannelFromURI(iconURI, getter_AddRefs(channel));
271  NS_ENSURE_SUCCESS(rv, rv);
272 
273 #ifdef DEBUG
274  {
275  nsCString spec;
276  rv = iconURI->GetSpec(spec);
277  NS_ENSURE_SUCCESS(rv, rv);
278  printf("icon URI: %s\n", spec.get());
279  }
280 #endif
281 
282  nsCOMPtr<nsIInputStream> inputStream;
283  rv = channel->Open(getter_AddRefs(inputStream));
284  NS_ENSURE_SUCCESS(rv, rv);
285 
286  // get the source MIME type
287  nsCAutoString sourceMimeType;
288  rv = channel->GetContentType(sourceMimeType);
289  NS_ENSURE_SUCCESS(rv, rv);
290 
291  // get the decoder
292  nsCAutoString decoderContractId =
293  NS_LITERAL_CSTRING("@mozilla.org/image/decoder;2?type=");
294  decoderContractId.Append(sourceMimeType);
295  nsCOMPtr<imgIDecoder>
296  decoder(do_CreateInstance(decoderContractId.get(), &rv));
297  NS_ENSURE_SUCCESS(rv, rv);
298 
299  // decode into our image container
300  rv = decoder->Init(this);
301  NS_ENSURE_SUCCESS(rv, rv);
302 
303  PRUint32 available;
304  rv = inputStream->Available(&available);
305  NS_ENSURE_SUCCESS(rv, rv);
306 
307  // need to wrap the stream so that the decoder can ReadSegments
308  nsCOMPtr<nsIBufferedInputStream> bufferedStream(
309  do_CreateInstance("@mozilla.org/network/buffered-input-stream;1", &rv));
310  NS_ENSURE_SUCCESS(rv, rv);
311 
312  rv = bufferedStream->Init(inputStream, 4096);
313  NS_ENSURE_SUCCESS(rv, rv);
314 
315  PRUint32 written;
316  rv = decoder->WriteFrom(bufferedStream, available, &written);
317  NS_ENSURE_SUCCESS(rv, rv);
318 
319  rv = decoder->Close();
320  NS_ENSURE_SUCCESS(rv, rv);
321 
322  nsRefPtr<gfxImageSurface> imageFrame;
323  rv = mImage->CopyCurrentFrame(getter_AddRefs(imageFrame));
324  NS_ENSURE_SUCCESS(rv, rv);
325 
326  if (!imageFrame)
327  return NS_ERROR_NOT_AVAILABLE;
328 
329  nsCOMPtr<nsIImageToBitmap> imageToBitmap(
330  do_GetService("@mozilla.org/widget/image-to-win32-hbitmap;1", &rv));
331  NS_ENSURE_SUCCESS(rv, rv);
332 
333  return imageToBitmap->ConvertImageToIcon(imageFrame, result);
334 }
335 
336 nsresult
338 {
339  result = (HICON)::SendMessage(hwnd, WM_GETICON, ICON_SMALL, NULL);
340  if (!result) {
341  // can't find icon; try GetClassLong
342  result = (HICON)::GetClassLongPtr(hwnd, GCLP_HICONSM);
343  }
344  if (!result) {
345  // still no icon - use generic windows icon
346  result = ::LoadIcon(NULL, IDI_WINLOGO);
347  }
348  if (!result)
349  return NS_ERROR_FAILURE;
350  return NS_OK;
351 }
352 
353 nsresult
355  nsIDOMElement* targetElement)
356 {
357  ::SetLastError(0);
358  HINSTANCE hInst = ::GetModuleHandle(NULL);
359  MK_ENSURE_NATIVE(hInst);
360 
361  if (!nsSystemTrayService::s_wndClass) {
362  WNDCLASS wndClassDef;
363  wndClassDef.style = CS_NOCLOSE | CS_GLOBALCLASS;
364  wndClassDef.lpfnWndProc = nsSystemTrayService::WindowProc;
365  wndClassDef.cbClsExtra = 0;
366  wndClassDef.cbWndExtra = 0;
367  wndClassDef.hInstance = hInst;
368  wndClassDef.hIcon = NULL;
369  wndClassDef.hCursor = NULL;
370  wndClassDef.hbrBackground = NULL;
371  wndClassDef.lpszMenuName = NULL;
372  wndClassDef.lpszClassName = TEXT("MinimizeToTray:MessageWindowClass");
373 
374  nsSystemTrayService::s_wndClass = ::RegisterClass(&wndClassDef);
375  MK_ENSURE_NATIVE(nsSystemTrayService::s_wndClass);
376  }
377 
378  *listenerWindow =
379  ::CreateWindow(
380  (LPCTSTR)nsSystemTrayService::s_wndClass, //class
381  TEXT("MinimizeToTray:MessageWindow"), //caption
382  WS_MINIMIZE, //style
383  CW_USEDEFAULT , //x
384  CW_USEDEFAULT , //y
385  CW_USEDEFAULT, //width
386  CW_USEDEFAULT, //height
387  ::GetDesktopWindow(), //parent
388  NULL, //menu
389  hInst, //hInst
390  NULL); //param
391 
392  if (!*listenerWindow) {
393  if (::UnregisterClass((LPCTSTR)nsSystemTrayService::s_wndClass, hInst))
394  nsSystemTrayService::s_wndClass = NULL;
395  MK_ENSURE_NATIVE(*listenerWindow);
396  }
397 
398  MK_ENSURE_NATIVE(::SetProp(
399  *listenerWindow,
400  S_PROPINST,
401  (HANDLE) targetElement)
402  );
403 
404  return NS_OK;
405 }
406 
407 // a little helper class to automatically manage our reentrancy counter
408 // if we reenter WindowProc very bad things happen
410 {
411 public:
412  AutoReentryBlocker(PRUint32* counter) { mCounter = counter; (*mCounter)++; }
413  ~AutoReentryBlocker() { (*mCounter)--; }
414 
415 protected:
416  PRUint32* mCounter;
417 };
418 
419 static PRUint32 numberOfCallsIntoWindowProc = 0;
420 
421 LRESULT CALLBACK
423  UINT uMsg,
424  WPARAM wParam,
425  LPARAM lParam)
426 {
427  if (numberOfCallsIntoWindowProc > 0)
428  // don't reenter this function ever or we could crash (if the popup
429  // frame is still being destroyed)
430  return FALSE;
431 
432  AutoReentryBlocker blocker(&numberOfCallsIntoWindowProc);
433 
434  bool handled = true;
435 
436  PRUint32 message = 0;
437  PRUint32 mask = 0;
438  POINT mousePos;
439 
440  PRUint16 button;
441  PRInt32 detail;
442  nsAutoString typeArg;
443 
444  switch(uMsg) {
445  case WM_TRAYICON:
446  break;
447  case WM_CREATE:
448  return 0;
449  case WM_NCCREATE:
450  return true;
451  case WM_ACTIVATE:
452  if (LOWORD(wParam) == WA_INACTIVE)
453  {
454  // if we are activating the popup menu then it will hide itself after
455  // command selection, so we just ignore this
456  // I don't suppose that using the Window class name is the cleanest
457  // way to do this, but it's hopefully a temporary hack anyway until
458  // the issues with popups are solved
459  // (see https://bugzilla.mozilla.org/show_bug.cgi?id=279703) and I
460  // can't see a way to get at the HWND of the popup to remember it
461  TCHAR classname[256];
462  HWND hNewWnd = (HWND) lParam;
463  ::GetClassName(hNewWnd, classname, 256);
464  if (_tcscmp(classname, _T("MozillaDropShadowWindowClass")) == 0)
465  return FALSE;
466 
467  typeArg = NS_LITERAL_STRING("blur");
468  detail = -1;
469  break;
470  }
471  default:
472  handled = false;
473  }
474 
475  // convert the Win32 event into a DOM event
476  // screaming to be encapsulated somewhere else (utility class?)
477  // only supporting click events for the time being
478 
479  nsCOMPtr<nsIDOMElement> targetElement;
480  nsCOMPtr<nsIDOMEventTarget> eventTarget;
481  if (handled)
482  {
483  targetElement = (nsIDOMElement *) GetProp(hwnd, S_PROPINST);
484  eventTarget = do_QueryInterface(targetElement);
485  }
486 
487  if (!eventTarget)
488  handled = false;
489 
490  nsAutoString syntheticEvent;
491 
492  if (uMsg == WM_TRAYICON && handled) {
493  switch (lParam) {
494  case WM_LBUTTONDOWN:
495  button = 0;
496  detail = 1;
497  typeArg = NS_LITERAL_STRING("mousedown");
498  break;
499  case WM_RBUTTONDOWN:
500  button = 2;
501  detail = 1;
502  typeArg = NS_LITERAL_STRING("mousedown");
503  break;
504  case WM_MBUTTONDOWN:
505  button = 1;
506  detail = 1;
507  typeArg = NS_LITERAL_STRING("mousedown");
508  break;
509  case WM_LBUTTONUP:
510  button = 0;
511  detail = 1;
512  typeArg = NS_LITERAL_STRING("mouseup");
513  syntheticEvent = NS_LITERAL_STRING("click");
514  break;
515  case WM_RBUTTONUP:
516  button = 2;
517  detail = 1;
518  typeArg = NS_LITERAL_STRING("mouseup");
519  syntheticEvent = NS_LITERAL_STRING("click");
520  break;
521  case WM_MBUTTONUP:
522  button = 1;
523  detail = 1;
524  typeArg = NS_LITERAL_STRING("mouseup");
525  syntheticEvent = NS_LITERAL_STRING("click");
526  break;
527  case WM_CONTEXTMENU:
528  button = 2;
529  detail = 1;
530  typeArg = NS_LITERAL_STRING("contextmenu");
531  break;
532  case WM_LBUTTONDBLCLK:
533  button = 0;
534  detail = 2;
535  typeArg = NS_LITERAL_STRING("click");
536  break;
537  case WM_MBUTTONDBLCLK:
538  button = 1;
539  detail = 2;
540  typeArg = NS_LITERAL_STRING("click");
541  break;
542  case WM_RBUTTONDBLCLK:
543  button = 2;
544  detail = 2;
545  typeArg = NS_LITERAL_STRING("click");
546  break;
547  default:
548  handled = false;
549  break;
550  }
551  }
552 
553  PRBool shiftArg = PR_FALSE;
554  PRBool ctrlArg = PR_FALSE;
555  PRBool altArg = PR_FALSE;
556 
557  if (handled) {
558  GetCursorPos(&mousePos);
559  // check modifier key states
560  if (::GetKeyState(VK_CONTROL) & 0x8000)
561  ctrlArg = PR_TRUE;
562  if (::GetKeyState(VK_MENU) & 0x8000)
563  altArg = PR_TRUE;
564  if (::GetKeyState(VK_SHIFT) & 0x8000)
565  shiftArg = PR_TRUE;
566 
567  // set the hidden window to foreground so the popup
568  // menu can go away when we lose focus
569  ::SetForegroundWindow(hwnd);
570 
571  POINT clientPos;
572  clientPos.x = mousePos.x;
573  clientPos.y = mousePos.y;
574 
575  nsresult rv;
576  nsCOMPtr<nsIDOMElement> element(do_QueryInterface(eventTarget, &rv));
577  NS_ENSURE_SUCCESS(rv, rv);
578 
579  nsCOMPtr<nsIDOMDocument> document;
580  rv = element->GetOwnerDocument(getter_AddRefs(document));
581  NS_ENSURE_SUCCESS(rv, rv);
582 
583  nsCOMPtr<nsIDOMDocumentEvent>
584  documentEvent(do_QueryInterface(document, &rv));
585  NS_ENSURE_SUCCESS(rv, rv);
586 
587  nsCOMPtr<nsIDOMDocumentView>
588  documentView(do_QueryInterface(document, &rv));
589  NS_ENSURE_SUCCESS(rv, rv);
590 
591  nsCOMPtr<nsIDOMAbstractView> abstractView;
592  rv = documentView->GetDefaultView(getter_AddRefs(abstractView));
593  NS_ENSURE_SUCCESS(rv, rv);
594 
595  PRBool ret = PR_TRUE;
596  nsCOMPtr<nsIDOMEvent> event;
597  if (detail == -1)
598  // not a mouse event
599  rv = CreateEvent(documentEvent, typeArg, getter_AddRefs(event));
600  else
601  rv = CreateMouseEvent(documentEvent, typeArg, abstractView, detail,
602  mousePos.x, mousePos.y, clientPos.x, clientPos.y, ctrlArg, altArg,
603  shiftArg, PR_FALSE, button, getter_AddRefs(event));
604  NS_ENSURE_SUCCESS(rv, rv);
605 
606  rv = eventTarget->DispatchEvent(event, &ret);
607  NS_ENSURE_SUCCESS(rv, rv);
608 
609  if (!syntheticEvent.IsEmpty())
610  {
611  rv = CreateMouseEvent(documentEvent, syntheticEvent, abstractView, detail,
612  mousePos.x, mousePos.y, clientPos.x, clientPos.y, ctrlArg, altArg,
613  shiftArg, PR_FALSE, button, getter_AddRefs(event));
614  NS_ENSURE_SUCCESS(rv, rv);
615 
616  rv = eventTarget->DispatchEvent(event, &ret);
617  NS_ENSURE_SUCCESS(rv, rv);
618  }
619  if (!ret)
620  {
621  // handler called preventDefault, so we're done
622  PostMessage(hwnd, WM_NULL, 0, 0);
623  return FALSE;
624  }
625  }
626 
627  return ::CallWindowProc(
628  DefWindowProc,
629  hwnd,
630  uMsg,
631  wParam,
632  lParam);
633 }
634 
635 nsresult
636 nsSystemTrayService::CreateEvent(nsIDOMDocumentEvent* documentEvent,
637  const nsAString& typeArg,
638  nsIDOMEvent** _retval)
639 {
640  nsresult rv;
641  nsCOMPtr<nsIDOMEvent> event;
642  rv = documentEvent->CreateEvent(NS_LITERAL_STRING("events"),
643  getter_AddRefs(event));
644  NS_ENSURE_SUCCESS(rv, rv);
645 
646  rv = event->InitEvent(typeArg, PR_FALSE, PR_TRUE);
647  NS_ENSURE_SUCCESS(rv, rv);
648 
649  *_retval = event;
650  NS_ADDREF(*_retval);
651  return NS_OK;
652 }
653 
654 nsresult
655 nsSystemTrayService::CreateMouseEvent(nsIDOMDocumentEvent* documentEvent,
656  const nsAString& typeArg,
657  nsIDOMAbstractView* viewArg,
658  PRInt32 detailArg,
659  PRInt32 screenXArg, PRInt32 screenYArg,
660  PRInt32 clientXArg, PRInt32 clientYArg,
661  PRBool ctrlKeyArg, PRBool altKeyArg,
662  PRBool shiftKeyArg, PRBool metaKeyArg,
663  PRUint16 buttonArg,
664  nsIDOMEvent** _retval)
665 {
666  nsresult rv;
667  nsCOMPtr<nsIDOMEvent> event;
668  rv = documentEvent->CreateEvent(NS_LITERAL_STRING("mouseevent"), getter_AddRefs(event));
669  NS_ENSURE_SUCCESS(rv, rv);
670 
671  nsCOMPtr<nsIDOMMouseEvent> mouseEvent(do_QueryInterface(event, &rv));
672  NS_ENSURE_SUCCESS(rv, rv);
673 
674  rv = mouseEvent->InitMouseEvent(typeArg, PR_FALSE, PR_TRUE, viewArg,
675  detailArg, screenXArg, screenYArg, clientXArg, clientYArg, ctrlKeyArg, altKeyArg,
676  shiftKeyArg, metaKeyArg, buttonArg, nsnull);
677  NS_ENSURE_SUCCESS(rv, rv);
678 
679  return CallQueryInterface(mouseEvent, _retval);
680 }
681 
682 nsresult
683 nsSystemTrayService::GetDOMWindow(nsIXULWindow* xulWindow,
684  nsIDOMWindow** _retval)
685 {
686  nsresult rv;
687  nsCOMPtr<nsIDocShell> docShell;
688  rv = xulWindow->GetDocShell(getter_AddRefs(docShell));
689  NS_ENSURE_SUCCESS(rv, rv);
690 
691  nsCOMPtr<nsIInterfaceRequestor> requestor(do_QueryInterface(docShell, &rv));
692  NS_ENSURE_SUCCESS(rv, rv);
693 
694  rv = requestor->GetInterface(NS_GET_IID(nsIDOMWindow), (void **) _retval);
695  NS_ENSURE_SUCCESS(rv, rv);
696 
697  return NS_OK;
698 }
699 
700 /* attribute imgIContainer image; */
701 NS_IMETHODIMP
702 nsSystemTrayService::GetImage(imgIContainer * *aImage)
703 {
704  *aImage = mImage;
705  NS_IF_ADDREF(*aImage);
706  return NS_OK;
707 }
708 
709 NS_IMETHODIMP
710 nsSystemTrayService::SetImage(imgIContainer * aImage)
711 {
712  mImage = aImage;
713  return NS_OK;
714 }
715 
716 /* readonly attribute PRBool isMultiPartChannel; */
717 NS_IMETHODIMP
718 nsSystemTrayService::GetIsMultiPartChannel(PRBool *aIsMultiPartChannel)
719 {
720  *aIsMultiPartChannel = PR_FALSE;
721  return NS_OK;
722 }
723 
724 /* void onStartRequest(in imgIRequest aRequest); */
725 NS_IMETHODIMP
726 nsSystemTrayService::OnStartRequest(imgIRequest* aRequest)
727 {
728  return NS_OK;
729 }
730 
731 /* void onStartDecode (in imgIRequest aRequest); */
732 NS_IMETHODIMP
733 nsSystemTrayService::OnStartDecode(imgIRequest *aRequest)
734 {
735  return NS_OK;
736 }
737 
738 /* void onStartContainer (in imgIRequest aRequest,
739  in imgIContainer aContainer); */
740 NS_IMETHODIMP
741 nsSystemTrayService::OnStartContainer(imgIRequest *aRequest,
742  imgIContainer *aContainer)
743 {
744  return NS_OK;
745 }
746 
747 /* void onStartFrame (in imgIRequest aRequest, in unsigned long aFrame); */
748 NS_IMETHODIMP
749 nsSystemTrayService::OnStartFrame(imgIRequest *aRequest,
750  PRUint32 aFrame)
751 {
752  return NS_OK;
753 }
754 
755 /* [noscript] void onDataAvailable (in imgIRequest aRequest,
756  in boolean aCurrentFrame, [const] in nsIntRect aRect); */
757 NS_IMETHODIMP
758 nsSystemTrayService::OnDataAvailable(imgIRequest *aRequest,
759  PRBool aCurrentFrame,
760  const nsIntRect * aRect)
761 {
762  return NS_OK;
763 }
764 
765 /* void onStopFrame (in imgIRequest aRequest, in unsigned long aFrame); */
766 NS_IMETHODIMP
767 nsSystemTrayService::OnStopFrame(imgIRequest *aRequest,
768  PRUint32 aFrame)
769 {
770  return NS_OK;
771 }
772 
773 /* void onStopContainer (in imgIRequest aRequest,
774  in imgIContainer aContainer); */
775 NS_IMETHODIMP
776 nsSystemTrayService::OnStopContainer(imgIRequest *aRequest,
777  imgIContainer *aContainer)
778 {
779  return NS_OK;
780 }
781 
782 /* void onStopDecode (in imgIRequest aRequest, in nsresult status,
783  in wstring statusArg); */
784 NS_IMETHODIMP
785 nsSystemTrayService::OnStopDecode(imgIRequest *aRequest,
786  nsresult status, const PRUnichar *statusArg)
787 {
788  return NS_OK;
789 }
790 
791 /* void onStopRequest(in imgIRequest aRequest, in boolean aIsLastPart); */
792 NS_IMETHODIMP
793 nsSystemTrayService::OnStopRequest(imgIRequest* aRequest,
794  PRBool aIsLastPart)
795 {
796  return NS_OK;
797 }
798 
799 /* [noscript] void frameChanged (in imgIContainer aContainer,
800  in nsIntRect aDirtyRect); */
801 NS_IMETHODIMP
802 nsSystemTrayService::FrameChanged(imgIContainer *aContainer,
803  nsIntRect * aDirtyRect)
804 {
805  return NS_OK;
806 }
nsCOMPtr< imgIContainer > mImage
return NS_OK
browser docShell
static const TCHAR * S_PROPPROC
nsresult GetIconForWnd(HWND hwnd, HICON &result)
nsresult CreateListenerWindow(HWND *listenerWindow, nsIDOMElement *targetElement)
struct HICON__ * HICON
var event
var ioService
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)
NS_IMPL_ISUPPORTS4(nsSystemTrayService, nsISystemTrayService, imgILoad, imgIContainerObserver, imgIDecoderObserver) nsSystemTrayService
const nsIDOMWindow
nsresult AddTrayIcon(HWND hwnd, nsIURI *iconURI, const nsAString &iconId, nsIDOMElement *targetElement)
GstMessage * message
return ret
static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
nsresult GetDOMWindow(nsIXULWindow *xulWindow, nsIDOMWindow **_retval)
AutoReentryBlocker(PRUint32 *counter)
nsresult GetIconForURI(nsIURI *iconURI, HICON &result)
#define MK_ENSURE_NATIVE(res)
#define WM_TRAYICON
static PRUint32 numberOfCallsIntoWindowProc
static const TCHAR * S_PROPINST
static nsresult CreateEvent(nsIDOMDocumentEvent *documentEvent, const nsAString &typeArg, nsIDOMEvent **_retval)
nsInterfaceHashtable< nsStringHashKey, nsSystemTrayIconGTK > mIconDataMap