Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/editor/libeditor/HTMLAbsPositionEditor.cpp
Line
Count
Source (jump to first uncovered line)
1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
 * License, v. 2.0. If a copy of the MPL was not distributed with this
3
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5
#include "mozilla/HTMLEditor.h"
6
7
#include <math.h>
8
9
#include "HTMLEditorObjectResizerUtils.h"
10
#include "HTMLEditRules.h"
11
#include "HTMLEditUtils.h"
12
#include "TextEditUtils.h"
13
#include "mozilla/EditAction.h"
14
#include "mozilla/EditorUtils.h"
15
#include "mozilla/Preferences.h"
16
#include "mozilla/TextEditRules.h"
17
#include "mozilla/dom/Selection.h"
18
#include "mozilla/dom/Element.h"
19
#include "mozilla/dom/EventTarget.h"
20
#include "mozilla/mozalloc.h"
21
#include "nsAString.h"
22
#include "nsAlgorithm.h"
23
#include "nsCOMPtr.h"
24
#include "nsComputedDOMStyle.h"
25
#include "nsDebug.h"
26
#include "nsError.h"
27
#include "nsGkAtoms.h"
28
#include "nsIContent.h"
29
#include "nsROCSSPrimitiveValue.h"
30
#include "nsIDOMEventListener.h"
31
#include "nsDOMCSSRGBColor.h"
32
#include "nsIDOMWindow.h"
33
#include "nsIHTMLObjectResizer.h"
34
#include "nsINode.h"
35
#include "nsIPresShell.h"
36
#include "nsISupportsImpl.h"
37
#include "nsISupportsUtils.h"
38
#include "nsLiteralString.h"
39
#include "nsReadableUtils.h"
40
#include "nsString.h"
41
#include "nsStringFwd.h"
42
#include "nscore.h"
43
#include <algorithm>
44
45
namespace mozilla {
46
47
using namespace dom;
48
49
nsresult
50
HTMLEditor::SetSelectionToAbsoluteOrStatic(bool aEnabled)
51
0
{
52
0
  AutoPlaceholderBatch beginBatching(this);
53
0
  AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
54
0
                                      *this,
55
0
                                      aEnabled ?
56
0
                                        EditSubAction::eSetPositionToAbsolute :
57
0
                                        EditSubAction::eSetPositionToStatic,
58
0
                                      nsIEditor::eNext);
59
0
60
0
  // the line below does not match the code; should it be removed?
61
0
  // Find out if the selection is collapsed:
62
0
  RefPtr<Selection> selection = GetSelection();
63
0
  NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
64
0
65
0
  EditSubActionInfo subActionInfo(
66
0
                      aEnabled ? EditSubAction::eSetPositionToAbsolute :
67
0
                                 EditSubAction::eSetPositionToStatic);
68
0
  bool cancel, handled;
69
0
  // Protect the edit rules object from dying
70
0
  RefPtr<TextEditRules> rules(mRules);
71
0
  nsresult rv =
72
0
    rules->WillDoAction(selection, subActionInfo, &cancel, &handled);
73
0
  if (NS_FAILED(rv) || cancel) {
74
0
    return rv;
75
0
  }
76
0
77
0
  return rules->DidDoAction(selection, subActionInfo, rv);
78
0
}
79
80
already_AddRefed<Element>
81
HTMLEditor::GetAbsolutelyPositionedSelectionContainer()
82
0
{
83
0
  RefPtr<Selection> selection = GetSelection();
84
0
  if (NS_WARN_IF(!selection)) {
85
0
    return nullptr;
86
0
  }
87
0
88
0
  RefPtr<Element> element = GetSelectionContainerElement(*selection);
89
0
  if (NS_WARN_IF(!element)) {
90
0
    return nullptr;
91
0
  }
92
0
93
0
  nsAutoString positionStr;
94
0
  while (element && !element->IsHTMLElement(nsGkAtoms::html)) {
95
0
    nsresult rv =
96
0
      CSSEditUtils::GetComputedProperty(*element, *nsGkAtoms::position,
97
0
                                        positionStr);
98
0
    if (NS_WARN_IF(NS_FAILED(rv))) {
99
0
      return nullptr;
100
0
    }
101
0
    if (positionStr.EqualsLiteral("absolute")) {
102
0
      return element.forget();
103
0
    }
104
0
    element = element->GetParentElement();
105
0
  }
106
0
  return nullptr;
107
0
}
108
109
NS_IMETHODIMP
110
HTMLEditor::GetAbsolutePositioningEnabled(bool* aIsEnabled)
111
0
{
112
0
  *aIsEnabled = IsAbsolutePositionEditorEnabled();
113
0
  return NS_OK;
114
0
}
115
116
NS_IMETHODIMP
117
HTMLEditor::SetAbsolutePositioningEnabled(bool aIsEnabled)
118
0
{
119
0
  EnableAbsolutePositionEditor(aIsEnabled);
120
0
  return NS_OK;
121
0
}
122
123
nsresult
124
HTMLEditor::RelativeChangeElementZIndex(Element& aElement,
125
                                        int32_t aChange,
126
                                        int32_t* aReturn)
