1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "WindowHook.h"
9 #include "nsWindowDefs.h"
14 nsresult
WindowHook::AddHook(UINT nMsg
, Callback callback
, void* context
) {
15 MessageData
* data
= LookupOrCreate(nMsg
);
17 if (!data
) return NS_ERROR_OUT_OF_MEMORY
;
19 // Ensure we don't overwrite another hook
20 NS_ENSURE_TRUE(nullptr == data
->hook
.cb
, NS_ERROR_UNEXPECTED
);
22 data
->hook
= CallbackData(callback
, context
);
27 nsresult
WindowHook::RemoveHook(UINT nMsg
, Callback callback
, void* context
) {
28 CallbackData
cbdata(callback
, context
);
29 MessageData
* data
= Lookup(nMsg
);
30 if (!data
) return NS_ERROR_UNEXPECTED
;
31 if (data
->hook
!= cbdata
) return NS_ERROR_UNEXPECTED
;
32 data
->hook
= CallbackData();
38 nsresult
WindowHook::AddMonitor(UINT nMsg
, Callback callback
, void* context
) {
39 MessageData
* data
= LookupOrCreate(nMsg
);
40 return (data
&& data
->monitors
.AppendElement(CallbackData(callback
, context
),
43 : NS_ERROR_OUT_OF_MEMORY
;
46 nsresult
WindowHook::RemoveMonitor(UINT nMsg
, Callback callback
,
48 CallbackData
cbdata(callback
, context
);
49 MessageData
* data
= Lookup(nMsg
);
50 if (!data
) return NS_ERROR_UNEXPECTED
;
51 CallbackDataArray::index_type idx
= data
->monitors
.IndexOf(cbdata
);
52 if (idx
== CallbackDataArray::NoIndex
) return NS_ERROR_UNEXPECTED
;
53 data
->monitors
.RemoveElementAt(idx
);
58 WindowHook::MessageData
* WindowHook::Lookup(UINT nMsg
) {
59 MessageDataArray::index_type idx
;
60 for (idx
= 0; idx
< mMessageData
.Length(); idx
++) {
61 MessageData
& data
= mMessageData
[idx
];
62 if (data
.nMsg
== nMsg
) return &data
;
67 WindowHook::MessageData
* WindowHook::LookupOrCreate(UINT nMsg
) {
68 MessageData
* data
= Lookup(nMsg
);
70 data
= mMessageData
.AppendElement();
72 if (!data
) return nullptr;
79 void WindowHook::DeleteIfEmpty(MessageData
* data
) {
80 // Never remove a MessageData that has still a hook or monitor entries.
81 if (data
->hook
|| !data
->monitors
.IsEmpty()) return;
83 MessageDataArray::index_type idx
;
84 idx
= data
- mMessageData
.Elements();
86 idx
< mMessageData
.Length(),
87 "Attempted to delete MessageData that doesn't belong to this array!");
88 mMessageData
.RemoveElementAt(idx
);
91 bool WindowHook::Notify(HWND hWnd
, UINT nMsg
, WPARAM wParam
, LPARAM lParam
,
93 MessageData
* data
= Lookup(nMsg
);
94 if (!data
) return false;
96 uint32_t length
= data
->monitors
.Length();
97 for (uint32_t midx
= 0; midx
< length
; midx
++) {
98 data
->monitors
[midx
].Invoke(hWnd
, nMsg
, wParam
, lParam
, &aResult
.mResult
);
102 data
->hook
.Invoke(hWnd
, nMsg
, wParam
, lParam
, &aResult
.mResult
);
103 return aResult
.mConsumed
;
106 bool WindowHook::CallbackData::Invoke(HWND hWnd
, UINT msg
, WPARAM wParam
,
107 LPARAM lParam
, LRESULT
* aResult
) {
108 if (!cb
) return false;
109 return cb(context
, hWnd
, msg
, wParam
, lParam
, aResult
);
112 } // namespace widget
113 } // namespace mozilla