1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/accessible/src/base/nsCoreUtils.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,650 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "nsCoreUtils.h" 1.10 + 1.11 +#include "nsIAccessibleTypes.h" 1.12 + 1.13 +#include "nsIBaseWindow.h" 1.14 +#include "nsIDocShellTreeOwner.h" 1.15 +#include "nsIDocument.h" 1.16 +#include "nsIDOMHTMLDocument.h" 1.17 +#include "nsIDOMHTMLElement.h" 1.18 +#include "nsRange.h" 1.19 +#include "nsIBoxObject.h" 1.20 +#include "nsIDOMXULElement.h" 1.21 +#include "nsIDocShell.h" 1.22 +#include "nsIPresShell.h" 1.23 +#include "nsPresContext.h" 1.24 +#include "nsIScrollableFrame.h" 1.25 +#include "nsISelectionPrivate.h" 1.26 +#include "nsISelectionController.h" 1.27 +#include "mozilla/dom/TouchEvent.h" 1.28 +#include "mozilla/EventListenerManager.h" 1.29 +#include "mozilla/EventStateManager.h" 1.30 +#include "mozilla/MouseEvents.h" 1.31 +#include "mozilla/TouchEvents.h" 1.32 +#include "nsView.h" 1.33 +#include "nsGkAtoms.h" 1.34 + 1.35 +#include "nsComponentManagerUtils.h" 1.36 + 1.37 +#include "nsITreeBoxObject.h" 1.38 +#include "nsITreeColumns.h" 1.39 +#include "mozilla/dom/Element.h" 1.40 + 1.41 +using namespace mozilla; 1.42 + 1.43 +//////////////////////////////////////////////////////////////////////////////// 1.44 +// nsCoreUtils 1.45 +//////////////////////////////////////////////////////////////////////////////// 1.46 + 1.47 +bool 1.48 +nsCoreUtils::HasClickListener(nsIContent *aContent) 1.49 +{ 1.50 + NS_ENSURE_TRUE(aContent, false); 1.51 + EventListenerManager* listenerManager = 1.52 + aContent->GetExistingListenerManager(); 1.53 + 1.54 + return listenerManager && 1.55 + (listenerManager->HasListenersFor(nsGkAtoms::onclick) || 1.56 + listenerManager->HasListenersFor(nsGkAtoms::onmousedown) || 1.57 + listenerManager->HasListenersFor(nsGkAtoms::onmouseup)); 1.58 +} 1.59 + 1.60 +void 1.61 +nsCoreUtils::DispatchClickEvent(nsITreeBoxObject *aTreeBoxObj, 1.62 + int32_t aRowIndex, nsITreeColumn *aColumn, 1.63 + const nsCString& aPseudoElt) 1.64 +{ 1.65 + nsCOMPtr<nsIDOMElement> tcElm; 1.66 + aTreeBoxObj->GetTreeBody(getter_AddRefs(tcElm)); 1.67 + if (!tcElm) 1.68 + return; 1.69 + 1.70 + nsCOMPtr<nsIContent> tcContent(do_QueryInterface(tcElm)); 1.71 + nsIDocument *document = tcContent->GetCurrentDoc(); 1.72 + if (!document) 1.73 + return; 1.74 + 1.75 + nsCOMPtr<nsIPresShell> presShell = document->GetShell(); 1.76 + if (!presShell) 1.77 + return; 1.78 + 1.79 + // Ensure row is visible. 1.80 + aTreeBoxObj->EnsureRowIsVisible(aRowIndex); 1.81 + 1.82 + // Calculate x and y coordinates. 1.83 + int32_t x = 0, y = 0, width = 0, height = 0; 1.84 + nsresult rv = aTreeBoxObj->GetCoordsForCellItem(aRowIndex, aColumn, 1.85 + aPseudoElt, 1.86 + &x, &y, &width, &height); 1.87 + if (NS_FAILED(rv)) 1.88 + return; 1.89 + 1.90 + nsCOMPtr<nsIDOMXULElement> tcXULElm(do_QueryInterface(tcElm)); 1.91 + nsCOMPtr<nsIBoxObject> tcBoxObj; 1.92 + tcXULElm->GetBoxObject(getter_AddRefs(tcBoxObj)); 1.93 + 1.94 + int32_t tcX = 0; 1.95 + tcBoxObj->GetX(&tcX); 1.96 + 1.97 + int32_t tcY = 0; 1.98 + tcBoxObj->GetY(&tcY); 1.99 + 1.100 + // Dispatch mouse events. 1.101 + nsWeakFrame tcFrame = tcContent->GetPrimaryFrame(); 1.102 + nsIFrame* rootFrame = presShell->GetRootFrame(); 1.103 + 1.104 + nsPoint offset; 1.105 + nsIWidget *rootWidget = 1.106 + rootFrame->GetViewExternal()->GetNearestWidget(&offset); 1.107 + 1.108 + nsRefPtr<nsPresContext> presContext = presShell->GetPresContext(); 1.109 + 1.110 + int32_t cnvdX = presContext->CSSPixelsToDevPixels(tcX + x + 1) + 1.111 + presContext->AppUnitsToDevPixels(offset.x); 1.112 + int32_t cnvdY = presContext->CSSPixelsToDevPixels(tcY + y + 1) + 1.113 + presContext->AppUnitsToDevPixels(offset.y); 1.114 + 1.115 + // XUL is just desktop, so there is no real reason for senfing touch events. 1.116 + DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN, cnvdX, cnvdY, 1.117 + tcContent, tcFrame, presShell, rootWidget); 1.118 + 1.119 + DispatchMouseEvent(NS_MOUSE_BUTTON_UP, cnvdX, cnvdY, 1.120 + tcContent, tcFrame, presShell, rootWidget); 1.121 +} 1.122 + 1.123 +void 1.124 +nsCoreUtils::DispatchMouseEvent(uint32_t aEventType, int32_t aX, int32_t aY, 1.125 + nsIContent *aContent, nsIFrame *aFrame, 1.126 + nsIPresShell *aPresShell, nsIWidget *aRootWidget) 1.127 +{ 1.128 + WidgetMouseEvent event(true, aEventType, aRootWidget, 1.129 + WidgetMouseEvent::eReal, WidgetMouseEvent::eNormal); 1.130 + 1.131 + event.refPoint = LayoutDeviceIntPoint(aX, aY); 1.132 + 1.133 + event.clickCount = 1; 1.134 + event.button = WidgetMouseEvent::eLeftButton; 1.135 + event.time = PR_IntervalNow(); 1.136 + event.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN; 1.137 + 1.138 + nsEventStatus status = nsEventStatus_eIgnore; 1.139 + aPresShell->HandleEventWithTarget(&event, aFrame, aContent, &status); 1.140 +} 1.141 + 1.142 +void 1.143 +nsCoreUtils::DispatchTouchEvent(uint32_t aEventType, int32_t aX, int32_t aY, 1.144 + nsIContent* aContent, nsIFrame* aFrame, 1.145 + nsIPresShell* aPresShell, nsIWidget* aRootWidget) 1.146 +{ 1.147 + if (!dom::TouchEvent::PrefEnabled()) 1.148 + return; 1.149 + 1.150 + WidgetTouchEvent event(true, aEventType, aRootWidget); 1.151 + 1.152 + event.time = PR_IntervalNow(); 1.153 + 1.154 + // XXX: Touch has an identifier of -1 to hint that it is synthesized. 1.155 + nsRefPtr<dom::Touch> t = new dom::Touch(-1, nsIntPoint(aX, aY), 1.156 + nsIntPoint(1, 1), 0.0f, 1.0f); 1.157 + t->SetTarget(aContent); 1.158 + event.touches.AppendElement(t); 1.159 + nsEventStatus status = nsEventStatus_eIgnore; 1.160 + aPresShell->HandleEventWithTarget(&event, aFrame, aContent, &status); 1.161 +} 1.162 + 1.163 +uint32_t 1.164 +nsCoreUtils::GetAccessKeyFor(nsIContent* aContent) 1.165 +{ 1.166 + // Accesskeys are registered by @accesskey attribute only. At first check 1.167 + // whether it is presented on the given element to avoid the slow 1.168 + // EventStateManager::GetRegisteredAccessKey() method. 1.169 + if (!aContent->HasAttr(kNameSpaceID_None, nsGkAtoms::accesskey)) 1.170 + return 0; 1.171 + 1.172 + nsIPresShell* presShell = aContent->OwnerDoc()->GetShell(); 1.173 + if (!presShell) 1.174 + return 0; 1.175 + 1.176 + nsPresContext *presContext = presShell->GetPresContext(); 1.177 + if (!presContext) 1.178 + return 0; 1.179 + 1.180 + EventStateManager *esm = presContext->EventStateManager(); 1.181 + if (!esm) 1.182 + return 0; 1.183 + 1.184 + return esm->GetRegisteredAccessKey(aContent); 1.185 +} 1.186 + 1.187 +nsIContent * 1.188 +nsCoreUtils::GetDOMElementFor(nsIContent *aContent) 1.189 +{ 1.190 + if (aContent->IsElement()) 1.191 + return aContent; 1.192 + 1.193 + if (aContent->IsNodeOfType(nsINode::eTEXT)) 1.194 + return aContent->GetFlattenedTreeParent(); 1.195 + 1.196 + return nullptr; 1.197 +} 1.198 + 1.199 +nsINode * 1.200 +nsCoreUtils::GetDOMNodeFromDOMPoint(nsINode *aNode, uint32_t aOffset) 1.201 +{ 1.202 + if (aNode && aNode->IsElement()) { 1.203 + uint32_t childCount = aNode->GetChildCount(); 1.204 + NS_ASSERTION(aOffset <= childCount, "Wrong offset of the DOM point!"); 1.205 + 1.206 + // The offset can be after last child of container node that means DOM point 1.207 + // is placed immediately after the last child. In this case use the DOM node 1.208 + // from the given DOM point is used as result node. 1.209 + if (aOffset != childCount) 1.210 + return aNode->GetChildAt(aOffset); 1.211 + } 1.212 + 1.213 + return aNode; 1.214 +} 1.215 + 1.216 +nsIContent* 1.217 +nsCoreUtils::GetRoleContent(nsINode *aNode) 1.218 +{ 1.219 + nsCOMPtr<nsIContent> content(do_QueryInterface(aNode)); 1.220 + if (!content) { 1.221 + nsCOMPtr<nsIDocument> doc(do_QueryInterface(aNode)); 1.222 + if (doc) { 1.223 + nsCOMPtr<nsIDOMHTMLDocument> htmlDoc(do_QueryInterface(aNode)); 1.224 + if (htmlDoc) { 1.225 + nsCOMPtr<nsIDOMHTMLElement> bodyElement; 1.226 + htmlDoc->GetBody(getter_AddRefs(bodyElement)); 1.227 + content = do_QueryInterface(bodyElement); 1.228 + } 1.229 + else { 1.230 + return doc->GetDocumentElement(); 1.231 + } 1.232 + } 1.233 + } 1.234 + 1.235 + return content; 1.236 +} 1.237 + 1.238 +bool 1.239 +nsCoreUtils::IsAncestorOf(nsINode *aPossibleAncestorNode, 1.240 + nsINode *aPossibleDescendantNode, 1.241 + nsINode *aRootNode) 1.242 +{ 1.243 + NS_ENSURE_TRUE(aPossibleAncestorNode && aPossibleDescendantNode, false); 1.244 + 1.245 + nsINode *parentNode = aPossibleDescendantNode; 1.246 + while ((parentNode = parentNode->GetParentNode()) && 1.247 + parentNode != aRootNode) { 1.248 + if (parentNode == aPossibleAncestorNode) 1.249 + return true; 1.250 + } 1.251 + 1.252 + return false; 1.253 +} 1.254 + 1.255 +nsresult 1.256 +nsCoreUtils::ScrollSubstringTo(nsIFrame* aFrame, nsRange* aRange, 1.257 + uint32_t aScrollType) 1.258 +{ 1.259 + nsIPresShell::ScrollAxis vertical, horizontal; 1.260 + ConvertScrollTypeToPercents(aScrollType, &vertical, &horizontal); 1.261 + 1.262 + return ScrollSubstringTo(aFrame, aRange, vertical, horizontal); 1.263 +} 1.264 + 1.265 +nsresult 1.266 +nsCoreUtils::ScrollSubstringTo(nsIFrame* aFrame, nsRange* aRange, 1.267 + nsIPresShell::ScrollAxis aVertical, 1.268 + nsIPresShell::ScrollAxis aHorizontal) 1.269 +{ 1.270 + if (!aFrame) 1.271 + return NS_ERROR_FAILURE; 1.272 + 1.273 + nsPresContext *presContext = aFrame->PresContext(); 1.274 + 1.275 + nsCOMPtr<nsISelectionController> selCon; 1.276 + aFrame->GetSelectionController(presContext, getter_AddRefs(selCon)); 1.277 + NS_ENSURE_TRUE(selCon, NS_ERROR_FAILURE); 1.278 + 1.279 + nsCOMPtr<nsISelection> selection; 1.280 + selCon->GetSelection(nsISelectionController::SELECTION_ACCESSIBILITY, 1.281 + getter_AddRefs(selection)); 1.282 + 1.283 + nsCOMPtr<nsISelectionPrivate> privSel(do_QueryInterface(selection)); 1.284 + selection->RemoveAllRanges(); 1.285 + selection->AddRange(aRange); 1.286 + 1.287 + privSel->ScrollIntoViewInternal( 1.288 + nsISelectionController::SELECTION_ANCHOR_REGION, 1.289 + true, aVertical, aHorizontal); 1.290 + 1.291 + selection->CollapseToStart(); 1.292 + 1.293 + return NS_OK; 1.294 +} 1.295 + 1.296 +void 1.297 +nsCoreUtils::ScrollFrameToPoint(nsIFrame *aScrollableFrame, 1.298 + nsIFrame *aFrame, 1.299 + const nsIntPoint& aPoint) 1.300 +{ 1.301 + nsIScrollableFrame* scrollableFrame = do_QueryFrame(aScrollableFrame); 1.302 + if (!scrollableFrame) 1.303 + return; 1.304 + 1.305 + nsPoint point = 1.306 + aPoint.ToAppUnits(aFrame->PresContext()->AppUnitsPerDevPixel()); 1.307 + nsRect frameRect = aFrame->GetScreenRectInAppUnits(); 1.308 + nsPoint deltaPoint(point.x - frameRect.x, point.y - frameRect.y); 1.309 + 1.310 + nsPoint scrollPoint = scrollableFrame->GetScrollPosition(); 1.311 + scrollPoint -= deltaPoint; 1.312 + 1.313 + scrollableFrame->ScrollTo(scrollPoint, nsIScrollableFrame::INSTANT); 1.314 +} 1.315 + 1.316 +void 1.317 +nsCoreUtils::ConvertScrollTypeToPercents(uint32_t aScrollType, 1.318 + nsIPresShell::ScrollAxis *aVertical, 1.319 + nsIPresShell::ScrollAxis *aHorizontal) 1.320 +{ 1.321 + int16_t whereY, whereX; 1.322 + nsIPresShell::WhenToScroll whenY, whenX; 1.323 + switch (aScrollType) 1.324 + { 1.325 + case nsIAccessibleScrollType::SCROLL_TYPE_TOP_LEFT: 1.326 + whereY = nsIPresShell::SCROLL_TOP; 1.327 + whenY = nsIPresShell::SCROLL_ALWAYS; 1.328 + whereX = nsIPresShell::SCROLL_LEFT; 1.329 + whenX = nsIPresShell::SCROLL_ALWAYS; 1.330 + break; 1.331 + case nsIAccessibleScrollType::SCROLL_TYPE_BOTTOM_RIGHT: 1.332 + whereY = nsIPresShell::SCROLL_BOTTOM; 1.333 + whenY = nsIPresShell::SCROLL_ALWAYS; 1.334 + whereX = nsIPresShell::SCROLL_RIGHT; 1.335 + whenX = nsIPresShell::SCROLL_ALWAYS; 1.336 + break; 1.337 + case nsIAccessibleScrollType::SCROLL_TYPE_TOP_EDGE: 1.338 + whereY = nsIPresShell::SCROLL_TOP; 1.339 + whenY = nsIPresShell::SCROLL_ALWAYS; 1.340 + whereX = nsIPresShell::SCROLL_MINIMUM; 1.341 + whenX = nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE; 1.342 + break; 1.343 + case nsIAccessibleScrollType::SCROLL_TYPE_BOTTOM_EDGE: 1.344 + whereY = nsIPresShell::SCROLL_BOTTOM; 1.345 + whenY = nsIPresShell::SCROLL_ALWAYS; 1.346 + whereX = nsIPresShell::SCROLL_MINIMUM; 1.347 + whenX = nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE; 1.348 + break; 1.349 + case nsIAccessibleScrollType::SCROLL_TYPE_LEFT_EDGE: 1.350 + whereY = nsIPresShell::SCROLL_MINIMUM; 1.351 + whenY = nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE; 1.352 + whereX = nsIPresShell::SCROLL_LEFT; 1.353 + whenX = nsIPresShell::SCROLL_ALWAYS; 1.354 + break; 1.355 + case nsIAccessibleScrollType::SCROLL_TYPE_RIGHT_EDGE: 1.356 + whereY = nsIPresShell::SCROLL_MINIMUM; 1.357 + whenY = nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE; 1.358 + whereX = nsIPresShell::SCROLL_RIGHT; 1.359 + whenX = nsIPresShell::SCROLL_ALWAYS; 1.360 + break; 1.361 + default: 1.362 + whereY = nsIPresShell::SCROLL_MINIMUM; 1.363 + whenY = nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE; 1.364 + whereX = nsIPresShell::SCROLL_MINIMUM; 1.365 + whenX = nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE; 1.366 + } 1.367 + *aVertical = nsIPresShell::ScrollAxis(whereY, whenY); 1.368 + *aHorizontal = nsIPresShell::ScrollAxis(whereX, whenX); 1.369 +} 1.370 + 1.371 +nsIntPoint 1.372 +nsCoreUtils::GetScreenCoordsForWindow(nsINode *aNode) 1.373 +{ 1.374 + nsIntPoint coords(0, 0); 1.375 + nsCOMPtr<nsIDocShellTreeItem> treeItem(GetDocShellFor(aNode)); 1.376 + if (!treeItem) 1.377 + return coords; 1.378 + 1.379 + nsCOMPtr<nsIDocShellTreeOwner> treeOwner; 1.380 + treeItem->GetTreeOwner(getter_AddRefs(treeOwner)); 1.381 + if (!treeOwner) 1.382 + return coords; 1.383 + 1.384 + nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(treeOwner); 1.385 + if (baseWindow) 1.386 + baseWindow->GetPosition(&coords.x, &coords.y); // in device pixels 1.387 + 1.388 + return coords; 1.389 +} 1.390 + 1.391 +already_AddRefed<nsIDocShell> 1.392 +nsCoreUtils::GetDocShellFor(nsINode *aNode) 1.393 +{ 1.394 + if (!aNode) 1.395 + return nullptr; 1.396 + 1.397 + nsCOMPtr<nsIDocShell> docShell = aNode->OwnerDoc()->GetDocShell(); 1.398 + return docShell.forget(); 1.399 +} 1.400 + 1.401 +bool 1.402 +nsCoreUtils::IsRootDocument(nsIDocument *aDocument) 1.403 +{ 1.404 + nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem = aDocument->GetDocShell(); 1.405 + NS_ASSERTION(docShellTreeItem, "No document shell for document!"); 1.406 + 1.407 + nsCOMPtr<nsIDocShellTreeItem> parentTreeItem; 1.408 + docShellTreeItem->GetParent(getter_AddRefs(parentTreeItem)); 1.409 + 1.410 + return !parentTreeItem; 1.411 +} 1.412 + 1.413 +bool 1.414 +nsCoreUtils::IsContentDocument(nsIDocument *aDocument) 1.415 +{ 1.416 + nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem = aDocument->GetDocShell(); 1.417 + NS_ASSERTION(docShellTreeItem, "No document shell tree item for document!"); 1.418 + 1.419 + return (docShellTreeItem->ItemType() == nsIDocShellTreeItem::typeContent); 1.420 +} 1.421 + 1.422 +bool 1.423 +nsCoreUtils::IsTabDocument(nsIDocument* aDocumentNode) 1.424 +{ 1.425 + nsCOMPtr<nsIDocShellTreeItem> treeItem(aDocumentNode->GetDocShell()); 1.426 + 1.427 + nsCOMPtr<nsIDocShellTreeItem> parentTreeItem; 1.428 + treeItem->GetParent(getter_AddRefs(parentTreeItem)); 1.429 + 1.430 + // Tab document running in own process doesn't have parent. 1.431 + if (XRE_GetProcessType() == GeckoProcessType_Content) 1.432 + return !parentTreeItem; 1.433 + 1.434 + // Parent of docshell for tab document running in chrome process is root. 1.435 + nsCOMPtr<nsIDocShellTreeItem> rootTreeItem; 1.436 + treeItem->GetRootTreeItem(getter_AddRefs(rootTreeItem)); 1.437 + 1.438 + return parentTreeItem == rootTreeItem; 1.439 +} 1.440 + 1.441 +bool 1.442 +nsCoreUtils::IsErrorPage(nsIDocument *aDocument) 1.443 +{ 1.444 + nsIURI *uri = aDocument->GetDocumentURI(); 1.445 + bool isAboutScheme = false; 1.446 + uri->SchemeIs("about", &isAboutScheme); 1.447 + if (!isAboutScheme) 1.448 + return false; 1.449 + 1.450 + nsAutoCString path; 1.451 + uri->GetPath(path); 1.452 + 1.453 + NS_NAMED_LITERAL_CSTRING(neterror, "neterror"); 1.454 + NS_NAMED_LITERAL_CSTRING(certerror, "certerror"); 1.455 + 1.456 + return StringBeginsWith(path, neterror) || StringBeginsWith(path, certerror); 1.457 +} 1.458 + 1.459 +bool 1.460 +nsCoreUtils::GetID(nsIContent *aContent, nsAString& aID) 1.461 +{ 1.462 + nsIAtom *idAttribute = aContent->GetIDAttributeName(); 1.463 + return idAttribute ? aContent->GetAttr(kNameSpaceID_None, idAttribute, aID) : false; 1.464 +} 1.465 + 1.466 +bool 1.467 +nsCoreUtils::GetUIntAttr(nsIContent *aContent, nsIAtom *aAttr, int32_t *aUInt) 1.468 +{ 1.469 + nsAutoString value; 1.470 + aContent->GetAttr(kNameSpaceID_None, aAttr, value); 1.471 + if (!value.IsEmpty()) { 1.472 + nsresult error = NS_OK; 1.473 + int32_t integer = value.ToInteger(&error); 1.474 + if (NS_SUCCEEDED(error) && integer > 0) { 1.475 + *aUInt = integer; 1.476 + return true; 1.477 + } 1.478 + } 1.479 + 1.480 + return false; 1.481 +} 1.482 + 1.483 +void 1.484 +nsCoreUtils::GetLanguageFor(nsIContent *aContent, nsIContent *aRootContent, 1.485 + nsAString& aLanguage) 1.486 +{ 1.487 + aLanguage.Truncate(); 1.488 + 1.489 + nsIContent *walkUp = aContent; 1.490 + while (walkUp && walkUp != aRootContent && 1.491 + !walkUp->GetAttr(kNameSpaceID_None, nsGkAtoms::lang, aLanguage)) 1.492 + walkUp = walkUp->GetParent(); 1.493 +} 1.494 + 1.495 +already_AddRefed<nsIBoxObject> 1.496 +nsCoreUtils::GetTreeBodyBoxObject(nsITreeBoxObject *aTreeBoxObj) 1.497 +{ 1.498 + nsCOMPtr<nsIDOMElement> tcElm; 1.499 + aTreeBoxObj->GetTreeBody(getter_AddRefs(tcElm)); 1.500 + nsCOMPtr<nsIDOMXULElement> tcXULElm(do_QueryInterface(tcElm)); 1.501 + if (!tcXULElm) 1.502 + return nullptr; 1.503 + 1.504 + nsCOMPtr<nsIBoxObject> boxObj; 1.505 + tcXULElm->GetBoxObject(getter_AddRefs(boxObj)); 1.506 + return boxObj.forget(); 1.507 +} 1.508 + 1.509 +already_AddRefed<nsITreeBoxObject> 1.510 +nsCoreUtils::GetTreeBoxObject(nsIContent *aContent) 1.511 +{ 1.512 + // Find DOMNode's parents recursively until reach the <tree> tag 1.513 + nsIContent* currentContent = aContent; 1.514 + while (currentContent) { 1.515 + if (currentContent->NodeInfo()->Equals(nsGkAtoms::tree, 1.516 + kNameSpaceID_XUL)) { 1.517 + // We will get the nsITreeBoxObject from the tree node 1.518 + nsCOMPtr<nsIDOMXULElement> xulElement(do_QueryInterface(currentContent)); 1.519 + if (xulElement) { 1.520 + nsCOMPtr<nsIBoxObject> box; 1.521 + xulElement->GetBoxObject(getter_AddRefs(box)); 1.522 + nsCOMPtr<nsITreeBoxObject> treeBox(do_QueryInterface(box)); 1.523 + if (treeBox) 1.524 + return treeBox.forget(); 1.525 + } 1.526 + } 1.527 + currentContent = currentContent->GetFlattenedTreeParent(); 1.528 + } 1.529 + 1.530 + return nullptr; 1.531 +} 1.532 + 1.533 +already_AddRefed<nsITreeColumn> 1.534 +nsCoreUtils::GetFirstSensibleColumn(nsITreeBoxObject *aTree) 1.535 +{ 1.536 + nsCOMPtr<nsITreeColumns> cols; 1.537 + aTree->GetColumns(getter_AddRefs(cols)); 1.538 + if (!cols) 1.539 + return nullptr; 1.540 + 1.541 + nsCOMPtr<nsITreeColumn> column; 1.542 + cols->GetFirstColumn(getter_AddRefs(column)); 1.543 + if (column && IsColumnHidden(column)) 1.544 + return GetNextSensibleColumn(column); 1.545 + 1.546 + return column.forget(); 1.547 +} 1.548 + 1.549 +uint32_t 1.550 +nsCoreUtils::GetSensibleColumnCount(nsITreeBoxObject *aTree) 1.551 +{ 1.552 + uint32_t count = 0; 1.553 + 1.554 + nsCOMPtr<nsITreeColumns> cols; 1.555 + aTree->GetColumns(getter_AddRefs(cols)); 1.556 + if (!cols) 1.557 + return count; 1.558 + 1.559 + nsCOMPtr<nsITreeColumn> column; 1.560 + cols->GetFirstColumn(getter_AddRefs(column)); 1.561 + 1.562 + while (column) { 1.563 + if (!IsColumnHidden(column)) 1.564 + count++; 1.565 + 1.566 + nsCOMPtr<nsITreeColumn> nextColumn; 1.567 + column->GetNext(getter_AddRefs(nextColumn)); 1.568 + column.swap(nextColumn); 1.569 + } 1.570 + 1.571 + return count; 1.572 +} 1.573 + 1.574 +already_AddRefed<nsITreeColumn> 1.575 +nsCoreUtils::GetSensibleColumnAt(nsITreeBoxObject *aTree, uint32_t aIndex) 1.576 +{ 1.577 + uint32_t idx = aIndex; 1.578 + 1.579 + nsCOMPtr<nsITreeColumn> column = GetFirstSensibleColumn(aTree); 1.580 + while (column) { 1.581 + if (idx == 0) 1.582 + return column.forget(); 1.583 + 1.584 + idx--; 1.585 + column = GetNextSensibleColumn(column); 1.586 + } 1.587 + 1.588 + return nullptr; 1.589 +} 1.590 + 1.591 +already_AddRefed<nsITreeColumn> 1.592 +nsCoreUtils::GetNextSensibleColumn(nsITreeColumn *aColumn) 1.593 +{ 1.594 + nsCOMPtr<nsITreeColumn> nextColumn; 1.595 + aColumn->GetNext(getter_AddRefs(nextColumn)); 1.596 + 1.597 + while (nextColumn && IsColumnHidden(nextColumn)) { 1.598 + nsCOMPtr<nsITreeColumn> tempColumn; 1.599 + nextColumn->GetNext(getter_AddRefs(tempColumn)); 1.600 + nextColumn.swap(tempColumn); 1.601 + } 1.602 + 1.603 + return nextColumn.forget(); 1.604 +} 1.605 + 1.606 +already_AddRefed<nsITreeColumn> 1.607 +nsCoreUtils::GetPreviousSensibleColumn(nsITreeColumn *aColumn) 1.608 +{ 1.609 + nsCOMPtr<nsITreeColumn> prevColumn; 1.610 + aColumn->GetPrevious(getter_AddRefs(prevColumn)); 1.611 + 1.612 + while (prevColumn && IsColumnHidden(prevColumn)) { 1.613 + nsCOMPtr<nsITreeColumn> tempColumn; 1.614 + prevColumn->GetPrevious(getter_AddRefs(tempColumn)); 1.615 + prevColumn.swap(tempColumn); 1.616 + } 1.617 + 1.618 + return prevColumn.forget(); 1.619 +} 1.620 + 1.621 +bool 1.622 +nsCoreUtils::IsColumnHidden(nsITreeColumn *aColumn) 1.623 +{ 1.624 + nsCOMPtr<nsIDOMElement> element; 1.625 + aColumn->GetElement(getter_AddRefs(element)); 1.626 + nsCOMPtr<nsIContent> content = do_QueryInterface(element); 1.627 + return content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::hidden, 1.628 + nsGkAtoms::_true, eCaseMatters); 1.629 +} 1.630 + 1.631 +void 1.632 +nsCoreUtils::ScrollTo(nsIPresShell* aPresShell, nsIContent* aContent, 1.633 + uint32_t aScrollType) 1.634 +{ 1.635 + nsIPresShell::ScrollAxis vertical, horizontal; 1.636 + ConvertScrollTypeToPercents(aScrollType, &vertical, &horizontal); 1.637 + aPresShell->ScrollContentIntoView(aContent, vertical, horizontal, 1.638 + nsIPresShell::SCROLL_OVERFLOW_HIDDEN); 1.639 +} 1.640 + 1.641 +bool 1.642 +nsCoreUtils::IsWhitespaceString(const nsSubstring& aString) 1.643 +{ 1.644 + nsSubstring::const_char_iterator iterBegin, iterEnd; 1.645 + 1.646 + aString.BeginReading(iterBegin); 1.647 + aString.EndReading(iterEnd); 1.648 + 1.649 + while (iterBegin != iterEnd && IsWhitespace(*iterBegin)) 1.650 + ++iterBegin; 1.651 + 1.652 + return iterBegin == iterEnd; 1.653 +}