127
0
{
128
0
  NS_ENSURE_ARG_POINTER(aReturn);
129
0
  if (!aChange) // early way out, no change
130
0
    return NS_OK;
131
0
132
0
  int32_t zIndex = GetZIndex(aElement);
133
0
  zIndex = std::max(zIndex + aChange, 0);
134
0
  SetZIndex(aElement, zIndex);
135
0
  *aReturn = zIndex;
136
0
137
0
  return NS_OK;
138
0
}
139
140
void
141
HTMLEditor::SetZIndex(Element& aElement,
142
                      int32_t aZindex)
143
0
{
144
0
  nsAutoString zIndexStr;
145
0
  zIndexStr.AppendInt(aZindex);
146
0
147
0
  mCSSEditUtils->SetCSSProperty(aElement, *nsGkAtoms::z_index, zIndexStr);
148
0
}
149
150
nsresult
151
HTMLEditor::AddZIndex(int32_t aChange)
152
0
{
153
0
  AutoPlaceholderBatch beginBatching(this);
154
0
  AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
155
0
                                      *this,
156
0
                                      aChange < 0 ?
157
0
                                        EditSubAction::eDecreaseZIndex :
158
0
                                        EditSubAction::eIncreaseZIndex,
159
0
                                      nsIEditor::eNext);
160
0
161
0
  // brade: can we get rid of this comment?
162
0
  // Find out if the selection is collapsed:
163
0
  RefPtr<Selection> selection = GetSelection();
164
0
  NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
165
0
  EditSubActionInfo subActionInfo(aChange < 0 ? EditSubAction::eDecreaseZIndex :
166
0
                                                EditSubAction::eIncreaseZIndex);
167
0
  bool cancel, handled;
168
0
  // Protect the edit rules object from dying
169
0
  RefPtr<TextEditRules> rules(mRules);
170
0
  nsresult rv =
171
0
    rules->WillDoAction(selection, subActionInfo, &cancel, &handled);
172
0
  if (cancel || NS_FAILED(rv)) {
173
0
    return rv;
174
0
  }
175
0
176
0
  return rules->DidDoAction(selection, subActionInfo, rv);
177
0
}
178
179
int32_t
180
HTMLEditor::GetZIndex(Element& aElement)
181
0
{
182
0
  nsAutoString zIndexStr;
183
0
184
0
  nsresult rv =
185
0
    CSSEditUtils::GetSpecifiedProperty(aElement, *nsGkAtoms::z_index,
186
0
                                       zIndexStr);
187
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
188
0
    return 0;
189
0
  }
190
0
  if (zIndexStr.EqualsLiteral("auto")) {
191
0
    // we have to look at the positioned ancestors
192
0
    // cf. CSS 2 spec section 9.9.1
193
0
    nsCOMPtr<nsINode> node = aElement.GetParentNode();
194
0
    nsAutoString positionStr;
195
0
    while (node && zIndexStr.EqualsLiteral("auto") &&
196
0
           !node->IsHTMLElement(nsGkAtoms::body)) {
197
0
      rv = CSSEditUtils::GetComputedProperty(*node, *nsGkAtoms::position,
198
0
                                             positionStr);
199
0
      if (NS_WARN_IF(NS_FAILED(rv))) {
200
0
        return 0;
201
0
      }
202
0
      if (positionStr.EqualsLiteral("absolute")) {
203
0
        // ah, we found one, what's its z-index ? If its z-index is auto,
204
0
        // we have to continue climbing the document's tree
205
0
        rv = CSSEditUtils::GetComputedProperty(*node, *nsGkAtoms::z_index,
206
0
                                               zIndexStr);
207
0
        if (NS_WARN_IF(NS_FAILED(rv))) {
208
0
          return 0;
209
0
        }
210
0
      }
211
0
      node = node->GetParentNode();
212
0
    }
213
0
  }
