1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is Mozilla Communicator client code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 1998
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Original Author: Eric J. Burley (ericb@neoplanet.com)
24 : *
25 : * Alternatively, the contents of this file may be used under the terms of
26 : * either of the GNU General Public License Version 2 or later (the "GPL"),
27 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 : * in which case the provisions of the GPL or the LGPL are applicable instead
29 : * of those above. If you wish to allow use of your version of this file only
30 : * under the terms of either the GPL or the LGPL, and not to allow others to
31 : * use your version of this file under the terms of the MPL, indicate your
32 : * decision by deleting the provisions above and replace them with the notice
33 : * and other provisions required by the GPL or the LGPL. If you do not delete
34 : * the provisions above, a recipient may use your version of this file under
35 : * the terms of any one of the MPL, the GPL or the LGPL.
36 : *
37 : * ***** END LICENSE BLOCK ***** */
38 :
39 : #include "nsCOMPtr.h"
40 : #include "nsIServiceManager.h"
41 : #include "nsResizerFrame.h"
42 : #include "nsIContent.h"
43 : #include "nsIDocument.h"
44 : #include "nsIDOMXULDocument.h"
45 : #include "nsIDOMNodeList.h"
46 : #include "nsGkAtoms.h"
47 : #include "nsINameSpaceManager.h"
48 : #include "nsIDOMElementCSSInlineStyle.h"
49 : #include "nsIDOMCSSStyleDeclaration.h"
50 :
51 : #include "nsPresContext.h"
52 : #include "nsFrameManager.h"
53 : #include "nsIDocShell.h"
54 : #include "nsIDocShellTreeItem.h"
55 : #include "nsIDocShellTreeOwner.h"
56 : #include "nsIBaseWindow.h"
57 : #include "nsPIDOMWindow.h"
58 : #include "nsGUIEvent.h"
59 : #include "nsEventDispatcher.h"
60 : #include "nsContentUtils.h"
61 : #include "nsMenuPopupFrame.h"
62 : #include "nsIScreenManager.h"
63 : #include "mozilla/dom/Element.h"
64 : #include "nsContentErrors.h"
65 :
66 :
67 : //
68 : // NS_NewResizerFrame
69 : //
70 : // Creates a new Resizer frame and returns it
71 : //
72 : nsIFrame*
73 0 : NS_NewResizerFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
74 : {
75 0 : return new (aPresShell) nsResizerFrame(aPresShell, aContext);
76 : }
77 :
78 0 : NS_IMPL_FRAMEARENA_HELPERS(nsResizerFrame)
79 :
80 0 : nsResizerFrame::nsResizerFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
81 0 : :nsTitleBarFrame(aPresShell, aContext)
82 : {
83 0 : }
84 :
85 : NS_IMETHODIMP
86 0 : nsResizerFrame::HandleEvent(nsPresContext* aPresContext,
87 : nsGUIEvent* aEvent,
88 : nsEventStatus* aEventStatus)
89 : {
90 0 : NS_ENSURE_ARG_POINTER(aEventStatus);
91 0 : if (nsEventStatus_eConsumeNoDefault == *aEventStatus) {
92 0 : return NS_OK;
93 : }
94 :
95 0 : nsWeakFrame weakFrame(this);
96 0 : bool doDefault = true;
97 :
98 0 : switch (aEvent->message) {
99 : case NS_MOUSE_BUTTON_DOWN: {
100 0 : if (aEvent->eventStructType == NS_MOUSE_EVENT &&
101 : static_cast<nsMouseEvent*>(aEvent)->button == nsMouseEvent::eLeftButton)
102 : {
103 0 : nsCOMPtr<nsIBaseWindow> window;
104 0 : nsIPresShell* presShell = aPresContext->GetPresShell();
105 : nsIContent* contentToResize =
106 0 : GetContentToResize(presShell, getter_AddRefs(window));
107 0 : if (contentToResize) {
108 0 : nsIFrame* frameToResize = contentToResize->GetPrimaryFrame();
109 0 : if (!frameToResize)
110 : break;
111 :
112 : // cache the content rectangle for the frame to resize
113 : // GetScreenRectInAppUnits returns the border box rectangle, so
114 : // adjust to get the desired content rectangle.
115 0 : nsRect rect = frameToResize->GetScreenRectInAppUnits();
116 0 : switch (frameToResize->GetStylePosition()->mBoxSizing) {
117 : case NS_STYLE_BOX_SIZING_CONTENT:
118 0 : rect.Deflate(frameToResize->GetUsedPadding());
119 : case NS_STYLE_BOX_SIZING_PADDING:
120 0 : rect.Deflate(frameToResize->GetUsedBorder());
121 : default:
122 : break;
123 : }
124 :
125 0 : mMouseDownRect = rect.ToNearestPixels(aPresContext->AppUnitsPerDevPixel());
126 0 : doDefault = false;
127 : }
128 : else {
129 : // If there is no window, then resizing isn't allowed.
130 0 : if (!window)
131 : break;
132 :
133 0 : doDefault = false;
134 :
135 : // ask the widget implementation to begin a resize drag if it can
136 0 : Direction direction = GetDirection();
137 0 : nsresult rv = aEvent->widget->BeginResizeDrag(aEvent,
138 0 : direction.mHorizontal, direction.mVertical);
139 : // for native drags, don't set the fields below
140 0 : if (rv != NS_ERROR_NOT_IMPLEMENTED)
141 : break;
142 :
143 : // if there's no native resize support, we need to do window
144 : // resizing ourselves
145 0 : window->GetPositionAndSize(&mMouseDownRect.x, &mMouseDownRect.y,
146 0 : &mMouseDownRect.width, &mMouseDownRect.height);
147 : }
148 :
149 : // we're tracking
150 0 : mTrackingMouseMove = true;
151 :
152 : // remember current mouse coordinates
153 0 : mMouseDownPoint = aEvent->refPoint + aEvent->widget->WidgetToScreenOffset();
154 :
155 0 : nsIPresShell::SetCapturingContent(GetContent(), CAPTURE_IGNOREALLOWED);
156 : }
157 : }
158 0 : break;
159 :
160 : case NS_MOUSE_BUTTON_UP: {
161 :
162 0 : if (mTrackingMouseMove && aEvent->eventStructType == NS_MOUSE_EVENT &&
163 : static_cast<nsMouseEvent*>(aEvent)->button == nsMouseEvent::eLeftButton)
164 : {
165 : // we're done tracking.
166 0 : mTrackingMouseMove = false;
167 :
168 0 : nsIPresShell::SetCapturingContent(nsnull, 0);
169 :
170 0 : doDefault = false;
171 : }
172 : }
173 0 : break;
174 :
175 : case NS_MOUSE_MOVE: {
176 0 : if (mTrackingMouseMove)
177 : {
178 0 : nsCOMPtr<nsIBaseWindow> window;
179 0 : nsIPresShell* presShell = aPresContext->GetPresShell();
180 : nsCOMPtr<nsIContent> contentToResize =
181 0 : GetContentToResize(presShell, getter_AddRefs(window));
182 :
183 : // check if the returned content really is a menupopup
184 0 : nsMenuPopupFrame* menuPopupFrame = nsnull;
185 0 : if (contentToResize) {
186 0 : nsIFrame* frameToResize = contentToResize->GetPrimaryFrame();
187 0 : if (frameToResize && frameToResize->GetType() == nsGkAtoms::menuPopupFrame) {
188 0 : menuPopupFrame = static_cast<nsMenuPopupFrame *>(frameToResize);
189 : }
190 : }
191 :
192 : // both MouseMove and direction are negative when pointing to the
193 : // top and left, and positive when pointing to the bottom and right
194 :
195 : // retrieve the offset of the mousemove event relative to the mousedown.
196 : // The difference is how much the resize needs to be
197 0 : nsIntPoint screenPoint(aEvent->refPoint + aEvent->widget->WidgetToScreenOffset());
198 0 : nsIntPoint mouseMove(screenPoint - mMouseDownPoint);
199 :
200 : // Determine which direction to resize by checking the dir attribute.
201 : // For windows and menus, ensure that it can be resized in that direction.
202 0 : Direction direction = GetDirection();
203 0 : if (window || menuPopupFrame) {
204 0 : if (menuPopupFrame) {
205 : menuPopupFrame->CanAdjustEdges(
206 : (direction.mHorizontal == -1) ? NS_SIDE_LEFT : NS_SIDE_RIGHT,
207 0 : (direction.mVertical == -1) ? NS_SIDE_TOP : NS_SIDE_BOTTOM, mouseMove);
208 : }
209 : }
210 0 : else if (!contentToResize) {
211 : break; // don't do anything if there's nothing to resize
212 : }
213 :
214 0 : nsIntRect rect = mMouseDownRect;
215 0 : AdjustDimensions(&rect.x, &rect.width, mouseMove.x, direction.mHorizontal);
216 0 : AdjustDimensions(&rect.y, &rect.height, mouseMove.y, direction.mVertical);
217 :
218 : // Don't allow resizing a window or a popup past the edge of the screen,
219 : // so adjust the rectangle to fit within the available screen area.
220 0 : if (window) {
221 0 : nsCOMPtr<nsIScreen> screen;
222 0 : nsCOMPtr<nsIScreenManager> sm(do_GetService("@mozilla.org/gfx/screenmanager;1"));
223 0 : if (sm) {
224 0 : nsIntRect frameRect = GetScreenRect();
225 0 : sm->ScreenForRect(frameRect.x, frameRect.y, 1, 1, getter_AddRefs(screen));
226 0 : if (screen) {
227 0 : nsIntRect screenRect;
228 0 : screen->GetRect(&screenRect.x, &screenRect.y,
229 0 : &screenRect.width, &screenRect.height);
230 0 : rect.IntersectRect(rect, screenRect);
231 : }
232 : }
233 : }
234 0 : else if (menuPopupFrame) {
235 0 : nsRect frameRect = menuPopupFrame->GetScreenRectInAppUnits();
236 0 : nsIFrame* rootFrame = aPresContext->PresShell()->FrameManager()->GetRootFrame();
237 0 : nsRect rootScreenRect = rootFrame->GetScreenRectInAppUnits();
238 :
239 0 : nsRect screenRect = menuPopupFrame->GetConstraintRect(frameRect, rootScreenRect);
240 : // round using ToInsidePixels as it's better to be a pixel too small
241 : // than be too large. If the popup is too large it could get flipped
242 : // to the opposite side of the anchor point while resizing.
243 0 : nsIntRect screenRectPixels = screenRect.ToInsidePixels(aPresContext->AppUnitsPerDevPixel());
244 0 : rect.IntersectRect(rect, screenRectPixels);
245 : }
246 :
247 0 : if (contentToResize) {
248 : // convert the rectangle into css pixels. When changing the size in a
249 : // direction, don't allow the new size to be less that the resizer's
250 : // size. This ensures that content isn't resized too small as to make
251 : // the resizer invisible.
252 0 : nsRect appUnitsRect = rect.ToAppUnits(aPresContext->AppUnitsPerDevPixel());
253 0 : if (appUnitsRect.width < mRect.width && mouseMove.x)
254 0 : appUnitsRect.width = mRect.width;
255 0 : if (appUnitsRect.height < mRect.height && mouseMove.y)
256 0 : appUnitsRect.height = mRect.height;
257 0 : nsIntRect cssRect = appUnitsRect.ToInsidePixels(nsPresContext::AppUnitsPerCSSPixel());
258 :
259 0 : nsIntRect oldRect;
260 0 : nsWeakFrame weakFrame(menuPopupFrame);
261 0 : if (menuPopupFrame) {
262 0 : nsCOMPtr<nsIWidget> widget = menuPopupFrame->GetWidget();
263 0 : if (widget)
264 0 : widget->GetScreenBounds(oldRect);
265 :
266 : // convert the new rectangle into outer window coordinates
267 0 : nsIntPoint clientOffset = widget->GetClientOffset();
268 0 : rect.x -= clientOffset.x;
269 0 : rect.y -= clientOffset.y;
270 : }
271 :
272 0 : SizeInfo sizeInfo, originalSizeInfo;
273 0 : sizeInfo.width.AppendInt(cssRect.width);
274 0 : sizeInfo.height.AppendInt(cssRect.height);
275 0 : ResizeContent(contentToResize, direction, sizeInfo, &originalSizeInfo);
276 0 : MaybePersistOriginalSize(contentToResize, originalSizeInfo);
277 :
278 0 : if (weakFrame.IsAlive() &&
279 : (oldRect.x != rect.x || oldRect.y != rect.y) &&
280 0 : (!menuPopupFrame->IsAnchored() ||
281 0 : menuPopupFrame->PopupLevel() != ePopupLevelParent)) {
282 0 : menuPopupFrame->MoveTo(rect.x, rect.y, true);
283 : }
284 : }
285 : else {
286 0 : window->SetPositionAndSize(rect.x, rect.y, rect.width, rect.height, true); // do the repaint.
287 : }
288 :
289 0 : doDefault = false;
290 : }
291 : }
292 0 : break;
293 :
294 : case NS_MOUSE_CLICK:
295 0 : if (NS_IS_MOUSE_LEFT_CLICK(aEvent))
296 : {
297 0 : MouseClicked(aPresContext, aEvent);
298 : }
299 0 : break;
300 :
301 : case NS_MOUSE_DOUBLECLICK:
302 0 : if (aEvent->eventStructType == NS_MOUSE_EVENT &&
303 : static_cast<nsMouseEvent*>(aEvent)->button == nsMouseEvent::eLeftButton)
304 : {
305 0 : nsCOMPtr<nsIBaseWindow> window;
306 0 : nsIPresShell* presShell = aPresContext->GetPresShell();
307 : nsIContent* contentToResize =
308 0 : GetContentToResize(presShell, getter_AddRefs(window));
309 0 : if (contentToResize) {
310 0 : nsIFrame* frameToResize = contentToResize->GetPrimaryFrame();
311 0 : if (frameToResize && frameToResize->GetType() == nsGkAtoms::menuPopupFrame)
312 : break; // Don't restore original sizing for menupopup frames until
313 : // we handle screen constraints here. (Bug 357725)
314 :
315 0 : RestoreOriginalSize(contentToResize);
316 : }
317 : }
318 0 : break;
319 : }
320 :
321 0 : if (!doDefault)
322 0 : *aEventStatus = nsEventStatus_eConsumeNoDefault;
323 :
324 0 : if (doDefault && weakFrame.IsAlive())
325 0 : return nsTitleBarFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
326 :
327 0 : return NS_OK;
328 : }
329 :
330 : nsIContent*
331 0 : nsResizerFrame::GetContentToResize(nsIPresShell* aPresShell, nsIBaseWindow** aWindow)
332 : {
333 0 : *aWindow = nsnull;
334 :
335 0 : nsAutoString elementid;
336 0 : mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::element, elementid);
337 0 : if (elementid.IsEmpty()) {
338 : // If the resizer is in a popup, resize the popup's widget, otherwise
339 : // resize the widget associated with the window.
340 0 : nsIFrame* popup = GetParent();
341 0 : while (popup) {
342 0 : if (popup->GetType() == nsGkAtoms::menuPopupFrame) {
343 0 : return popup->GetContent();
344 : }
345 0 : popup = popup->GetParent();
346 : }
347 :
348 : // don't allow resizing windows in content shells
349 0 : bool isChromeShell = false;
350 0 : nsCOMPtr<nsISupports> cont = aPresShell->GetPresContext()->GetContainer();
351 0 : nsCOMPtr<nsIDocShellTreeItem> dsti = do_QueryInterface(cont);
352 0 : if (dsti) {
353 0 : PRInt32 type = -1;
354 0 : isChromeShell = (NS_SUCCEEDED(dsti->GetItemType(&type)) &&
355 0 : type == nsIDocShellTreeItem::typeChrome);
356 : }
357 :
358 0 : if (!isChromeShell) {
359 : // don't allow resizers in content shells, except for the viewport
360 : // scrollbar which doesn't have a parent
361 0 : nsIContent* nonNativeAnon = mContent->FindFirstNonNativeAnonymous();
362 0 : if (!nonNativeAnon || nonNativeAnon->GetParent()) {
363 0 : return nsnull;
364 : }
365 : }
366 :
367 : // get the document and the window - should this be cached?
368 0 : nsPIDOMWindow *domWindow = aPresShell->GetDocument()->GetWindow();
369 0 : if (domWindow) {
370 : nsCOMPtr<nsIDocShellTreeItem> docShellAsItem =
371 0 : do_QueryInterface(domWindow->GetDocShell());
372 0 : if (docShellAsItem) {
373 0 : nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
374 0 : docShellAsItem->GetTreeOwner(getter_AddRefs(treeOwner));
375 0 : if (treeOwner) {
376 0 : CallQueryInterface(treeOwner, aWindow);
377 : }
378 : }
379 : }
380 :
381 0 : return nsnull;
382 : }
383 :
384 0 : if (elementid.EqualsLiteral("_parent")) {
385 : // return the parent, but skip over native anonymous content
386 0 : nsIContent* parent = mContent->GetParent();
387 0 : return parent ? parent->FindFirstNonNativeAnonymous() : nsnull;
388 : }
389 :
390 0 : return aPresShell->GetDocument()->GetElementById(elementid);
391 : }
392 :
393 : /* adjust the window position and size according to the mouse movement and
394 : * the resizer direction
395 : */
396 : void
397 0 : nsResizerFrame::AdjustDimensions(PRInt32* aPos, PRInt32* aSize,
398 : PRInt32 aMovement, PRInt8 aResizerDirection)
399 : {
400 0 : switch(aResizerDirection)
401 : {
402 : case -1:
403 : // only move the window when the direction is top and/or left
404 0 : *aPos+= aMovement;
405 : // falling through: the window is resized in both cases
406 : case 1:
407 0 : *aSize+= aResizerDirection*aMovement;
408 : // use one as a minimum size or the element could disappear
409 0 : if (*aSize < 1)
410 0 : *aSize = 1;
411 : }
412 0 : }
413 :
414 : /* static */ void
415 0 : nsResizerFrame::ResizeContent(nsIContent* aContent, const Direction& aDirection,
416 : const SizeInfo& aSizeInfo, SizeInfo* aOriginalSizeInfo)
417 : {
418 : // for XUL elements, just set the width and height attributes. For
419 : // other elements, set style.width and style.height
420 0 : if (aContent->IsXUL()) {
421 0 : if (aOriginalSizeInfo) {
422 : aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::width,
423 0 : aOriginalSizeInfo->width);
424 : aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::height,
425 0 : aOriginalSizeInfo->height);
426 : }
427 : // only set the property if the element could have changed in that direction
428 0 : if (aDirection.mHorizontal) {
429 0 : aContent->SetAttr(kNameSpaceID_None, nsGkAtoms::width, aSizeInfo.width, true);
430 : }
431 0 : if (aDirection.mVertical) {
432 0 : aContent->SetAttr(kNameSpaceID_None, nsGkAtoms::height, aSizeInfo.height, true);
433 : }
434 : }
435 : else {
436 : nsCOMPtr<nsIDOMElementCSSInlineStyle> inlineStyleContent =
437 0 : do_QueryInterface(aContent);
438 0 : if (inlineStyleContent) {
439 0 : nsCOMPtr<nsIDOMCSSStyleDeclaration> decl;
440 0 : inlineStyleContent->GetStyle(getter_AddRefs(decl));
441 :
442 0 : if (aOriginalSizeInfo) {
443 0 : decl->GetPropertyValue(NS_LITERAL_STRING("width"),
444 0 : aOriginalSizeInfo->width);
445 0 : decl->GetPropertyValue(NS_LITERAL_STRING("height"),
446 0 : aOriginalSizeInfo->height);
447 : }
448 :
449 : // only set the property if the element could have changed in that direction
450 0 : if (aDirection.mHorizontal) {
451 0 : nsAutoString widthstr(aSizeInfo.width);
452 0 : if (!widthstr.IsEmpty() &&
453 0 : !Substring(widthstr, widthstr.Length() - 2, 2).EqualsLiteral("px"))
454 0 : widthstr.AppendLiteral("px");
455 0 : decl->SetProperty(NS_LITERAL_STRING("width"), widthstr, EmptyString());
456 : }
457 0 : if (aDirection.mVertical) {
458 0 : nsAutoString heightstr(aSizeInfo.height);
459 0 : if (!heightstr.IsEmpty() &&
460 0 : !Substring(heightstr, heightstr.Length() - 2, 2).EqualsLiteral("px"))
461 0 : heightstr.AppendLiteral("px");
462 0 : decl->SetProperty(NS_LITERAL_STRING("height"), heightstr, EmptyString());
463 : }
464 : }
465 : }
466 0 : }
467 :
468 : /* static */ void
469 0 : nsResizerFrame::SizeInfoDtorFunc(void *aObject, nsIAtom *aPropertyName,
470 : void *aPropertyValue, void *aData)
471 : {
472 : nsResizerFrame::SizeInfo *propertyValue =
473 0 : static_cast<nsResizerFrame::SizeInfo*>(aPropertyValue);
474 0 : delete propertyValue;
475 0 : }
476 :
477 : /* static */ void
478 0 : nsResizerFrame::MaybePersistOriginalSize(nsIContent* aContent,
479 : const SizeInfo& aSizeInfo)
480 : {
481 : nsresult rv;
482 :
483 0 : aContent->GetProperty(nsGkAtoms::_moz_original_size, &rv);
484 0 : if (rv != NS_PROPTABLE_PROP_NOT_THERE)
485 0 : return;
486 :
487 0 : nsAutoPtr<SizeInfo> sizeInfo(new SizeInfo(aSizeInfo));
488 0 : rv = aContent->SetProperty(nsGkAtoms::_moz_original_size, sizeInfo.get(),
489 0 : &SizeInfoDtorFunc);
490 0 : if (NS_SUCCEEDED(rv))
491 0 : sizeInfo.forget();
492 : }
493 :
494 : /* static */ void
495 0 : nsResizerFrame::RestoreOriginalSize(nsIContent* aContent)
496 : {
497 : nsresult rv;
498 : SizeInfo* sizeInfo =
499 : static_cast<SizeInfo*>(aContent->GetProperty(nsGkAtoms::_moz_original_size,
500 0 : &rv));
501 0 : if (NS_FAILED(rv))
502 0 : return;
503 :
504 0 : NS_ASSERTION(sizeInfo, "We set a null sizeInfo!?");
505 0 : Direction direction = {1, 1};
506 0 : ResizeContent(aContent, direction, *sizeInfo, nsnull);
507 0 : aContent->DeleteProperty(nsGkAtoms::_moz_original_size);
508 : }
509 :
510 : /* returns a Direction struct containing the horizontal and vertical direction
511 : */
512 : nsResizerFrame::Direction
513 0 : nsResizerFrame::GetDirection()
514 : {
515 : static const nsIContent::AttrValuesArray strings[] =
516 : {&nsGkAtoms::topleft, &nsGkAtoms::top, &nsGkAtoms::topright,
517 : &nsGkAtoms::left, &nsGkAtoms::right,
518 : &nsGkAtoms::bottomleft, &nsGkAtoms::bottom, &nsGkAtoms::bottomright,
519 : &nsGkAtoms::bottomstart, &nsGkAtoms::bottomend,
520 : nsnull};
521 :
522 : static const Direction directions[] =
523 : {{-1, -1}, {0, -1}, {1, -1},
524 : {-1, 0}, {1, 0},
525 : {-1, 1}, {0, 1}, {1, 1},
526 : {-1, 1}, {1, 1}
527 : };
528 :
529 0 : if (!GetContent())
530 0 : return directions[0]; // default: topleft
531 :
532 0 : PRInt32 index = GetContent()->FindAttrValueIn(kNameSpaceID_None,
533 : nsGkAtoms::dir,
534 0 : strings, eCaseMatters);
535 0 : if(index < 0)
536 0 : return directions[0]; // default: topleft
537 0 : else if (index >= 8 && GetStyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL) {
538 : // Directions 8 and higher are RTL-aware directions and should reverse the
539 : // horizontal component if RTL.
540 0 : Direction direction = directions[index];
541 0 : direction.mHorizontal *= -1;
542 0 : return direction;
543 : }
544 0 : return directions[index];
545 : }
546 :
547 : void
548 0 : nsResizerFrame::MouseClicked(nsPresContext* aPresContext, nsGUIEvent *aEvent)
549 : {
550 : // Execute the oncommand event handler.
551 : nsContentUtils::DispatchXULCommand(mContent,
552 : aEvent ?
553 0 : NS_IS_TRUSTED_EVENT(aEvent) : false);
554 0 : }
|