Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : #include "nsCoreUtils.h"
7 :
8 : #include "nsIAccessibleTypes.h"
9 :
10 : #include "nsIBaseWindow.h"
11 : #include "nsIDocShellTreeOwner.h"
12 : #include "nsIDocument.h"
13 : #include "nsIDOMHTMLDocument.h"
14 : #include "nsIDOMHTMLElement.h"
15 : #include "nsRange.h"
16 : #include "nsIBoxObject.h"
17 : #include "nsXULElement.h"
18 : #include "mozilla/dom/BoxObject.h"
19 : #include "nsIDocShell.h"
20 : #include "nsIObserverService.h"
21 : #include "nsIPresShell.h"
22 : #include "nsPresContext.h"
23 : #include "nsIScrollableFrame.h"
24 : #include "nsISelectionPrivate.h"
25 : #include "nsISelectionController.h"
26 : #include "nsISimpleEnumerator.h"
27 : #include "mozilla/dom/TouchEvent.h"
28 : #include "mozilla/ErrorResult.h"
29 : #include "mozilla/EventListenerManager.h"
30 : #include "mozilla/EventStateManager.h"
31 : #include "mozilla/MouseEvents.h"
32 : #include "mozilla/TouchEvents.h"
33 : #include "nsView.h"
34 : #include "nsGkAtoms.h"
35 :
36 : #include "nsComponentManagerUtils.h"
37 :
38 : #include "nsITreeBoxObject.h"
39 : #include "nsITreeColumns.h"
40 : #include "mozilla/dom/Element.h"
41 : #include "mozilla/dom/HTMLLabelElement.h"
42 :
43 : using namespace mozilla;
44 :
45 : ////////////////////////////////////////////////////////////////////////////////
46 : // nsCoreUtils
47 : ////////////////////////////////////////////////////////////////////////////////
48 :
49 : bool
50 0 : nsCoreUtils::IsLabelWithControl(nsIContent* aContent)
51 : {
52 0 : dom::HTMLLabelElement* label = dom::HTMLLabelElement::FromContent(aContent);
53 0 : if (label && label->GetControl())
54 0 : return true;
55 :
56 0 : return false;
57 : }
58 :
59 : bool
60 0 : nsCoreUtils::HasClickListener(nsIContent *aContent)
61 : {
62 0 : NS_ENSURE_TRUE(aContent, false);
63 : EventListenerManager* listenerManager =
64 0 : aContent->GetExistingListenerManager();
65 :
66 0 : return listenerManager &&
67 0 : (listenerManager->HasListenersFor(nsGkAtoms::onclick) ||
68 0 : listenerManager->HasListenersFor(nsGkAtoms::onmousedown) ||
69 0 : listenerManager->HasListenersFor(nsGkAtoms::onmouseup));
70 : }
71 :
72 : void
73 0 : nsCoreUtils::DispatchClickEvent(nsITreeBoxObject *aTreeBoxObj,
74 : int32_t aRowIndex, nsITreeColumn *aColumn,
75 : const nsAString& aPseudoElt)
76 : {
77 0 : nsCOMPtr<nsIDOMElement> tcElm;
78 0 : aTreeBoxObj->GetTreeBody(getter_AddRefs(tcElm));
79 0 : if (!tcElm)
80 0 : return;
81 :
82 0 : nsCOMPtr<nsIContent> tcContent(do_QueryInterface(tcElm));
83 0 : nsIDocument *document = tcContent->GetUncomposedDoc();
84 0 : if (!document)
85 0 : return;
86 :
87 0 : nsCOMPtr<nsIPresShell> presShell = document->GetShell();
88 0 : if (!presShell)
89 0 : return;
90 :
91 : // Ensure row is visible.
92 0 : aTreeBoxObj->EnsureRowIsVisible(aRowIndex);
93 :
94 : // Calculate x and y coordinates.
95 0 : int32_t x = 0, y = 0, width = 0, height = 0;
96 : nsresult rv = aTreeBoxObj->GetCoordsForCellItem(aRowIndex, aColumn,
97 : aPseudoElt,
98 0 : &x, &y, &width, &height);
99 0 : if (NS_FAILED(rv))
100 0 : return;
101 :
102 0 : nsCOMPtr<nsIContent> tcXULElm(do_QueryInterface(tcElm));
103 0 : IgnoredErrorResult ignored;
104 : nsCOMPtr<nsIBoxObject> tcBoxObj =
105 0 : nsXULElement::FromContent(tcXULElm)->GetBoxObject(ignored);
106 :
107 0 : int32_t tcX = 0;
108 0 : tcBoxObj->GetX(&tcX);
109 :
110 0 : int32_t tcY = 0;
111 0 : tcBoxObj->GetY(&tcY);
112 :
113 : // Dispatch mouse events.
114 0 : AutoWeakFrame tcFrame = tcContent->GetPrimaryFrame();
115 0 : nsIFrame* rootFrame = presShell->GetRootFrame();
116 :
117 0 : nsPoint offset;
118 : nsIWidget *rootWidget =
119 0 : rootFrame->GetView()->GetNearestWidget(&offset);
120 :
121 0 : RefPtr<nsPresContext> presContext = presShell->GetPresContext();
122 :
123 0 : int32_t cnvdX = presContext->CSSPixelsToDevPixels(tcX + x + 1) +
124 0 : presContext->AppUnitsToDevPixels(offset.x);
125 0 : int32_t cnvdY = presContext->CSSPixelsToDevPixels(tcY + y + 1) +
126 0 : presContext->AppUnitsToDevPixels(offset.y);
127 :
128 : // XUL is just desktop, so there is no real reason for senfing touch events.
129 0 : DispatchMouseEvent(eMouseDown, cnvdX, cnvdY,
130 0 : tcContent, tcFrame, presShell, rootWidget);
131 :
132 0 : DispatchMouseEvent(eMouseUp, cnvdX, cnvdY,
133 0 : tcContent, tcFrame, presShell, rootWidget);
134 : }
135 :
136 : void
137 0 : nsCoreUtils::DispatchMouseEvent(EventMessage aMessage, int32_t aX, int32_t aY,
138 : nsIContent *aContent, nsIFrame *aFrame,
139 : nsIPresShell *aPresShell, nsIWidget *aRootWidget)
140 : {
141 : WidgetMouseEvent event(true, aMessage, aRootWidget,
142 0 : WidgetMouseEvent::eReal, WidgetMouseEvent::eNormal);
143 :
144 0 : event.mRefPoint = LayoutDeviceIntPoint(aX, aY);
145 :
146 0 : event.mClickCount = 1;
147 0 : event.button = WidgetMouseEvent::eLeftButton;
148 0 : event.mTime = PR_IntervalNow();
149 0 : event.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN;
150 :
151 0 : nsEventStatus status = nsEventStatus_eIgnore;
152 0 : aPresShell->HandleEventWithTarget(&event, aFrame, aContent, &status);
153 0 : }
154 :
155 : void
156 0 : nsCoreUtils::DispatchTouchEvent(EventMessage aMessage, int32_t aX, int32_t aY,
157 : nsIContent* aContent, nsIFrame* aFrame,
158 : nsIPresShell* aPresShell, nsIWidget* aRootWidget)
159 : {
160 0 : nsIDocShell* docShell = nullptr;
161 0 : if (aPresShell->GetDocument()) {
162 0 : docShell = aPresShell->GetDocument()->GetDocShell();
163 : }
164 0 : if (!dom::TouchEvent::PrefEnabled(docShell)) {
165 0 : return;
166 : }
167 :
168 0 : WidgetTouchEvent event(true, aMessage, aRootWidget);
169 :
170 0 : event.mTime = PR_IntervalNow();
171 :
172 : // XXX: Touch has an identifier of -1 to hint that it is synthesized.
173 0 : RefPtr<dom::Touch> t = new dom::Touch(-1, LayoutDeviceIntPoint(aX, aY),
174 0 : LayoutDeviceIntPoint(1, 1), 0.0f, 1.0f);
175 0 : t->SetTarget(aContent);
176 0 : event.mTouches.AppendElement(t);
177 0 : nsEventStatus status = nsEventStatus_eIgnore;
178 0 : aPresShell->HandleEventWithTarget(&event, aFrame, aContent, &status);
179 : }
180 :
181 : uint32_t
182 0 : nsCoreUtils::GetAccessKeyFor(nsIContent* aContent)
183 : {
184 : // Accesskeys are registered by @accesskey attribute only. At first check
185 : // whether it is presented on the given element to avoid the slow
186 : // EventStateManager::GetRegisteredAccessKey() method.
187 0 : if (!aContent->HasAttr(kNameSpaceID_None, nsGkAtoms::accesskey))
188 0 : return 0;
189 :
190 0 : nsIPresShell* presShell = aContent->OwnerDoc()->GetShell();
191 0 : if (!presShell)
192 0 : return 0;
193 :
194 0 : nsPresContext *presContext = presShell->GetPresContext();
195 0 : if (!presContext)
196 0 : return 0;
197 :
198 0 : EventStateManager *esm = presContext->EventStateManager();
199 0 : if (!esm)
200 0 : return 0;
201 :
202 0 : return esm->GetRegisteredAccessKey(aContent);
203 : }
204 :
205 : nsIContent *
206 0 : nsCoreUtils::GetDOMElementFor(nsIContent *aContent)
207 : {
208 0 : if (aContent->IsElement())
209 0 : return aContent;
210 :
211 0 : if (aContent->IsNodeOfType(nsINode::eTEXT))
212 0 : return aContent->GetFlattenedTreeParent();
213 :
214 0 : return nullptr;
215 : }
216 :
217 : nsINode *
218 0 : nsCoreUtils::GetDOMNodeFromDOMPoint(nsINode *aNode, uint32_t aOffset)
219 : {
220 0 : if (aNode && aNode->IsElement()) {
221 0 : uint32_t childCount = aNode->GetChildCount();
222 0 : NS_ASSERTION(aOffset <= childCount, "Wrong offset of the DOM point!");
223 :
224 : // The offset can be after last child of container node that means DOM point
225 : // is placed immediately after the last child. In this case use the DOM node
226 : // from the given DOM point is used as result node.
227 0 : if (aOffset != childCount)
228 0 : return aNode->GetChildAt(aOffset);
229 : }
230 :
231 0 : return aNode;
232 : }
233 :
234 : bool
235 0 : nsCoreUtils::IsAncestorOf(nsINode *aPossibleAncestorNode,
236 : nsINode *aPossibleDescendantNode,
237 : nsINode *aRootNode)
238 : {
239 0 : NS_ENSURE_TRUE(aPossibleAncestorNode && aPossibleDescendantNode, false);
240 :
241 0 : nsINode *parentNode = aPossibleDescendantNode;
242 0 : while ((parentNode = parentNode->GetParentNode()) &&
243 : parentNode != aRootNode) {
244 0 : if (parentNode == aPossibleAncestorNode)
245 0 : return true;
246 : }
247 :
248 0 : return false;
249 : }
250 :
251 : nsresult
252 0 : nsCoreUtils::ScrollSubstringTo(nsIFrame* aFrame, nsRange* aRange,
253 : uint32_t aScrollType)
254 : {
255 0 : nsIPresShell::ScrollAxis vertical, horizontal;
256 0 : ConvertScrollTypeToPercents(aScrollType, &vertical, &horizontal);
257 :
258 0 : return ScrollSubstringTo(aFrame, aRange, vertical, horizontal);
259 : }
260 :
261 : nsresult
262 0 : nsCoreUtils::ScrollSubstringTo(nsIFrame* aFrame, nsRange* aRange,
263 : nsIPresShell::ScrollAxis aVertical,
264 : nsIPresShell::ScrollAxis aHorizontal)
265 : {
266 0 : if (!aFrame)
267 0 : return NS_ERROR_FAILURE;
268 :
269 0 : nsPresContext *presContext = aFrame->PresContext();
270 :
271 0 : nsCOMPtr<nsISelectionController> selCon;
272 0 : aFrame->GetSelectionController(presContext, getter_AddRefs(selCon));
273 0 : NS_ENSURE_TRUE(selCon, NS_ERROR_FAILURE);
274 :
275 0 : nsCOMPtr<nsISelection> selection;
276 0 : selCon->GetSelection(nsISelectionController::SELECTION_ACCESSIBILITY,
277 0 : getter_AddRefs(selection));
278 :
279 0 : nsCOMPtr<nsISelectionPrivate> privSel(do_QueryInterface(selection));
280 0 : selection->RemoveAllRanges();
281 0 : selection->AddRange(aRange);
282 :
283 0 : privSel->ScrollIntoViewInternal(
284 : nsISelectionController::SELECTION_ANCHOR_REGION,
285 0 : true, aVertical, aHorizontal);
286 :
287 0 : selection->CollapseToStart();
288 :
289 0 : return NS_OK;
290 : }
291 :
292 : void
293 0 : nsCoreUtils::ScrollFrameToPoint(nsIFrame *aScrollableFrame,
294 : nsIFrame *aFrame,
295 : const nsIntPoint& aPoint)
296 : {
297 0 : nsIScrollableFrame* scrollableFrame = do_QueryFrame(aScrollableFrame);
298 0 : if (!scrollableFrame)
299 0 : return;
300 :
301 : nsPoint point =
302 0 : ToAppUnits(aPoint, aFrame->PresContext()->AppUnitsPerDevPixel());
303 0 : nsRect frameRect = aFrame->GetScreenRectInAppUnits();
304 0 : nsPoint deltaPoint(point.x - frameRect.x, point.y - frameRect.y);
305 :
306 0 : nsPoint scrollPoint = scrollableFrame->GetScrollPosition();
307 0 : scrollPoint -= deltaPoint;
308 :
309 0 : scrollableFrame->ScrollTo(scrollPoint, nsIScrollableFrame::INSTANT);
310 : }
311 :
312 : void
313 0 : nsCoreUtils::ConvertScrollTypeToPercents(uint32_t aScrollType,
314 : nsIPresShell::ScrollAxis *aVertical,
315 : nsIPresShell::ScrollAxis *aHorizontal)
316 : {
317 : int16_t whereY, whereX;
318 : nsIPresShell::WhenToScroll whenY, whenX;
319 0 : switch (aScrollType)
320 : {
321 : case nsIAccessibleScrollType::SCROLL_TYPE_TOP_LEFT:
322 0 : whereY = nsIPresShell::SCROLL_TOP;
323 0 : whenY = nsIPresShell::SCROLL_ALWAYS;
324 0 : whereX = nsIPresShell::SCROLL_LEFT;
325 0 : whenX = nsIPresShell::SCROLL_ALWAYS;
326 0 : break;
327 : case nsIAccessibleScrollType::SCROLL_TYPE_BOTTOM_RIGHT:
328 0 : whereY = nsIPresShell::SCROLL_BOTTOM;
329 0 : whenY = nsIPresShell::SCROLL_ALWAYS;
330 0 : whereX = nsIPresShell::SCROLL_RIGHT;
331 0 : whenX = nsIPresShell::SCROLL_ALWAYS;
332 0 : break;
333 : case nsIAccessibleScrollType::SCROLL_TYPE_TOP_EDGE:
334 0 : whereY = nsIPresShell::SCROLL_TOP;
335 0 : whenY = nsIPresShell::SCROLL_ALWAYS;
336 0 : whereX = nsIPresShell::SCROLL_MINIMUM;
337 0 : whenX = nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE;
338 0 : break;
339 : case nsIAccessibleScrollType::SCROLL_TYPE_BOTTOM_EDGE:
340 0 : whereY = nsIPresShell::SCROLL_BOTTOM;
341 0 : whenY = nsIPresShell::SCROLL_ALWAYS;
342 0 : whereX = nsIPresShell::SCROLL_MINIMUM;
343 0 : whenX = nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE;
344 0 : break;
345 : case nsIAccessibleScrollType::SCROLL_TYPE_LEFT_EDGE:
346 0 : whereY = nsIPresShell::SCROLL_MINIMUM;
347 0 : whenY = nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE;
348 0 : whereX = nsIPresShell::SCROLL_LEFT;
349 0 : whenX = nsIPresShell::SCROLL_ALWAYS;
350 0 : break;
351 : case nsIAccessibleScrollType::SCROLL_TYPE_RIGHT_EDGE:
352 0 : whereY = nsIPresShell::SCROLL_MINIMUM;
353 0 : whenY = nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE;
354 0 : whereX = nsIPresShell::SCROLL_RIGHT;
355 0 : whenX = nsIPresShell::SCROLL_ALWAYS;
356 0 : break;
357 : default:
358 0 : whereY = nsIPresShell::SCROLL_MINIMUM;
359 0 : whenY = nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE;
360 0 : whereX = nsIPresShell::SCROLL_MINIMUM;
361 0 : whenX = nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE;
362 : }
363 0 : *aVertical = nsIPresShell::ScrollAxis(whereY, whenY);
364 0 : *aHorizontal = nsIPresShell::ScrollAxis(whereX, whenX);
365 0 : }
366 :
367 : nsIntPoint
368 0 : nsCoreUtils::GetScreenCoordsForWindow(nsINode *aNode)
369 : {
370 0 : nsIntPoint coords(0, 0);
371 0 : nsCOMPtr<nsIDocShellTreeItem> treeItem(GetDocShellFor(aNode));
372 0 : if (!treeItem)
373 0 : return coords;
374 :
375 0 : nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
376 0 : treeItem->GetTreeOwner(getter_AddRefs(treeOwner));
377 0 : if (!treeOwner)
378 0 : return coords;
379 :
380 0 : nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(treeOwner);
381 0 : if (baseWindow)
382 0 : baseWindow->GetPosition(&coords.x, &coords.y); // in device pixels
383 :
384 0 : return coords;
385 : }
386 :
387 : already_AddRefed<nsIDocShell>
388 0 : nsCoreUtils::GetDocShellFor(nsINode *aNode)
389 : {
390 0 : if (!aNode)
391 0 : return nullptr;
392 :
393 0 : nsCOMPtr<nsIDocShell> docShell = aNode->OwnerDoc()->GetDocShell();
394 0 : return docShell.forget();
395 : }
396 :
397 : bool
398 0 : nsCoreUtils::IsRootDocument(nsIDocument *aDocument)
399 : {
400 0 : nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem = aDocument->GetDocShell();
401 0 : NS_ASSERTION(docShellTreeItem, "No document shell for document!");
402 :
403 0 : nsCOMPtr<nsIDocShellTreeItem> parentTreeItem;
404 0 : docShellTreeItem->GetParent(getter_AddRefs(parentTreeItem));
405 :
406 0 : return !parentTreeItem;
407 : }
408 :
409 : bool
410 0 : nsCoreUtils::IsContentDocument(nsIDocument *aDocument)
411 : {
412 0 : nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem = aDocument->GetDocShell();
413 0 : NS_ASSERTION(docShellTreeItem, "No document shell tree item for document!");
414 :
415 0 : return (docShellTreeItem->ItemType() == nsIDocShellTreeItem::typeContent);
416 : }
417 :
418 : bool
419 0 : nsCoreUtils::IsTabDocument(nsIDocument* aDocumentNode)
420 : {
421 0 : nsCOMPtr<nsIDocShellTreeItem> treeItem(aDocumentNode->GetDocShell());
422 :
423 0 : nsCOMPtr<nsIDocShellTreeItem> parentTreeItem;
424 0 : treeItem->GetParent(getter_AddRefs(parentTreeItem));
425 :
426 : // Tab document running in own process doesn't have parent.
427 0 : if (XRE_IsContentProcess())
428 0 : return !parentTreeItem;
429 :
430 : // Parent of docshell for tab document running in chrome process is root.
431 0 : nsCOMPtr<nsIDocShellTreeItem> rootTreeItem;
432 0 : treeItem->GetRootTreeItem(getter_AddRefs(rootTreeItem));
433 :
434 0 : return parentTreeItem == rootTreeItem;
435 : }
436 :
437 : bool
438 0 : nsCoreUtils::IsErrorPage(nsIDocument *aDocument)
439 : {
440 0 : nsIURI *uri = aDocument->GetDocumentURI();
441 0 : bool isAboutScheme = false;
442 0 : uri->SchemeIs("about", &isAboutScheme);
443 0 : if (!isAboutScheme)
444 0 : return false;
445 :
446 0 : nsAutoCString path;
447 0 : uri->GetPath(path);
448 :
449 0 : NS_NAMED_LITERAL_CSTRING(neterror, "neterror");
450 0 : NS_NAMED_LITERAL_CSTRING(certerror, "certerror");
451 :
452 0 : return StringBeginsWith(path, neterror) || StringBeginsWith(path, certerror);
453 : }
454 :
455 : bool
456 0 : nsCoreUtils::GetID(nsIContent *aContent, nsAString& aID)
457 : {
458 0 : return aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::id, aID);
459 : }
460 :
461 : bool
462 0 : nsCoreUtils::GetUIntAttr(nsIContent *aContent, nsIAtom *aAttr, int32_t *aUInt)
463 : {
464 0 : nsAutoString value;
465 0 : aContent->GetAttr(kNameSpaceID_None, aAttr, value);
466 0 : if (!value.IsEmpty()) {
467 0 : nsresult error = NS_OK;
468 0 : int32_t integer = value.ToInteger(&error);
469 0 : if (NS_SUCCEEDED(error) && integer > 0) {
470 0 : *aUInt = integer;
471 0 : return true;
472 : }
473 : }
474 :
475 0 : return false;
476 : }
477 :
478 : void
479 0 : nsCoreUtils::GetLanguageFor(nsIContent *aContent, nsIContent *aRootContent,
480 : nsAString& aLanguage)
481 : {
482 0 : aLanguage.Truncate();
483 :
484 0 : nsIContent *walkUp = aContent;
485 0 : while (walkUp && walkUp != aRootContent &&
486 0 : !walkUp->GetAttr(kNameSpaceID_None, nsGkAtoms::lang, aLanguage))
487 0 : walkUp = walkUp->GetParent();
488 0 : }
489 :
490 : already_AddRefed<nsIBoxObject>
491 0 : nsCoreUtils::GetTreeBodyBoxObject(nsITreeBoxObject *aTreeBoxObj)
492 : {
493 0 : nsCOMPtr<nsIDOMElement> tcElm;
494 0 : aTreeBoxObj->GetTreeBody(getter_AddRefs(tcElm));
495 0 : nsCOMPtr<nsIContent> tcContent(do_QueryInterface(tcElm));
496 0 : RefPtr<nsXULElement> tcXULElm = nsXULElement::FromContentOrNull(tcContent);
497 0 : if (!tcXULElm)
498 0 : return nullptr;
499 :
500 0 : IgnoredErrorResult ignored;
501 0 : return tcXULElm->GetBoxObject(ignored);
502 : }
503 :
504 : already_AddRefed<nsITreeBoxObject>
505 0 : nsCoreUtils::GetTreeBoxObject(nsIContent *aContent)
506 : {
507 : // Find DOMNode's parents recursively until reach the <tree> tag
508 0 : nsIContent* currentContent = aContent;
509 0 : while (currentContent) {
510 0 : if (currentContent->NodeInfo()->Equals(nsGkAtoms::tree,
511 : kNameSpaceID_XUL)) {
512 : // We will get the nsITreeBoxObject from the tree node
513 : RefPtr<nsXULElement> xulElement =
514 0 : nsXULElement::FromContent(currentContent);
515 0 : IgnoredErrorResult ignored;
516 0 : nsCOMPtr<nsIBoxObject> box = xulElement->GetBoxObject(ignored);
517 0 : nsCOMPtr<nsITreeBoxObject> treeBox(do_QueryInterface(box));
518 0 : if (treeBox)
519 0 : return treeBox.forget();
520 : }
521 0 : currentContent = currentContent->GetFlattenedTreeParent();
522 : }
523 :
524 0 : return nullptr;
525 : }
526 :
527 : already_AddRefed<nsITreeColumn>
528 0 : nsCoreUtils::GetFirstSensibleColumn(nsITreeBoxObject *aTree)
529 : {
530 0 : nsCOMPtr<nsITreeColumns> cols;
531 0 : aTree->GetColumns(getter_AddRefs(cols));
532 0 : if (!cols)
533 0 : return nullptr;
534 :
535 0 : nsCOMPtr<nsITreeColumn> column;
536 0 : cols->GetFirstColumn(getter_AddRefs(column));
537 0 : if (column && IsColumnHidden(column))
538 0 : return GetNextSensibleColumn(column);
539 :
540 0 : return column.forget();
541 : }
542 :
543 : uint32_t
544 0 : nsCoreUtils::GetSensibleColumnCount(nsITreeBoxObject *aTree)
545 : {
546 0 : uint32_t count = 0;
547 :
548 0 : nsCOMPtr<nsITreeColumns> cols;
549 0 : aTree->GetColumns(getter_AddRefs(cols));
550 0 : if (!cols)
551 0 : return count;
552 :
553 0 : nsCOMPtr<nsITreeColumn> column;
554 0 : cols->GetFirstColumn(getter_AddRefs(column));
555 :
556 0 : while (column) {
557 0 : if (!IsColumnHidden(column))
558 0 : count++;
559 :
560 0 : nsCOMPtr<nsITreeColumn> nextColumn;
561 0 : column->GetNext(getter_AddRefs(nextColumn));
562 0 : column.swap(nextColumn);
563 : }
564 :
565 0 : return count;
566 : }
567 :
568 : already_AddRefed<nsITreeColumn>
569 0 : nsCoreUtils::GetSensibleColumnAt(nsITreeBoxObject *aTree, uint32_t aIndex)
570 : {
571 0 : uint32_t idx = aIndex;
572 :
573 0 : nsCOMPtr<nsITreeColumn> column = GetFirstSensibleColumn(aTree);
574 0 : while (column) {
575 0 : if (idx == 0)
576 0 : return column.forget();
577 :
578 0 : idx--;
579 0 : column = GetNextSensibleColumn(column);
580 : }
581 :
582 0 : return nullptr;
583 : }
584 :
585 : already_AddRefed<nsITreeColumn>
586 0 : nsCoreUtils::GetNextSensibleColumn(nsITreeColumn *aColumn)
587 : {
588 0 : nsCOMPtr<nsITreeColumn> nextColumn;
589 0 : aColumn->GetNext(getter_AddRefs(nextColumn));
590 :
591 0 : while (nextColumn && IsColumnHidden(nextColumn)) {
592 0 : nsCOMPtr<nsITreeColumn> tempColumn;
593 0 : nextColumn->GetNext(getter_AddRefs(tempColumn));
594 0 : nextColumn.swap(tempColumn);
595 : }
596 :
597 0 : return nextColumn.forget();
598 : }
599 :
600 : already_AddRefed<nsITreeColumn>
601 0 : nsCoreUtils::GetPreviousSensibleColumn(nsITreeColumn *aColumn)
602 : {
603 0 : nsCOMPtr<nsITreeColumn> prevColumn;
604 0 : aColumn->GetPrevious(getter_AddRefs(prevColumn));
605 :
606 0 : while (prevColumn && IsColumnHidden(prevColumn)) {
607 0 : nsCOMPtr<nsITreeColumn> tempColumn;
608 0 : prevColumn->GetPrevious(getter_AddRefs(tempColumn));
609 0 : prevColumn.swap(tempColumn);
610 : }
611 :
612 0 : return prevColumn.forget();
613 : }
614 :
615 : bool
616 0 : nsCoreUtils::IsColumnHidden(nsITreeColumn *aColumn)
617 : {
618 0 : nsCOMPtr<nsIDOMElement> element;
619 0 : aColumn->GetElement(getter_AddRefs(element));
620 0 : nsCOMPtr<nsIContent> content = do_QueryInterface(element);
621 0 : return content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::hidden,
622 0 : nsGkAtoms::_true, eCaseMatters);
623 : }
624 :
625 : void
626 0 : nsCoreUtils::ScrollTo(nsIPresShell* aPresShell, nsIContent* aContent,
627 : uint32_t aScrollType)
628 : {
629 0 : nsIPresShell::ScrollAxis vertical, horizontal;
630 0 : ConvertScrollTypeToPercents(aScrollType, &vertical, &horizontal);
631 : aPresShell->ScrollContentIntoView(aContent, vertical, horizontal,
632 0 : nsIPresShell::SCROLL_OVERFLOW_HIDDEN);
633 0 : }
634 :
635 : bool
636 0 : nsCoreUtils::IsWhitespaceString(const nsAString& aString)
637 : {
638 : nsAString::const_char_iterator iterBegin, iterEnd;
639 :
640 0 : aString.BeginReading(iterBegin);
641 0 : aString.EndReading(iterEnd);
642 :
643 0 : while (iterBegin != iterEnd && IsWhitespace(*iterBegin))
644 0 : ++iterBegin;
645 :
646 0 : return iterBegin == iterEnd;
647 : }
648 :
649 : bool
650 0 : nsCoreUtils::AccEventObserversExist()
651 : {
652 0 : nsCOMPtr<nsIObserverService> obsService = services::GetObserverService();
653 0 : NS_ENSURE_TRUE(obsService, false);
654 :
655 0 : nsCOMPtr<nsISimpleEnumerator> observers;
656 0 : obsService->EnumerateObservers(NS_ACCESSIBLE_EVENT_TOPIC,
657 0 : getter_AddRefs(observers));
658 0 : NS_ENSURE_TRUE(observers, false);
659 :
660 0 : bool hasObservers = false;
661 0 : observers->HasMoreElements(&hasObservers);
662 :
663 0 : return hasObservers;
664 : }
665 :
666 : void
667 0 : nsCoreUtils::DispatchAccEvent(RefPtr<nsIAccessibleEvent> event)
668 : {
669 0 : nsCOMPtr<nsIObserverService> obsService = services::GetObserverService();
670 0 : NS_ENSURE_TRUE_VOID(obsService);
671 :
672 0 : obsService->NotifyObservers(event, NS_ACCESSIBLE_EVENT_TOPIC, nullptr);
673 : }
674 :
675 : void
676 0 : nsCoreUtils::XBLBindingRole(const nsIContent* aEl, nsAString& aRole)
677 : {
678 0 : for (const nsXBLBinding* binding = aEl->GetXBLBinding(); binding;
679 : binding = binding->GetBaseBinding()) {
680 0 : nsIContent* bindingElm = binding->PrototypeBinding()->GetBindingElement();
681 0 : bindingElm->GetAttr(kNameSpaceID_None, nsGkAtoms::role, aRole);
682 0 : if (!aRole.IsEmpty())
683 0 : break;
684 : }
685 0 : }
|