214
0
215
0
  if (zIndexStr.EqualsLiteral("auto")) {
216
0
    return 0;
217
0
  }
218
0
219
0
  nsresult errorCode;
220
0
  return zIndexStr.ToInteger(&errorCode);
221
0
}
222
223
bool
224
HTMLEditor::CreateGrabberInternal(nsIContent& aParentContent)
225
0
{
226
0
  if (NS_WARN_IF(mGrabber)) {
227
0
    return false;
228
0
  }
229
0
230
0
  mGrabber = CreateAnonymousElement(nsGkAtoms::span, aParentContent,
231
0
                                    NS_LITERAL_STRING("mozGrabber"), false);
232
0
233
0
  // mGrabber may be destroyed during creation due to there may be
234
0
  // mutation event listener.
235
0
  if (NS_WARN_IF(!mGrabber)) {
236
0
    return false;
237
0
  }
238
0
239
0
  EventListenerManager* eventListenerManager =
240
0
    mGrabber->GetOrCreateListenerManager();
241
0
  eventListenerManager->AddEventListenerByType(
242
0
                          mEventListener,
243
0
                          NS_LITERAL_STRING("mousedown"),
244
0
                          TrustedEventsAtSystemGroupBubble());
245
0
  MOZ_ASSERT(mGrabber);
246
0
  return true;
247
0
}
248
249
NS_IMETHODIMP
250
HTMLEditor::RefreshGrabber()
251
0
{
252
0
  if (NS_WARN_IF(!mAbsolutelyPositionedObject)) {
253
0
    return NS_ERROR_FAILURE;
254
0
  }
255
0
256
0
  nsresult rv = RefreshGrabberInternal();
257
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
258
0
    return rv;
259
0
  }
260
0
  return NS_OK;
261
0
}
262
263
nsresult
264
HTMLEditor::RefreshGrabberInternal()
265
0
{
266
0
  if (!mAbsolutelyPositionedObject) {
267
0
    return NS_OK;
268
0
  }
269
0
  nsresult rv = GetPositionAndDimensions(*mAbsolutelyPositionedObject,
270
0
                                         mPositionedObjectX,
271
0
                                         mPositionedObjectY,
272
0
                                         mPositionedObjectWidth,
273
0
                                         mPositionedObjectHeight,
274
0
                                         mPositionedObjectBorderLeft,
275
0
                                         mPositionedObjectBorderTop,
276
0
                                         mPositionedObjectMarginLeft,
277
0
                                         mPositionedObjectMarginTop);
278
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
279
0
    return rv;
280
0
  }
281
0
282
0
  SetAnonymousElementPosition(mPositionedObjectX + 12,
283
0
                              mPositionedObjectY - 14,
284
0
                              mGrabber);
285
0
  return NS_OK;
