nsWindowUtilWin.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  *
26  * Alternatively, the contents of this file may be used under the terms of
27  * either the GNU General Public License Version 2 or later (the "GPL"), or
28  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29  * in which case the provisions of the GPL or the LGPL are applicable instead
30  * of those above. If you wish to allow use of your version of this file only
31  * under the terms of either the GPL or the LGPL, and not to allow others to
32  * use your version of this file under the terms of the MPL, indicate your
33  * decision by deleting the provisions above and replace them with the notice
34  * and other provisions required by the GPL or the LGPL. If you do not delete
35  * the provisions above, a recipient may use your version of this file under
36  * the terms of any one of the MPL, the GPL or the LGPL.
37  *
38  * ***** END LICENSE BLOCK ***** */
39 
40 #include "nsWindowUtilWin.h"
41 #include "nsStringGlue.h"
42 #include "nsIBaseWindow.h"
43 #include "nsIDocShell.h"
44 #include "nsIDocShellTreeItem.h"
45 #include "nsIDocShellTreeOwner.h"
46 #include "nsIDOMAbstractView.h"
47 #include "nsIDOMDocument.h"
48 #include "nsIDOMDocumentEvent.h"
49 #include "nsIDOMDocumentView.h"
50 #include "nsIDOMEventTarget.h"
51 #include "nsIDOMMouseEvent.h"
52 #include "nsIDOMWindow.h"
53 #include "nsIInterfaceRequestor.h"
54 #include "nsIWebNavigation.h"
55 #include "nsIXULWindow.h"
56 
57 #define S_PROPINST TEXT("_NS_WINDOWUTIL_INST")
58 #define S_PROPPROC TEXT("_NS_WINDOWUTIL_PROC")
59 
60 #define MK_ENSURE_NATIVE(res) \
61  PR_BEGIN_MACRO \
62  NS_ENSURE_TRUE(0 != res || 0 == ::GetLastError(), \
63  ::GetLastError() + MK_ERROR_OFFSET); \
64  PR_END_MACRO
65 
66 #define MK_ERROR_OFFSET (0xD0000000 + (__LINE__ * 0x10000))
67 
69 
71 {
72  mOldProc = NULL;
73 }
74 
75 nsWindowUtil::~nsWindowUtil()
76 {
77  if (mOldProc)
78  {
79  ::RemoveProp(this->mWnd, S_PROPINST);
80  ::SetProp(this->mWnd, S_PROPPROC, (HANDLE)this->mOldProc);
81  }
82 }
83 
84 /* void init (in nsIDOMWindow win); */
85 NS_IMETHODIMP
87 {
88  nsresult rv;
89  mDOMWindow = win;
90 
91  nsCOMPtr<nsIDocShell> docShell;
92  rv = GetDocShell(getter_AddRefs(docShell));
93  NS_ENSURE_SUCCESS(rv, rv);
94 
95  nsCOMPtr<nsIBaseWindow> baseWindow(do_QueryInterface(docShell, &rv));
96  NS_ENSURE_SUCCESS(rv, rv);
97 
98  nativeWindow theNativeWindow;
99  rv = baseWindow->GetParentNativeWindow( &theNativeWindow );
100  NS_ENSURE_SUCCESS(rv, rv);
101 
102  mWnd = reinterpret_cast<HWND>(theNativeWindow);
103  NS_ENSURE_TRUE(mWnd, NS_ERROR_UNEXPECTED);
104 
105  return NS_OK;
106 }
107 
108 /* readonly attribute nsIXULWindow xulWindow */
109 NS_IMETHODIMP
110 nsWindowUtil::GetXulWindow(nsIXULWindow **_retval)
111 {
112  NS_ENSURE_STATE(mDOMWindow);
113 
114  nsresult rv;
115  nsCOMPtr<nsIInterfaceRequestor>
116  requestor(do_QueryInterface(mDOMWindow, &rv));
117  NS_ENSURE_SUCCESS(rv, rv);
118 
119  nsCOMPtr<nsIWebNavigation> nav;
120  rv = requestor->GetInterface(NS_GET_IID(nsIWebNavigation),
121  getter_AddRefs(nav));
122  NS_ENSURE_SUCCESS(rv, rv);
123 
124  nsCOMPtr<nsIDocShellTreeItem> treeItem(do_QueryInterface(nav, &rv));
125  NS_ENSURE_SUCCESS(rv, rv);
126 
127  nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
128  rv = treeItem->GetTreeOwner(getter_AddRefs(treeOwner));
129  NS_ENSURE_SUCCESS(rv, rv);
130 
131  requestor = do_QueryInterface(treeOwner, &rv);
132  NS_ENSURE_SUCCESS(rv, rv);
133 
134  return requestor->GetInterface(NS_GET_IID(nsIXULWindow), (void **) _retval);
135 }
136 
137 /* readonly attribute nsIDocShell docShell */
138 NS_IMETHODIMP
139 nsWindowUtil::GetDocShell(nsIDocShell **_retval)
140 {
141  nsresult rv;
142  nsCOMPtr<nsIXULWindow> xulWindow;
143  rv = GetXulWindow(getter_AddRefs(xulWindow));
144  NS_ENSURE_SUCCESS(rv, rv);
145 
146  return xulWindow->GetDocShell(_retval);
147 }
148 
149 /* void minimize(); */
150 NS_IMETHODIMP
151 nsWindowUtil::Minimize()
152 {
153  ::ShowWindow(mWnd, SW_MINIMIZE);
154  return NS_OK;
155 }
156 
157 /* readonly attribute boolean hidden; */
158 NS_IMETHODIMP
159 nsWindowUtil::GetHidden(PRBool* _retval)
160 {
161  NS_ENSURE_STATE(mWnd);
162 
163  if (::IsWindowVisible(mWnd))
164  *_retval = PR_FALSE;
165  else
166  *_retval = PR_TRUE;
167 
168  return NS_OK;
169 }
170 
171 /* void watch() */
172 NS_IMETHODIMP
173 nsWindowUtil::Watch()
174 {
175  NS_ENSURE_STATE(mWnd);
176 
177  // subclass the window (need to intercept WM_TRAYICON)
178  ::SetLastError(0);
179 
180  if (::GetProp(mWnd, S_PROPINST))
181  return NS_ERROR_ALREADY_INITIALIZED;
182  MK_ENSURE_NATIVE(::SetProp(mWnd, S_PROPINST, (HANDLE)this));
183  mOldProc = (WNDPROC)::GetWindowLongPtr(mWnd, GWLP_WNDPROC);
184  ::SetLastError(0);
185  MK_ENSURE_NATIVE(::SetWindowLongPtr(
186  mWnd,
187  GWLP_WNDPROC,
188  (LONG_PTR)nsWindowUtil::WindowProc
189  ));
190 
191  return NS_OK;
192 }
193 
194 NS_IMETHODIMP
195 nsWindowUtil::Unwatch()
196 {
197  return NS_ERROR_NOT_IMPLEMENTED;
198 }
199 
200 LRESULT CALLBACK
202  UINT uMsg,
203  WPARAM wParam,
204  LPARAM lParam)
205 {
206  bool handled = true;
207  WNDPROC proc;
208  nsWindowUtil* self =
209  (nsWindowUtil*)GetProp(hwnd, S_PROPINST);
210 
211  if (self && self->mOldProc && self->mDOMWindow) {
212  proc = self->mOldProc;
213  } else {
214  // property not found - we don't exist anymore
215  // use the original window proc
216  proc = (WNDPROC)GetProp(hwnd, S_PROPPROC);
217  if (!proc)
218  // can't find the right process... skip over to the default
219  // (this will, at the minimum, totally break the app)
220  proc = DefWindowProc;
221  handled = false;
222  }
223 
224  /*
225  * For this next section, including all the switches, we are simply
226  * collecting messages we feel are important to collect. Once we collect
227  * all the windows messages that may be important to us, then these messages
228  * are dispatched as DOM events to the window.
229  */
230 
231  nsAutoString typeArg;
232 
233  POINT clientPos = { 0, 0};
234  POINT screenPos = { 0, 0};
235 
236  if (handled) {
237  switch (uMsg) {
238  case WM_NCLBUTTONDOWN:
239  switch(wParam) {
240  // these are the min, max, and close buttons for
241  case HTMINBUTTON:
242  typeArg = NS_LITERAL_STRING("minimizing");
243  break;
244  case HTMAXBUTTON:
245  typeArg = NS_LITERAL_STRING("maximizing");
246  break;
247  case HTCLOSE:
248  typeArg = NS_LITERAL_STRING("closing");
249  break;
250  default:
251  handled = false;
252  }
253  clientPos.x = screenPos.x = LOWORD(lParam);
254  clientPos.y = screenPos.y = LOWORD(lParam);
255  ::ClientToScreen(hwnd, &screenPos);
256  break;
257  case WM_ACTIVATE:
258  switch (LOWORD(wParam)) {
259  case WA_ACTIVE:
260  case WA_CLICKACTIVE:
261  // window is being activated
262  typeArg = NS_LITERAL_STRING("activating");
263  break;
264  default:
265  handled = false;
266  }
267  break;
268  case WM_SIZE:
269  switch (wParam) {
270  case SIZE_MINIMIZED:
271  typeArg = NS_LITERAL_STRING("minimizing");
272  break;
273  default:
274  // for some reason this message is received with wParam ==
275  // SIZE_MAXIMIZED when the browser is shutting down, and calling
276  // Restore() results in the maximized window being "restored"
277  // (returned to non-maximized) size. This size is preserved
278  // after restarting, which is annoying, so I'm commenting it out
279  // until someone can prove that this is actually useful.
280  //
281  // we're resizing, but not minimized, so some part must be visible
282  //typeArg = NS_LITERAL_STRING("activating");
283  break;
284  }
285  break;
286  case WM_SYSCOMMAND:
287  switch (wParam) {
288  case SC_CLOSE:
289  //The user has clicked on the top left window icon and selected close...
290  //Or the user typed Alt+F4.
291  typeArg = NS_LITERAL_STRING("closing");
292  break;
293  default:
294  handled = false;
295  }
296  break;
297  default:
298  handled = false;
299  break;
300  }
301  }
302 
303  PRBool ctrlArg = PR_FALSE;
304  PRBool altArg = PR_FALSE;
305  PRBool shiftArg = PR_FALSE;
306 
307  if (handled) {
308  // check modifier key states
309  if (::GetKeyState(VK_CONTROL) & 0x8000)
310  ctrlArg = PR_TRUE;
311  if (::GetKeyState(VK_MENU) & 0x8000)
312  altArg = PR_TRUE;
313  if (::GetKeyState(VK_SHIFT) & 0x8000)
314  shiftArg = PR_TRUE;
315 
316  // dispatch the event
317  PRBool ret = TRUE;
318  nsresult rv;
319 
320  nsCOMPtr<nsIDOMEventTarget> eventTarget(do_QueryInterface(self->mDOMWindow, &rv));
321  NS_ENSURE_SUCCESS(rv, rv);
322 
323  nsCOMPtr<nsIDOMDocument> document;
324  rv = self->mDOMWindow->GetDocument(getter_AddRefs(document));
325  NS_ENSURE_SUCCESS(rv, rv);
326 
327  nsCOMPtr<nsIDOMDocumentEvent> documentEvent(do_QueryInterface(document, &rv));
328  NS_ENSURE_SUCCESS(rv, rv);
329 
330  nsCOMPtr<nsIDOMDocumentView> documentView(do_QueryInterface(document, &rv));
331  NS_ENSURE_SUCCESS(rv, rv);
332 
333  nsCOMPtr<nsIDOMAbstractView> abstractView;
334  rv = documentView->GetDefaultView(getter_AddRefs(abstractView));
335  NS_ENSURE_SUCCESS(rv, rv);
336 
337  nsCOMPtr<nsIDOMEvent> event;
338  rv = documentEvent->CreateEvent(NS_LITERAL_STRING("mouseevent"), getter_AddRefs(event));
339  NS_ENSURE_SUCCESS(rv, rv);
340 
341  nsCOMPtr<nsIDOMMouseEvent> mouseEvent(do_QueryInterface(event, &rv));
342  NS_ENSURE_SUCCESS(rv, rv);
343 
344  rv = mouseEvent->InitMouseEvent(typeArg, PR_TRUE, PR_TRUE, abstractView,
345  1, screenPos.x, screenPos.y, clientPos.x, clientPos.y, ctrlArg, altArg,
346  shiftArg, PR_FALSE, 0, nsnull);
347  NS_ENSURE_SUCCESS(rv, rv);
348 
349  rv = eventTarget->DispatchEvent(mouseEvent, &ret);
350  NS_ENSURE_SUCCESS(rv, rv);
351 
352  if (!ret)
353  // event was hooked
354  return FALSE;
355  }
356 
357  return CallWindowProc(proc, hwnd, uMsg, wParam, lParam);
358 }
return NS_OK
readonly attribute nsIXULWindow xulWindow
readonly attribute nsIDocShell docShell
NS_IMPL_ISUPPORTS1(sbDeviceCapabilitiesUtils, sbIDeviceCapabilitiesUtils) sbDeviceCapabilitiesUtils
var event
const nsIDOMWindow
const nsIWebNavigation
Definition: browser.js:71
#define MK_ENSURE_NATIVE(res)
#define S_PROPPROC
function Init()
WNDPROC mOldProc
return ret
var self
static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
nsCOMPtr< nsIDOMWindow > mDOMWindow
#define S_PROPINST