nsQueryContentEventResult.cpp (7627B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 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/. */ 6 7 #include "nsQueryContentEventResult.h" 8 9 #include <utility> 10 11 #include "mozilla/TextEvents.h" 12 #include "nsIWidget.h" 13 #include "nsPoint.h" 14 15 using namespace mozilla; 16 17 /****************************************************************************** 18 * Is*PropertyAvailable() methods which check if the property is available 19 * (valid) with the event message. 20 ******************************************************************************/ 21 22 static bool IsNotFoundPropertyAvailable(EventMessage aEventMessage) { 23 return aEventMessage == eQuerySelectedText || 24 aEventMessage == eQueryCharacterAtPoint; 25 } 26 27 static bool IsOffsetPropertyAvailable(EventMessage aEventMessage) { 28 return aEventMessage == eQueryTextContent || 29 aEventMessage == eQueryTextRect || aEventMessage == eQueryCaretRect || 30 IsNotFoundPropertyAvailable(aEventMessage); 31 } 32 33 static bool IsRectRelatedPropertyAvailable(EventMessage aEventMessage) { 34 return aEventMessage == eQueryCaretRect || aEventMessage == eQueryTextRect || 35 aEventMessage == eQueryEditorRect || 36 aEventMessage == eQueryCharacterAtPoint; 37 } 38 39 /****************************************************************************** 40 * nsQueryContentEventResult 41 ******************************************************************************/ 42 43 NS_INTERFACE_MAP_BEGIN(nsQueryContentEventResult) 44 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIQueryContentEventResult) 45 NS_INTERFACE_MAP_ENTRY(nsIQueryContentEventResult) 46 NS_INTERFACE_MAP_END 47 48 NS_IMPL_ADDREF(nsQueryContentEventResult) 49 NS_IMPL_RELEASE(nsQueryContentEventResult) 50 51 nsQueryContentEventResult::nsQueryContentEventResult( 52 mozilla::WidgetQueryContentEvent&& aEvent) 53 : mEventMessage(aEvent.mMessage), 54 mSucceeded(aEvent.Succeeded()), 55 mReversed(false) { 56 if (mSucceeded) { 57 mOffsetAndData = std::move(aEvent.mReply->mOffsetAndData); 58 mTentativeCaretOffset = std::move(aEvent.mReply->mTentativeCaretOffset); 59 mRect = std::move(aEvent.mReply->mRect); 60 mRectArray = std::move(aEvent.mReply->mRectArray); 61 mReversed = aEvent.mReply->mReversed; 62 } 63 // Mark as result that is longer used. 64 aEvent.mReply.reset(); 65 } 66 67 NS_IMETHODIMP 68 nsQueryContentEventResult::GetOffset(uint32_t* aOffset) { 69 if (NS_WARN_IF(!mSucceeded)) { 70 return NS_ERROR_NOT_AVAILABLE; 71 } 72 73 if (NS_WARN_IF(!IsOffsetPropertyAvailable(mEventMessage))) { 74 return NS_ERROR_NOT_AVAILABLE; 75 } 76 77 // With some event message, both offset and notFound properties are available. 78 // In that case, offset value may mean "not found". If so, this method 79 // shouldn't return mOffset as the result because it's a special value for 80 // "not found". 81 if (IsNotFoundPropertyAvailable(mEventMessage)) { 82 bool notFound; 83 nsresult rv = GetNotFound(¬Found); 84 if (NS_WARN_IF(NS_FAILED(rv))) { 85 return rv; // Just an unexpected case... 86 } 87 // As said above, if mOffset means "not found", offset property shouldn't 88 // return its value without any errors. 89 if (NS_WARN_IF(notFound)) { 90 return NS_ERROR_NOT_AVAILABLE; 91 } 92 } 93 94 *aOffset = mOffsetAndData->StartOffset(); 95 return NS_OK; 96 } 97 98 NS_IMETHODIMP 99 nsQueryContentEventResult::GetTentativeCaretOffset(uint32_t* aOffset) { 100 bool notFound; 101 nsresult rv = GetTentativeCaretOffsetNotFound(¬Found); 102 if (NS_WARN_IF(NS_FAILED(rv))) { 103 return rv; 104 } 105 if (NS_WARN_IF(notFound)) { 106 return NS_ERROR_NOT_AVAILABLE; 107 } 108 *aOffset = mTentativeCaretOffset.value(); 109 return NS_OK; 110 } 111 112 NS_IMETHODIMP 113 nsQueryContentEventResult::GetReversed(bool* aReversed) { 114 NS_ENSURE_TRUE(mSucceeded, NS_ERROR_NOT_AVAILABLE); 115 NS_ENSURE_TRUE(mEventMessage == eQuerySelectedText, NS_ERROR_NOT_AVAILABLE); 116 *aReversed = mReversed; 117 return NS_OK; 118 } 119 120 NS_IMETHODIMP 121 nsQueryContentEventResult::GetLeft(int32_t* aLeft) { 122 NS_ENSURE_TRUE(mSucceeded, NS_ERROR_NOT_AVAILABLE); 123 NS_ENSURE_TRUE(IsRectRelatedPropertyAvailable(mEventMessage), 124 NS_ERROR_NOT_AVAILABLE); 125 *aLeft = mRect.x; 126 return NS_OK; 127 } 128 129 NS_IMETHODIMP 130 nsQueryContentEventResult::GetWidth(int32_t* aWidth) { 131 NS_ENSURE_TRUE(mSucceeded, NS_ERROR_NOT_AVAILABLE); 132 NS_ENSURE_TRUE(IsRectRelatedPropertyAvailable(mEventMessage), 133 NS_ERROR_NOT_AVAILABLE); 134 *aWidth = mRect.Width(); 135 return NS_OK; 136 } 137 138 NS_IMETHODIMP 139 nsQueryContentEventResult::GetTop(int32_t* aTop) { 140 NS_ENSURE_TRUE(mSucceeded, NS_ERROR_NOT_AVAILABLE); 141 NS_ENSURE_TRUE(IsRectRelatedPropertyAvailable(mEventMessage), 142 NS_ERROR_NOT_AVAILABLE); 143 *aTop = mRect.y; 144 return NS_OK; 145 } 146 147 NS_IMETHODIMP 148 nsQueryContentEventResult::GetHeight(int32_t* aHeight) { 149 NS_ENSURE_TRUE(mSucceeded, NS_ERROR_NOT_AVAILABLE); 150 NS_ENSURE_TRUE(IsRectRelatedPropertyAvailable(mEventMessage), 151 NS_ERROR_NOT_AVAILABLE); 152 *aHeight = mRect.Height(); 153 return NS_OK; 154 } 155 156 NS_IMETHODIMP 157 nsQueryContentEventResult::GetText(nsAString& aText) { 158 NS_ENSURE_TRUE(mSucceeded, NS_ERROR_NOT_AVAILABLE); 159 NS_ENSURE_TRUE(mEventMessage == eQuerySelectedText || 160 mEventMessage == eQueryTextContent || 161 mEventMessage == eQueryTextRect, 162 NS_ERROR_NOT_AVAILABLE); 163 NS_ENSURE_TRUE(mOffsetAndData.isSome(), NS_ERROR_NOT_AVAILABLE); 164 aText = mOffsetAndData->DataRef(); 165 return NS_OK; 166 } 167 168 NS_IMETHODIMP 169 nsQueryContentEventResult::GetSucceeded(bool* aSucceeded) { 170 NS_ENSURE_TRUE(mEventMessage != eVoidEvent, NS_ERROR_NOT_INITIALIZED); 171 *aSucceeded = mSucceeded; 172 return NS_OK; 173 } 174 175 NS_IMETHODIMP 176 nsQueryContentEventResult::GetNotFound(bool* aNotFound) { 177 if (NS_WARN_IF(!mSucceeded) || 178 NS_WARN_IF(!IsNotFoundPropertyAvailable(mEventMessage))) { 179 return NS_ERROR_NOT_AVAILABLE; 180 } 181 *aNotFound = mOffsetAndData.isNothing(); 182 return NS_OK; 183 } 184 185 NS_IMETHODIMP 186 nsQueryContentEventResult::GetTentativeCaretOffsetNotFound(bool* aNotFound) { 187 if (NS_WARN_IF(!mSucceeded)) { 188 return NS_ERROR_NOT_AVAILABLE; 189 } 190 if (NS_WARN_IF(mEventMessage != eQueryCharacterAtPoint)) { 191 return NS_ERROR_NOT_AVAILABLE; 192 } 193 *aNotFound = mTentativeCaretOffset.isNothing(); 194 return NS_OK; 195 } 196 197 NS_IMETHODIMP 198 nsQueryContentEventResult::GetCharacterRect(int32_t aOffset, int32_t* aLeft, 199 int32_t* aTop, int32_t* aWidth, 200 int32_t* aHeight) { 201 NS_ENSURE_TRUE(mSucceeded, NS_ERROR_NOT_AVAILABLE); 202 NS_ENSURE_TRUE(mEventMessage == eQueryTextRectArray, NS_ERROR_NOT_AVAILABLE); 203 204 if (NS_WARN_IF(mRectArray.Length() <= static_cast<size_t>(aOffset))) { 205 return NS_ERROR_FAILURE; 206 } 207 208 *aLeft = mRectArray[aOffset].x; 209 *aTop = mRectArray[aOffset].y; 210 *aWidth = mRectArray[aOffset].Width(); 211 *aHeight = mRectArray[aOffset].Height(); 212 213 return NS_OK; 214 } 215 216 void nsQueryContentEventResult::SetEventResult(nsIWidget* aWidget) { 217 if (!IsRectRelatedPropertyAvailable(mEventMessage) || !aWidget || 218 !mSucceeded) { 219 return; 220 } 221 222 nsIWidget* topWidget = aWidget->GetTopLevelWidget(); 223 if (!topWidget || topWidget == aWidget) { 224 return; 225 } 226 227 // Convert the top widget related coordinates to the given widget's. 228 LayoutDeviceIntPoint offset = 229 aWidget->WidgetToScreenOffset() - topWidget->WidgetToScreenOffset(); 230 mRect.MoveBy(-offset); 231 for (size_t i = 0; i < mRectArray.Length(); i++) { 232 mRectArray[i].MoveBy(-offset); 233 } 234 }