286
0
}
287
288
void
289
HTMLEditor::HideGrabberInternal()
290
0
{
291
0
  if (NS_WARN_IF(!mAbsolutelyPositionedObject)) {
292
0
    return;
293
0
  }
294
0
295
0
  // Move all members to the local variables first since mutation event
296
0
  // listener may try to show grabber while we're hiding them.
297
0
  RefPtr<Element> absolutePositioningObject =
298
0
    std::move(mAbsolutelyPositionedObject);
299
0
  ManualNACPtr grabber = std::move(mGrabber);
300
0
  ManualNACPtr positioningShadow = std::move(mPositioningShadow);
301
0
302
0
  DebugOnly<nsresult> rv =
303
0
    absolutePositioningObject->UnsetAttr(kNameSpaceID_None,
304
0
                                         nsGkAtoms::_moz_abspos,
305
0
                                         true);
306
0
  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to unset the attribute");
307
0
308
0
  // We allow the pres shell to be null; when it is, we presume there
309
0
  // are no document observers to notify, but we still want to
310
0
  // UnbindFromTree.
311
0
  nsCOMPtr<nsIPresShell> presShell = GetPresShell();
312
0
  if (grabber) {
313
0
    DeleteRefToAnonymousNode(std::move(grabber), presShell);
314
0
  }
315
0
  if (positioningShadow) {
316
0
    DeleteRefToAnonymousNode(std::move(positioningShadow), presShell);
317
0
  }
318
0
}
319
320
nsresult
321
HTMLEditor::ShowGrabberInternal(Element& aElement)
322
0
{
323
0
  if (NS_WARN_IF(!IsDescendantOfEditorRoot(&aElement))) {
324
0
    return NS_ERROR_UNEXPECTED;
325
0
  }
326
0
327
0
  if (NS_WARN_IF(mGrabber)) {
328
0
    return NS_ERROR_UNEXPECTED;
329
0
  }
330
0
331
0
  nsAutoString classValue;
332
0
  nsresult rv =
333
0
    GetTemporaryStyleForFocusedPositionedElement(aElement, classValue);
334
0
  NS_ENSURE_SUCCESS(rv, rv);
335
0
336
0
  rv = aElement.SetAttr(kNameSpaceID_None, nsGkAtoms::_moz_abspos,
337
0
                        classValue, true);
338
0
  NS_ENSURE_SUCCESS(rv, rv);
339
0
340
0
  mAbsolutelyPositionedObject = &aElement;
341
0
342
0
  nsIContent* parentContent = aElement.GetParent();
343
0
  if (NS_WARN_IF(!parentContent)) {
344
0
    return NS_ERROR_FAILURE;
345
0
  }
346
0
347
0
  if (NS_WARN_IF(!CreateGrabberInternal(*parentContent))) {
348
0
    return NS_ERROR_FAILURE;
349
0
  }
350
0
351
0
  // If we succeeded to create the grabber, HideGrabberInternal() hasn't been
352
0
  // called yet.  So, mAbsolutelyPositionedObject should be non-nullptr.
353
0
  MOZ_ASSERT(mAbsolutelyPositionedObject);
354
0
355
0
  mHasShownGrabber = true;
356
0
357
0
  // Finally, move the grabber to proper position.
358
0
  rv = RefreshGrabberInternal();
359
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
360
0
    return rv;
361
0
  }
362
0
  return NS_OK;
