widget/windows/WindowHook.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
michael@0 2 *
michael@0 3 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #include "WindowHook.h"
michael@0 8 #include "nsWindow.h"
michael@0 9 #include "nsWindowDefs.h"
michael@0 10
michael@0 11 namespace mozilla {
michael@0 12 namespace widget {
michael@0 13
michael@0 14 nsresult
michael@0 15 WindowHook::AddHook(UINT nMsg, Callback callback, void *context) {
michael@0 16 MessageData *data = LookupOrCreate(nMsg);
michael@0 17
michael@0 18 if (!data)
michael@0 19 return NS_ERROR_OUT_OF_MEMORY;
michael@0 20
michael@0 21 // Ensure we don't overwrite another hook
michael@0 22 NS_ENSURE_TRUE(nullptr == data->hook.cb, NS_ERROR_UNEXPECTED);
michael@0 23
michael@0 24 data->hook = CallbackData(callback, context);
michael@0 25
michael@0 26 return NS_OK;
michael@0 27 }
michael@0 28
michael@0 29 nsresult
michael@0 30 WindowHook::RemoveHook(UINT nMsg, Callback callback, void *context) {
michael@0 31 CallbackData cbdata(callback, context);
michael@0 32 MessageData *data = Lookup(nMsg);
michael@0 33 if (!data)
michael@0 34 return NS_ERROR_UNEXPECTED;
michael@0 35 if (data->hook != cbdata)
michael@0 36 return NS_ERROR_UNEXPECTED;
michael@0 37 data->hook = CallbackData();
michael@0 38
michael@0 39 DeleteIfEmpty(data);
michael@0 40 return NS_OK;
michael@0 41 }
michael@0 42
michael@0 43 nsresult
michael@0 44 WindowHook::AddMonitor(UINT nMsg, Callback callback, void *context) {
michael@0 45 MessageData *data = LookupOrCreate(nMsg);
michael@0 46 return (data && data->monitors.AppendElement(CallbackData(callback, context)))
michael@0 47 ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
michael@0 48 }
michael@0 49
michael@0 50 nsresult
michael@0 51 WindowHook::RemoveMonitor(UINT nMsg, Callback callback, void *context) {
michael@0 52 CallbackData cbdata(callback, context);
michael@0 53 MessageData *data = Lookup(nMsg);
michael@0 54 if (!data)
michael@0 55 return NS_ERROR_UNEXPECTED;
michael@0 56 CallbackDataArray::index_type idx = data->monitors.IndexOf(cbdata);
michael@0 57 if (idx == CallbackDataArray::NoIndex)
michael@0 58 return NS_ERROR_UNEXPECTED;
michael@0 59 data->monitors.RemoveElementAt(idx);
michael@0 60 DeleteIfEmpty(data);
michael@0 61 return NS_OK;
michael@0 62 }
michael@0 63
michael@0 64 WindowHook::MessageData *
michael@0 65 WindowHook::Lookup(UINT nMsg) {
michael@0 66 MessageDataArray::index_type idx;
michael@0 67 for (idx = 0; idx < mMessageData.Length(); idx++) {
michael@0 68 MessageData &data = mMessageData[idx];
michael@0 69 if (data.nMsg == nMsg)
michael@0 70 return &data;
michael@0 71 }
michael@0 72 return nullptr;
michael@0 73 }
michael@0 74
michael@0 75 WindowHook::MessageData *
michael@0 76 WindowHook::LookupOrCreate(UINT nMsg) {
michael@0 77 MessageData *data = Lookup(nMsg);
michael@0 78 if (!data) {
michael@0 79 data = mMessageData.AppendElement();
michael@0 80
michael@0 81 if (!data)
michael@0 82 return nullptr;
michael@0 83
michael@0 84 data->nMsg = nMsg;
michael@0 85 }
michael@0 86 return data;
michael@0 87 }
michael@0 88
michael@0 89 void
michael@0 90 WindowHook::DeleteIfEmpty(MessageData *data) {
michael@0 91 // Never remove a MessageData that has still a hook or monitor entries.
michael@0 92 if (data->hook || !data->monitors.IsEmpty())
michael@0 93 return;
michael@0 94
michael@0 95 MessageDataArray::index_type idx;
michael@0 96 idx = data - mMessageData.Elements();
michael@0 97 NS_ASSERTION(idx >= 0 && idx < mMessageData.Length(), "Attempted to delete MessageData that doesn't belong to this array!");
michael@0 98 mMessageData.RemoveElementAt(idx);
michael@0 99 }
michael@0 100
michael@0 101 bool
michael@0 102 WindowHook::Notify(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam,
michael@0 103 MSGResult& aResult)
michael@0 104 {
michael@0 105 MessageData *data = Lookup(nMsg);
michael@0 106 if (!data)
michael@0 107 return false;
michael@0 108
michael@0 109 uint32_t length = data->monitors.Length();
michael@0 110 for (uint32_t midx = 0; midx < length; midx++) {
michael@0 111 data->monitors[midx].Invoke(hWnd, nMsg, wParam, lParam, &aResult.mResult);
michael@0 112 }
michael@0 113
michael@0 114 aResult.mConsumed =
michael@0 115 data->hook.Invoke(hWnd, nMsg, wParam, lParam, &aResult.mResult);
michael@0 116 return aResult.mConsumed;
michael@0 117 }
michael@0 118
michael@0 119 bool
michael@0 120 WindowHook::CallbackData::Invoke(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam,
michael@0 121 LRESULT *aResult) {
michael@0 122 if (!cb)
michael@0 123 return false;
michael@0 124 return cb(context, hWnd, msg, wParam, lParam, aResult);
michael@0 125 }
michael@0 126 } // namespace widget
michael@0 127 } // namespace mozilla
michael@0 128

mercurial