CLOSED TREE: TraceMonkey merge head. (a=blockers)
[mozilla-central.git] / widget / src / windows / WindowHook.cpp
blobd60251312299a142d916a3aefe73c18bfa08364d
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
3 * ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
14 * License.
16 * The Original Code is mozilla.org code.
18 * The Initial Developer of the Original Code is
19 * Mozilla Foundation
20 * Portions created by the Initial Developer are Copyright (C) 2009
21 * the Initial Developer. All Rights Reserved.
23 * Contributor(s):
24 * Rob Arnold <tellrob@gmail.com>
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.
38 * ***** END LICENSE BLOCK ***** */
40 #include "WindowHook.h"
41 #include "nsWindow.h"
43 namespace mozilla {
44 namespace widget {
46 nsresult
47 WindowHook::AddHook(UINT nMsg, Callback callback, void *context) {
48 MessageData *data = LookupOrCreate(nMsg);
50 if (!data)
51 return NS_ERROR_OUT_OF_MEMORY;
53 // Ensure we don't overwrite another hook
54 NS_ENSURE_TRUE(nsnull == data->hook.cb, NS_ERROR_UNEXPECTED);
56 data->hook = CallbackData(callback, context);
58 return NS_OK;
61 nsresult
62 WindowHook::RemoveHook(UINT nMsg, Callback callback, void *context) {
63 CallbackData cbdata(callback, context);
64 MessageData *data = Lookup(nMsg);
65 if (!data)
66 return NS_ERROR_UNEXPECTED;
67 if (data->hook != cbdata)
68 return NS_ERROR_UNEXPECTED;
69 data->hook = CallbackData();
71 DeleteIfEmpty(data);
72 return NS_OK;
75 nsresult
76 WindowHook::AddMonitor(UINT nMsg, Callback callback, void *context) {
77 MessageData *data = LookupOrCreate(nMsg);
78 return (data && data->monitors.AppendElement(CallbackData(callback, context)))
79 ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
82 nsresult
83 WindowHook::RemoveMonitor(UINT nMsg, Callback callback, void *context) {
84 CallbackData cbdata(callback, context);
85 MessageData *data = Lookup(nMsg);
86 if (!data)
87 return NS_ERROR_UNEXPECTED;
88 CallbackDataArray::index_type idx = data->monitors.IndexOf(cbdata);
89 if (idx == CallbackDataArray::NoIndex)
90 return NS_ERROR_UNEXPECTED;
91 data->monitors.RemoveElementAt(idx);
92 DeleteIfEmpty(data);
93 return NS_OK;
96 WindowHook::MessageData *
97 WindowHook::Lookup(UINT nMsg) {
98 MessageDataArray::index_type idx;
99 for (idx = 0; idx < mMessageData.Length(); idx++) {
100 MessageData &data = mMessageData[idx];
101 if (data.nMsg == nMsg)
102 return &data;
104 return nsnull;
107 WindowHook::MessageData *
108 WindowHook::LookupOrCreate(UINT nMsg) {
109 MessageData *data = Lookup(nMsg);
110 if (!data) {
111 data = mMessageData.AppendElement();
113 if (!data)
114 return nsnull;
116 data->nMsg = nMsg;
118 return data;
121 void
122 WindowHook::DeleteIfEmpty(MessageData *data) {
123 // Never remove a MessageData that has still a hook or monitor entries.
124 if (data->hook || !data->monitors.IsEmpty())
125 return;
127 MessageDataArray::index_type idx;
128 idx = data - mMessageData.Elements();
129 NS_ASSERTION(idx >= 0 && idx < mMessageData.Length(), "Attempted to delete MessageData that doesn't belong to this array!");
130 mMessageData.RemoveElementAt(idx);
133 PRBool
134 WindowHook::Notify(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam,
135 LRESULT *aResult) {
136 MessageData *data = Lookup(nMsg);
137 if (!data)
138 return PR_FALSE;
140 PRUint32 length = data->monitors.Length();
141 for (PRUint32 midx = 0; midx < length; midx++) {
142 data->monitors[midx].Invoke(hWnd, nMsg, wParam, lParam, aResult);
145 return data->hook.Invoke(hWnd, nMsg, wParam, lParam, aResult);
148 PRBool
149 WindowHook::CallbackData::Invoke(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam,
150 LRESULT *aResult) {
151 if (!cb)
152 return PR_FALSE;
153 return cb(context, hWnd, msg, wParam, lParam, aResult);
155 } // namespace widget
156 } // namespace mozilla