363
0
}
364
365
nsresult
366
HTMLEditor::StartMoving()
367
0
{
368
0
  nsCOMPtr<nsIContent> parentContent = mGrabber->GetParent();
369
0
  if (NS_WARN_IF(!parentContent) || NS_WARN_IF(!mAbsolutelyPositionedObject)) {
370
0
    return NS_ERROR_FAILURE;
371
0
  }
372
0
373
0
  // now, let's create the resizing shadow
374
0
  mPositioningShadow =
375
0
    CreateShadow(*parentContent, *mAbsolutelyPositionedObject);
376
0
  if (NS_WARN_IF(!mPositioningShadow) ||
377
0
      NS_WARN_IF(!mAbsolutelyPositionedObject)) {
378
0
    return NS_ERROR_FAILURE;
379
0
  }
380
0
  nsresult rv = SetShadowPosition(*mPositioningShadow,
381
0
                                  *mAbsolutelyPositionedObject,
382
0
                                  mPositionedObjectX, mPositionedObjectY);
383
0
  NS_ENSURE_SUCCESS(rv, rv);
384
0
385
0
  // make the shadow appear
386
0
  mPositioningShadow->UnsetAttr(kNameSpaceID_None, nsGkAtoms::_class, true);
387
0
388
0
  // position it
389
0
  mCSSEditUtils->SetCSSPropertyPixels(*mPositioningShadow, *nsGkAtoms::width,
390
0
                                      mPositionedObjectWidth);
391
0
  mCSSEditUtils->SetCSSPropertyPixels(*mPositioningShadow, *nsGkAtoms::height,
392
0
                                      mPositionedObjectHeight);
393
0
394
0
  mIsMoving = true;
395
0
  return NS_OK; // XXX Looks like nobody refers this result
396
0
}
397
398
void
399
HTMLEditor::SnapToGrid(int32_t& newX, int32_t& newY)
400
0
{
401
0
  if (mSnapToGridEnabled && mGridSize) {
402
0
    newX = (int32_t) floor( ((float)newX / (float)mGridSize) + 0.5f ) * mGridSize;
403
0
    newY = (int32_t) floor( ((float)newY / (float)mGridSize) + 0.5f ) * mGridSize;
404
0
  }
405
0
}
406
407
nsresult
408
HTMLEditor::GrabberClicked()
409
0
{
410
0
  // add a mouse move listener to the editor
411
0
  nsresult rv = NS_OK;
412
0
  if (!mMouseMotionListenerP) {
413
0
    EventTarget* eventTarget = GetDOMEventTarget();
414
0
    if (NS_WARN_IF(!eventTarget)) {
415
0
      return NS_ERROR_FAILURE;
416
0
    }
417
0
    mMouseMotionListenerP = new ResizerMouseMotionListener(*this);
418
0
    EventListenerManager* eventListenerManager =
419
0
      eventTarget->GetOrCreateListenerManager();
420
0
    eventListenerManager->AddEventListenerByType(
421
0
                            mMouseMotionListenerP,
422
0
                            NS_LITERAL_STRING("mousemove"),
423
0
                            TrustedEventsAtSystemGroupBubble());
424
0
  }
425
0
  mGrabberClicked = true;
426
0
  return rv;
427
0
}
428
429
nsresult
430
HTMLEditor::EndMoving()
431
0
{
432
0
  if (mPositioningShadow) {
433
0
    nsCOMPtr<nsIPresShell> ps = GetPresShell();
434
0
    NS_ENSURE_TRUE(ps, NS_ERROR_NOT_INITIALIZED);
435
0
436
0
    DeleteRefToAnonymousNode(std::move(mPositioningShadow), ps);
437
0
438
0
    mPositioningShadow = nullptr;
439
0
  }
440
0
441
0
  EventTarget* eventTarget = GetDOMEventTarget();
442
0
  if (eventTarget && mMouseMotionListenerP) {
443
0
    EventListenerManager* eventListenerManager =
444
0
      eventTarget->GetOrCreateListenerManager();
445
0
    eventListenerManager->RemoveEventListenerByType(
446
0
                            mMouseMotionListenerP,
447
0
                            NS_LITERAL_STRING("mousemove"),
448
0
                            TrustedEventsAtSystemGroupBubble());
449
0
  }
450
0
  mMouseMotionListenerP = nullptr;
451
0
452
0
  mGrabberClicked = false;
453
0
  mIsMoving = false;
454
0
  RefPtr<Selection> selection = GetSelection();
455
0
  if (!selection) {
456
0
    return NS_ERROR_NOT_INITIALIZED;
457
0
  }
458
0
  nsresult rv = RefereshEditingUI(*selection);
459
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
460
0
    return rv;
461
0
  }
462
0
  return NS_OK;
463
0
}
464
nsresult
465
HTMLEditor::SetFinalPosition(int32_t aX,
466
                             int32_t aY)
467
0
{
468
0
  nsresult rv = EndMoving();
469
0
  NS_ENSURE_SUCCESS(rv, rv);
470
0
471
0
  // we have now to set the new width and height of the resized object
472
0
  // we don't set the x and y position because we don't control that in
473
0
  // a normal HTML layout
474
0
  int32_t newX = mPositionedObjectX + aX - mOriginalX - (mPositionedObjectBorderLeft+mPositionedObjectMarginLeft);
475
0
  int32_t newY = mPositionedObjectY + aY - mOriginalY - (mPositionedObjectBorderTop+mPositionedObjectMarginTop);
476
0
477
0
  SnapToGrid(newX, newY);
478
0
479
0
  nsAutoString x, y;
480
0
  x.AppendInt(newX);
481
0
  y.AppendInt(newY);
482
0
483
0
  // we want one transaction only from a user's point of view
484
0
  AutoPlaceholderBatch batchIt(this);
485
0
486
0
  if (NS_WARN_IF(!mAbsolutelyPositionedObject)) {
487
0
    return NS_ERROR_FAILURE;
488
0
  }
489
0
  OwningNonNull<Element> absolutelyPositionedObject =
490
0
    *mAbsolutelyPositionedObject;
491
0
  mCSSEditUtils->SetCSSPropertyPixels(*absolutelyPositionedObject,
492
0
                                      *nsGkAtoms::top, newY);
493
0
  mCSSEditUtils->SetCSSPropertyPixels(*absolutelyPositionedObject,
494
0
                                      *nsGkAtoms::left, newX);
495
0
  // keep track of that size
496
0
  mPositionedObjectX  = newX;
497
0
  mPositionedObjectY  = newY;
498
0
499
0
  rv = RefreshResizers();
500
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
501
0
    return rv;
502
0
  }
503
0
  return NS_OK;
504
0
}
505
506
void
507
HTMLEditor::AddPositioningOffset(int32_t& aX,
508
                                 int32_t& aY)
509
0
{
510
0
  // Get the positioning offset
511
0
  int32_t positioningOffset =
512
0
    Preferences::GetInt("editor.positioning.offset", 0);
513
0
514
0
  aX += positioningOffset;
515
0
  aY += positioningOffset;
516
0
}
517
518
nsresult
519
HTMLEditor::SetPositionToAbsoluteOrStatic(Element& aElement,
520
                                          bool aEnabled)
521
0
{
522
0
  nsAutoString positionStr;
523
0
  CSSEditUtils::GetComputedProperty(aElement, *nsGkAtoms::position,
524
0
                                    positionStr);
525
0
  bool isPositioned = (positionStr.EqualsLiteral("absolute"));
526
0
527
0
  // nothing to do if the element is already in the state we want
528
0
  if (isPositioned == aEnabled) {
529
0
    return NS_OK;
530
0
  }
531
0
532
0
  if (aEnabled) {
533
0
    return SetPositionToAbsolute(aElement);
534
0
  }
535
0
536
0
  return SetPositionToStatic(aElement);
537
0
}
538
539
nsresult
540
HTMLEditor::SetPositionToAbsolute(Element& aElement)
541
0
{
542
0
  AutoPlaceholderBatch batchIt(this);
543
0
544
0
  int32_t x, y;
545
0
  GetElementOrigin(aElement, x, y);
546
0
547
0
  mCSSEditUtils->SetCSSProperty(aElement, *nsGkAtoms::position,
548
0
                                NS_LITERAL_STRING("absolute"));
549
0
550
0
  AddPositioningOffset(x, y);
551
0
  SnapToGrid(x, y);
552
0
  SetTopAndLeft(aElement, x, y);
553
0
554
0
  // we may need to create a br if the positioned element is alone in its
555
0
  // container
556
0
  nsINode* parentNode = aElement.GetParentNode();
557
0
  if (parentNode->GetChildCount() == 1) {
558
0
    RefPtr<Selection> selection = GetSelection();
559
0
    if (NS_WARN_IF(!selection)) {
560
0
      return NS_ERROR_FAILURE;
561
0
    }
562
0
    RefPtr<Element> newBrElement =
563
0
      InsertBrElementWithTransaction(*selection,
564
0
                                     EditorRawDOMPoint(parentNode, 0));
565
0
    if (NS_WARN_IF(!newBrElement)) {
566
0
      return NS_ERROR_FAILURE;
567
0
    }
568
0
  }
569
0
  return NS_OK;
570
0
}
571
572
nsresult
573
HTMLEditor::SetPositionToStatic(Element& aElement)
574
0
{
575
0
  AutoPlaceholderBatch batchIt(this);
576
0
577
0
  mCSSEditUtils->RemoveCSSProperty(aElement, *nsGkAtoms::position,
578
0
                                   EmptyString());
579
0
  mCSSEditUtils->RemoveCSSProperty(aElement, *nsGkAtoms::top,
580
0
                                   EmptyString());
581
0
  mCSSEditUtils->RemoveCSSProperty(aElement, *nsGkAtoms::left,
582
0
                                   EmptyString());
583
0
  mCSSEditUtils->RemoveCSSProperty(aElement, *nsGkAtoms::z_index,
584
0
                                   EmptyString());
585
0
586
0
  if (!HTMLEditUtils::IsImage(&aElement)) {
587
0
    mCSSEditUtils->RemoveCSSProperty(aElement, *nsGkAtoms::width,
588
0
                                     EmptyString());
589
0
    mCSSEditUtils->RemoveCSSProperty(aElement, *nsGkAtoms::height,
590
0
                                     EmptyString());
591
0
  }
592
0
593
0
  if (aElement.IsHTMLElement(nsGkAtoms::div) &&
594
0
      !HasStyleOrIdOrClass(&aElement)) {
595
0
    RefPtr<HTMLEditRules> htmlRules =
596
0
      static_cast<HTMLEditRules*>(mRules.get());
597
0
    NS_ENSURE_TRUE(htmlRules, NS_ERROR_FAILURE);
598
0
    nsresult rv = htmlRules->MakeSureElemStartsAndEndsOnCR(aElement);
599
0
    NS_ENSURE_SUCCESS(rv, rv);
600
0
    rv = RemoveContainerWithTransaction(aElement);
601
0
    NS_ENSURE_SUCCESS(rv, rv);
602
0
  }
603
0
  return NS_OK;
604
0
}
605
606
NS_IMETHODIMP
607
HTMLEditor::SetSnapToGridEnabled(bool aEnabled)
608
0
{
609
0
  mSnapToGridEnabled = aEnabled;
610
0
  return NS_OK;
611
0
}
612
613
NS_IMETHODIMP
614
HTMLEditor::GetSnapToGridEnabled(bool* aIsEnabled)
615
0
{
616
0
  *aIsEnabled = mSnapToGridEnabled;
617
0
  return NS_OK;
618
0
}
619
620
NS_IMETHODIMP
621
HTMLEditor::SetGridSize(uint32_t aSize)
622
0
{
623
0
  mGridSize = aSize;
624
0
  return NS_OK;
625
0
}
626
627
NS_IMETHODIMP
628
HTMLEditor::GetGridSize(uint32_t* aSize)
629
0
{
630
0
  *aSize = mGridSize;
631
0
  return NS_OK;
632
0
}
633
634
// self-explanatory
635
void
636
HTMLEditor::SetTopAndLeft(Element& aElement,
637
                          int32_t aX,
638
                          int32_t aY)
639
0
{
640
0
  AutoPlaceholderBatch batchIt(this);
641
0
  mCSSEditUtils->SetCSSPropertyPixels(aElement, *nsGkAtoms::left, aX);
642
0
  mCSSEditUtils->SetCSSPropertyPixels(aElement, *nsGkAtoms::top, aY);
643
0
}
644
645
nsresult
646
HTMLEditor::GetTemporaryStyleForFocusedPositionedElement(Element& aElement,
647
                                                         nsAString& aReturn)
648
0
{
649
0
  // we are going to outline the positioned element and bring it to the
650
0
  // front to overlap any other element intersecting with it. But
651
0
  // first, let's see what's the background and foreground colors of the
652
0
  // positioned element.
653
0
  // if background-image computed value is 'none,
654
0
  //   If the background color is 'auto' and R G B values of the foreground are
655
0
  //       each above #d0, use a black background
656
0
  //   If the background color is 'auto' and at least one of R G B values of
657
0
  //       the foreground is below #d0, use a white background
658
0
  // Otherwise don't change background/foreground
659
0
  aReturn.Truncate();
660
0
661
0
  nsAutoString bgImageStr;
662
0
  nsresult rv =
663
0
    CSSEditUtils::GetComputedProperty(aElement, *nsGkAtoms::background_image,
664
0
                                      bgImageStr);
665
0
  NS_ENSURE_SUCCESS(rv, rv);
666
0
  if (!bgImageStr.EqualsLiteral("none")) {
667
0
    return NS_OK;
668
0
  }
669
0
670
0
  nsAutoString bgColorStr;
671
0
  rv =
672
0
    CSSEditUtils::GetComputedProperty(aElement, *nsGkAtoms::backgroundColor,
673
0
                                      bgColorStr);
674
0
  NS_ENSURE_SUCCESS(rv, rv);
675
0
  if (!bgColorStr.EqualsLiteral("rgba(0, 0, 0, 0)")) {
676
0
    return NS_OK;
677
0
  }
678
0
679
0
  RefPtr<ComputedStyle> style =
680
0
    nsComputedDOMStyle::GetComputedStyle(&aElement, nullptr);
681
0
  NS_ENSURE_STATE(style);
682
0
683
0
  const uint8_t kBlackBgTrigger = 0xd0;
684
0
685
0
  nscolor color = style->StyleColor()->mColor;
686
0
  if (NS_GET_R(color) >= kBlackBgTrigger &&
687
0
      NS_GET_G(color) >= kBlackBgTrigger &&
688
0
      NS_GET_B(color) >= kBlackBgTrigger) {
689
0
    aReturn.AssignLiteral("black");
690
0
  } else {
691
0
    aReturn.AssignLiteral("white");
692
0
  }
693
0
694
0
  return NS_OK;
695
0
}
696
697
} // namespace mozilla