Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/layout/generic/nsFrameSelection.h
Line
Count
Source (jump to first uncovered line)
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
#ifndef nsFrameSelection_h___
8
#define nsFrameSelection_h___
9
10
#include "mozilla/Attributes.h"
11
#include "mozilla/EventForwards.h"
12
#include "mozilla/dom/Selection.h"
13
#include "mozilla/TextRange.h"
14
#include "mozilla/UniquePtr.h"
15
#include "nsIFrame.h"
16
#include "nsIContent.h"
17
#include "nsISelectionController.h"
18
#include "nsISelectionListener.h"
19
#include "nsITableCellLayout.h"
20
#include "WordMovementType.h"
21
#include "CaretAssociationHint.h"
22
#include "nsBidiPresUtils.h"
23
24
class nsRange;
25
26
0
#define BIDI_LEVEL_UNDEFINED 0x80
27
28
//----------------------------------------------------------------------
29
30
// Selection interface
31
32
struct SelectionDetails
33
{
34
  SelectionDetails()
35
    : mStart()
36
    , mEnd()
37
0
    , mSelectionType(mozilla::SelectionType::eInvalid) {
38
0
    MOZ_COUNT_CTOR(SelectionDetails);
39
0
  }
40
#ifdef NS_BUILD_REFCNT_LOGGING
41
  ~SelectionDetails() {
42
    MOZ_COUNT_DTOR(SelectionDetails);
43
  }
44
#endif
45
  int32_t mStart;
46
  int32_t mEnd;
47
  mozilla::SelectionType mSelectionType;
48
  mozilla::TextRangeStyle mTextRangeStyle;
49
  mozilla::UniquePtr<SelectionDetails> mNext;
50
};
51
52
struct SelectionCustomColors
53
{
54
#ifdef NS_BUILD_REFCNT_LOGGING
55
  SelectionCustomColors()
56
  {
57
    MOZ_COUNT_CTOR(SelectionCustomColors);
58
  }
59
  ~SelectionCustomColors()
60
  {
61
    MOZ_COUNT_DTOR(SelectionCustomColors);
62
  }
63
#endif
64
  mozilla::Maybe<nscolor> mForegroundColor;
65
  mozilla::Maybe<nscolor> mBackgroundColor;
66
  mozilla::Maybe<nscolor> mAltForegroundColor;
67
  mozilla::Maybe<nscolor> mAltBackgroundColor;
68
};
69
70
class nsIPresShell;
71
72
/** PeekOffsetStruct is used to group various arguments (both input and output)
73
 *  that are passed to nsFrame::PeekOffset(). See below for the description of
74
 *  individual arguments.
75
 */
76
struct MOZ_STACK_CLASS nsPeekOffsetStruct
77
{
78
  nsPeekOffsetStruct(nsSelectionAmount aAmount,
79
                     nsDirection aDirection,
80
                     int32_t aStartOffset,
81
                     nsPoint aDesiredPos,
82
                     bool aJumpLines,
83
                     bool aScrollViewStop,
84
                     bool aIsKeyboardSelect,
85
                     bool aVisual,
86
                     bool aExtend,
87
                     mozilla::EWordMovementType aWordMovementType = mozilla::eDefaultBehavior);
88
89
  // Note: Most arguments (input and output) are only used with certain values
90
  // of mAmount. These values are indicated for each argument below.
91
  // Arguments with no such indication are used with all values of mAmount.
92
93
  /*** Input arguments ***/
94
  // Note: The value of some of the input arguments may be changed upon exit.
95
96
  // mAmount: The type of movement requested (by character, word, line, etc.)
97
  nsSelectionAmount mAmount;
98
99
  // mDirection: eDirPrevious or eDirNext.
100
  //             * Note for visual bidi movement:
101
  //             eDirPrevious means 'left-then-up' if the containing block is LTR,
102
  //             'right-then-up' if it is RTL.
103
  //             eDirNext means 'right-then-down' if the containing block is LTR,
104
  //             'left-then-down' if it is RTL.
105
  //             Between paragraphs, eDirPrevious means "go to the visual end of the
106
  //             previous paragraph", and eDirNext means "go to the visual beginning
107
  //             of the next paragraph".
108
  //             Used with: eSelectCharacter, eSelectWord, eSelectLine, eSelectParagraph.
109
  nsDirection mDirection;
110
111
  // mStartOffset: Offset into the content of the current frame where the peek starts.
112
  //               Used with: eSelectCharacter, eSelectWord
113
  int32_t mStartOffset;
114
115
  // mDesiredPos: The desired inline coordinate for the caret
116
  //              (one of .x or .y will be used, depending on line's writing mode)
117
  //              Used with: eSelectLine.
118
  nsPoint mDesiredPos;
119
120
  // mWordMovementType: An enum that determines whether to prefer the start or end of a word
121
  //                    or to use the default beahvior, which is a combination of
122
  //                    direction and the platform-based pref
123
  //                    "layout.word_select.eat_space_to_next_word"
124
  mozilla::EWordMovementType mWordMovementType;
125
126
  // mJumpLines: Whether to allow jumping across line boundaries.
127
  //             Used with: eSelectCharacter, eSelectWord.
128
  bool mJumpLines;
129
130
  // mScrollViewStop: Whether to stop when reaching a scroll view boundary.
131
  //                  Used with: eSelectCharacter, eSelectWord, eSelectLine.
132
  bool mScrollViewStop;
133
134
  // mIsKeyboardSelect: Whether the peeking is done in response to a keyboard action.
135
  //                    Used with: eSelectWord.
136
  bool mIsKeyboardSelect;
137
138
  // mVisual: Whether bidi caret behavior is visual (true) or logical (false).
139
  //          Used with: eSelectCharacter, eSelectWord, eSelectBeginLine, eSelectEndLine.
140
  bool mVisual;
141
142
  // mExtend: Whether the selection is being extended or moved.
143
  bool mExtend;
144
145
  /*** Output arguments ***/
146
147
  // mResultContent: Content reached as a result of the peek.
148
  nsCOMPtr<nsIContent> mResultContent;
149
150
  // mResultFrame: Frame reached as a result of the peek.
151
  //               Used with: eSelectCharacter, eSelectWord.
152
  nsIFrame *mResultFrame;
153
154
  // mContentOffset: Offset into content reached as a result of the peek.
155
  int32_t mContentOffset;
156
157
  // mAttachForward: When the result position is between two frames,
158
  //                 indicates which of the two frames the caret should be painted in.
159
  //                 false means "the end of the frame logically before the caret",
160
  //                 true means "the beginning of the frame logically after the caret".
161
  //                 Used with: eSelectLine, eSelectBeginLine, eSelectEndLine.
162
  mozilla::CaretAssociationHint mAttach;
163
};
164
165
struct nsPrevNextBidiLevels
166
{
167
  void SetData(nsIFrame* aFrameBefore,
168
               nsIFrame* aFrameAfter,
169
               nsBidiLevel aLevelBefore,
170
               nsBidiLevel aLevelAfter)
171
0
  {
172
0
    mFrameBefore = aFrameBefore;
173
0
    mFrameAfter = aFrameAfter;
174
0
    mLevelBefore = aLevelBefore;
175
0
    mLevelAfter = aLevelAfter;
176
0
  }
177
  nsIFrame* mFrameBefore;
178
  nsIFrame* mFrameAfter;
179
  nsBidiLevel mLevelBefore;
180
  nsBidiLevel mLevelAfter;
181
};
182
183
namespace mozilla {
184
class SelectionChangeEventDispatcher;
185
namespace dom {
186
class Selection;
187
} // namespace dom
188
189
/**
190
 * Constants for places that want to handle table selections.  These
191
 * indicate what part of a table is being selected.
192
 */
193
enum class TableSelection : uint32_t {
194
  None, /* Nothing being selected; not valid in all cases. */
195
  Cell, /* A cell is being selected. */
196
  Row,  /* A row is being selected. */
197
  Column, /* A column is being selected. */
198
  Table, /* A table (including cells and captions) is being selected. */
199
  AllCells, /* All the cells in a table are being selected. */
200
};
201
202
} // namespace mozilla
203
class nsIScrollableFrame;
204
205
/**
206
 * Methods which are marked with *unsafe* should be handled with special care.
207
 * They may cause nsFrameSelection to be deleted, if strong pointer isn't used,
208
 * or they may cause other objects to be deleted.
209
 */
210
class nsFrameSelection final
211
{
212
public:
213
  typedef mozilla::CaretAssociationHint CaretAssociateHint;
214
215
  /*interfaces for addref and release and queryinterface*/
216
217
  NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(nsFrameSelection)
218
  NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(nsFrameSelection)
219
220
  /** Init will initialize the frame selector with the necessary pres shell to
221
   *  be used by most of the methods
222
   *  @param aShell is the parameter to be used for most of the other calls for callbacks etc
223
   *  @param aLimiter limits the selection to nodes with aLimiter parents
224
   *  @param aAccessibleCaretEnabled true if we should enable the accessible caret.
225
   */
226
  void Init(nsIPresShell *aShell, nsIContent *aLimiter,
227
            bool aAccessibleCaretEnabled);
228
229
  /** HandleClick will take the focus to the new frame at the new offset and
230
   *  will either extend the selection from the old anchor, or replace the old anchor.
231
   *  the old anchor and focus position may also be used to deselect things
232
   *  @param aNewfocus is the content that wants the focus
233
   *  @param aContentOffset is the content offset of the parent aNewFocus
234
   *  @param aContentOffsetEnd is the content offset of the parent aNewFocus and is specified different
235
   *                           when you need to select to and include both start and end points
236
   *  @param aContinueSelection is the flag that tells the selection to keep the old anchor point or not.
237
   *  @param aMultipleSelection will tell the frame selector to replace /or not the old selection.
238
   *         cannot coexist with aContinueSelection
239
   *  @param aHint will tell the selection which direction geometrically to actually show the caret on.
240
   *         1 = end of this line 0 = beginning of this line
241
   */
242
  MOZ_CAN_RUN_SCRIPT_BOUNDARY
243
  nsresult HandleClick(nsIContent *aNewFocus,
244
                       uint32_t aContentOffset,
245
                       uint32_t aContentEndOffset,
246
                       bool aContinueSelection,
247
                       bool aMultipleSelection,
248
                       CaretAssociateHint aHint);
249
250
  /** HandleDrag extends the selection to contain the frame closest to aPoint.
251
   *  @param aPresContext is the context to use when figuring out what frame contains the point.
252
   *  @param aFrame is the parent of all frames to use when searching for the closest frame to the point.
253
   *  @param aPoint is relative to aFrame
254
   */
255
  /*unsafe*/
256
  void HandleDrag(nsIFrame* aFrame, const nsPoint& aPoint);
257
258
  /** HandleTableSelection will set selection to a table, cell, etc
259
   *   depending on information contained in aFlags
260
   *  @param aParentContent is the paretent of either a table or cell that user clicked or dragged the mouse in
261
   *  @param aContentOffset is the offset of the table or cell
262
   *  @param aTarget indicates what to select
263
   *    TableSelection::Cell     We should select a cell (content points to the cell)
264
   *    TableSelection::Row      We should select a row (content points to any cell in row)
265
   *    TableSelection::Column   We should select a row (content points to any cell in column)
266
   *    TableSelection::Table    We should select a table (content points to the table)
267
   *    TableSelection::AllCells We should select all cells (content points to any cell in table)
268
   *  @param aMouseEvent         passed in so we can get where event occurred and what keys are pressed
269
   */
270
  /*unsafe*/
271
  nsresult HandleTableSelection(nsINode* aParentContent,
272
                                int32_t aContentOffset,
273
                                mozilla::TableSelection aTarget,
274
                                mozilla::WidgetMouseEvent* aMouseEvent);
275
276
  /**
277
   * Add cell to the selection.
278
   *
279
   * @param  aCell  [in] HTML td element.
280
   */
281
  nsresult SelectCellElement(nsIContent *aCell);
282
283
  /**
284
   * Add cells to the selection inside of the given cells range.
285
   *
286
   * @param  aTable             [in] HTML table element
287
   * @param  aStartRowIndex     [in] row index where the cells range starts
288
   * @param  aStartColumnIndex  [in] column index where the cells range starts
289
   * @param  aEndRowIndex       [in] row index where the cells range ends
290
   * @param  aEndColumnIndex    [in] column index where the cells range ends
291
   */
292
  nsresult AddCellsToSelection(nsIContent* aTable,
293
                               int32_t aStartRowIndex,
294
                               int32_t aStartColumnIndex,
295
                               int32_t aEndRowIndex,
296
                               int32_t aEndColumnIndex);
297
298
  /**
299
   * Remove cells from selection inside of the given cell range.
300
   *
301
   * @param  aTable             [in] HTML table element
302
   * @param  aStartRowIndex     [in] row index where the cells range starts
303
   * @param  aStartColumnIndex  [in] column index where the cells range starts
304
   * @param  aEndRowIndex       [in] row index where the cells range ends
305
   * @param  aEndColumnIndex    [in] column index where the cells range ends
306
   */
307
  nsresult RemoveCellsFromSelection(nsIContent* aTable,
308
                                    int32_t aStartRowIndex,
309
                                    int32_t aStartColumnIndex,
310
                                    int32_t aEndRowIndex,
311
                                    int32_t aEndColumnIndex);
312
313
  /**
314
   * Remove cells from selection outside of the given cell range.
315
   *
316
   * @param  aTable             [in] HTML table element
317
   * @param  aStartRowIndex     [in] row index where the cells range starts
318
   * @param  aStartColumnIndex  [in] column index where the cells range starts
319
   * @param  aEndRowIndex       [in] row index where the cells range ends
320
   * @param  aEndColumnIndex    [in] column index where the cells range ends
321
   */
322
  nsresult RestrictCellsToSelection(nsIContent* aTable,
323
                                    int32_t aStartRowIndex,
324
                                    int32_t aStartColumnIndex,
325
                                    int32_t aEndRowIndex,
326
                                    int32_t aEndColumnIndex);
327
328
  /** StartAutoScrollTimer is responsible for scrolling frames so that
329
   *  aPoint is always visible, and for selecting any frame that contains
330
   *  aPoint. The timer will also reset itself to fire again if we have
331
   *  not scrolled to the end of the document.
332
   *  @param aFrame is the outermost frame to use when searching for
333
   *  the closest frame for the point, i.e. the frame that is capturing
334
   *  the mouse
335
   *  @param aPoint is relative to aFrame.
336
   *  @param aDelay is the timer's interval.
337
   */
338
  /*unsafe*/
339
  nsresult StartAutoScrollTimer(nsIFrame* aFrame,
340
                                const nsPoint& aPoint,
341
                                uint32_t aDelay);
342
343
  /** StopAutoScrollTimer stops any active auto scroll timer.
344
   */
345
  void StopAutoScrollTimer();
346
347
  /** Lookup Selection
348
   *  returns in frame coordinates the selection beginning and ending with the type of selection given
349
   * @param aContent is the content asking
350
   * @param aContentOffset is the starting content boundary
351
   * @param aContentLength is the length of the content piece asking
352
   * @param aSlowCheck will check using slow method with no shortcuts
353
   */
354
  mozilla::UniquePtr<SelectionDetails> LookUpSelection(nsIContent *aContent,
355
                                                       int32_t aContentOffset,
356
                                                       int32_t aContentLength,
357
                                                       bool aSlowCheck) const;
358
359
  /** SetDragState(bool);
360
   *  sets the drag state to aState for resons of drag state.
361
   * @param aState is the new state of drag
362
   */
363
  MOZ_CAN_RUN_SCRIPT_BOUNDARY
364
  void SetDragState(bool aState);
365
366
  /** GetDragState(bool *);
367
   *  gets the drag state to aState for resons of drag state.
368
   * @param aState will hold the state of drag
369
   */
370
0
  bool GetDragState() const { return mDragState; }
371
372
  /**
373
    if we are in table cell selection mode. aka ctrl click in table cell
374
   */
375
  bool GetTableCellSelection() const
376
0
  {
377
0
    return mSelectingTableCellMode != mozilla::TableSelection::None;
378
0
  }
379
  void ClearTableCellSelection()
380
0
  {
381
0
    mSelectingTableCellMode = mozilla::TableSelection::None;
382
0
  }
383
384
  /** GetSelection
385
   * no query interface for selection. must use this method now.
386
   * @param aSelectionType The selection type what you want.
387
   */
388
  mozilla::dom::Selection*
389
    GetSelection(mozilla::SelectionType aSelectionType) const;
390
391
  /**
392
   * ScrollSelectionIntoView scrolls a region of the selection,
393
   * so that it is visible in the scrolled view.
394
   *
395
   * @param aSelectionType the selection to scroll into view.
396
   * @param aRegion the region inside the selection to scroll into view.
397
   * @param aFlags the scroll flags.  Valid bits include:
398
   * SCROLL_SYNCHRONOUS: when set, scrolls the selection into view
399
   * before returning. If not set, posts a request which is processed
400
   * at some point after the method returns.
401
   * SCROLL_FIRST_ANCESTOR_ONLY: if set, only the first ancestor will be scrolled
402
   * into view.
403
   *
404
   */
405
  /*unsafe*/
406
  nsresult ScrollSelectionIntoView(mozilla::SelectionType aSelectionType,
407
                                   SelectionRegion aRegion,
408
                                   int16_t aFlags) const;
409
410
  /** RepaintSelection repaints the selected frames that are inside the selection
411
   *  specified by aSelectionType.
412
   * @param aSelectionType The selection type what you want to repaint.
413
   */
414
  nsresult RepaintSelection(mozilla::SelectionType aSelectionType);
415
416
  /** GetFrameForNodeOffset given a node and its child offset, return the nsIFrame and
417
   *  the offset into that frame.
418
   * @param aNode input parameter for the node to look at
419
   * @param aOffset offset into above node.
420
   * @param aReturnOffset will contain offset into frame.
421
   */
422
  nsIFrame* GetFrameForNodeOffset(nsIContent*        aNode,
423
                                  int32_t            aOffset,
424
                                  CaretAssociateHint aHint,
425
                                  int32_t*           aReturnOffset) const;
426
427
  /**
428
   * Scrolling then moving caret placement code in common to text areas and
429
   * content areas should be located in the implementer
430
   * This method will accept the following parameters and perform the scroll
431
   * and caret movement.  It remains for the caller to call the final
432
   * ScrollCaretIntoView if that called wants to be sure the caret is always
433
   * visible.
434
   *
435
   * @param aForward if true, scroll forward if not scroll backward
436
   * @param aExtend  if true, extend selection to the new point
437
   * @param aScrollableFrame the frame to scroll
438
   */
439
  /*unsafe*/
440
  void CommonPageMove(bool aForward,
441
                      bool aExtend,
442
                      nsIScrollableFrame* aScrollableFrame);
443
444
0
  void SetHint(CaretAssociateHint aHintRight) { mHint = aHintRight; }
445
0
  CaretAssociateHint GetHint() const { return mHint; }
446
447
  /**
448
   * SetCaretBidiLevel sets the caret bidi level.
449
   * @param aLevel the caret bidi level
450
   */
451
  void SetCaretBidiLevel(nsBidiLevel aLevel);
452
453
  /**
454
   * GetCaretBidiLevel gets the caret bidi level.
455
   */
456
  nsBidiLevel GetCaretBidiLevel() const;
457
458
  /**
459
   * UndefineCaretBidiLevel sets the caret bidi level to "undefined".
460
   */
461
  void UndefineCaretBidiLevel();
462
463
  /** PhysicalMove will generally be called from the nsiselectioncontroller implementations.
464
   *  the effect being the selection will move one unit 'aAmount' in the
465
   *  given aDirection.
466
   * @param aDirection  the direction to move the selection
467
   * @param aAmount     amount of movement (char/line; word/page; eol/doc)
468
   * @param aExtend     continue selection
469
   */
470
  /*unsafe*/
471
  nsresult PhysicalMove(int16_t aDirection, int16_t aAmount, bool aExtend);
472
473
  /** CharacterMove will generally be called from the nsiselectioncontroller implementations.
474
   *  the effect being the selection will move one character left or right.
475
   * @param aForward move forward in document.
476
   * @param aExtend continue selection
477
   */
478
  /*unsafe*/
479
  nsresult CharacterMove(bool aForward, bool aExtend);
480
481
  /** CharacterExtendForDelete extends the selection forward (logically) to
482
   * the next character cell, so that the selected cell can be deleted.
483
   */
484
  /*unsafe*/
485
  nsresult CharacterExtendForDelete();
486
487
  /** CharacterExtendForBackspace extends the selection backward (logically) to
488
   * the previous character cell, so that the selected cell can be deleted.
489
   */
490
  /*unsafe*/
491
  nsresult CharacterExtendForBackspace();
492
493
  /** WordMove will generally be called from the nsiselectioncontroller implementations.
494
   *  the effect being the selection will move one word left or right.
495
   * @param aForward move forward in document.
496
   * @param aExtend continue selection
497
   */
498
  /*unsafe*/
499
  nsresult WordMove(bool aForward, bool aExtend);
500
501
  /** WordExtendForDelete extends the selection backward or forward (logically) to the
502
   *  next word boundary, so that the selected word can be deleted.
503
   * @param aForward select forward in document.
504
   */
505
  /*unsafe*/
506
  nsresult WordExtendForDelete(bool aForward);
507
508
  /** LineMove will generally be called from the nsiselectioncontroller implementations.
509
   *  the effect being the selection will move one line up or down.
510
   * @param aForward move forward in document.
511
   * @param aExtend continue selection
512
   */
513
  /*unsafe*/
514
  nsresult LineMove(bool aForward, bool aExtend);
515
516
  /** IntraLineMove will generally be called from the nsiselectioncontroller implementations.
517
   *  the effect being the selection will move to beginning or end of line
518
   * @param aForward move forward in document.
519
   * @param aExtend continue selection
520
   */
521
  /*unsafe*/
522
  nsresult IntraLineMove(bool aForward, bool aExtend);
523
524
  /** Select All will generally be called from the nsiselectioncontroller implementations.
525
   *  it will select the whole doc
526
   */
527
  MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult SelectAll();
528
529
  /** Sets/Gets The display selection enum.
530
   */
531
0
  void SetDisplaySelection(int16_t aState) { mDisplaySelection = aState; }
532
0
  int16_t GetDisplaySelection() const { return mDisplaySelection; }
533
534
  /** This method can be used to store the data received during a MouseDown
535
   *  event so that we can place the caret during the MouseUp event.
536
   * @aMouseEvent the event received by the selection MouseDown
537
   *  handling method. A nullptr value can be use to tell this method
538
   *  that any data is storing is no longer valid.
539
   */
540
  void SetDelayedCaretData(mozilla::WidgetMouseEvent* aMouseEvent);
541
542
  /** Get the delayed MouseDown event data necessary to place the
543
   *  caret during MouseUp processing.
544
   * @return a pointer to the event received
545
   *  by the selection during MouseDown processing. It can be nullptr
546
   *  if the data is no longer valid.
547
   */
548
0
  bool HasDelayedCaretData() { return mDelayedMouseEventValid; }
549
  bool IsShiftDownInDelayedCaretData()
550
0
  {
551
0
    NS_ASSERTION(mDelayedMouseEventValid, "No valid delayed caret data");
552
0
    return mDelayedMouseEventIsShift;
553
0
  }
554
  uint32_t GetClickCountInDelayedCaretData()
555
0
  {
556
0
    NS_ASSERTION(mDelayedMouseEventValid, "No valid delayed caret data");
557
0
    return mDelayedMouseEventClickCount;
558
0
  }
559
560
  bool MouseDownRecorded()
561
0
  {
562
0
    return !GetDragState() &&
563
0
           HasDelayedCaretData() &&
564
0
           GetClickCountInDelayedCaretData() < 2;
565
0
  }
566
567
  /** Get the content node that limits the selection
568
   *  When searching up a nodes for parents, as in a text edit field
569
   *    in an browser page, we must stop at this node else we reach into the
570
   *    parent page, which is very bad!
571
   */
572
0
  nsIContent* GetLimiter() const { return mLimiter; }
573
574
0
  nsIContent* GetAncestorLimiter() const { return mAncestorLimiter; }
575
  MOZ_CAN_RUN_SCRIPT_BOUNDARY void SetAncestorLimiter(nsIContent* aLimiter);
576
577
  /** This will tell the frame selection that a double click has been pressed
578
   *  so it can track abort future drags if inside the same selection
579
   *  @aDoubleDown has the double click down happened
580
   */
581
0
  void SetMouseDoubleDown(bool aDoubleDown) { mMouseDoubleDownState = aDoubleDown; }
582
583
  /** This will return whether the double down flag was set.
584
   *  @return whether the double down flag was set
585
   */
586
0
  bool GetMouseDoubleDown() const { return mMouseDoubleDownState; }
587
588
  /**
589
   * GetPrevNextBidiLevels will return the frames and associated Bidi levels of the characters
590
   *   logically before and after a (collapsed) selection.
591
   *  @param aNode is the node containing the selection
592
   *  @param aContentOffset is the offset of the selection in the node
593
   *  @param aJumpLines If true, look across line boundaries.
594
   *                    If false, behave as if there were base-level frames at line edges.
595
   *
596
   *  @return A struct holding the before/after frame and the before/after level.
597
   *
598
   *  At the beginning and end of each line there is assumed to be a frame with
599
   *   Bidi level equal to the paragraph embedding level.
600
   *  In these cases the before frame and after frame respectively will be
601
   *   nullptr.
602
   */
603
  nsPrevNextBidiLevels GetPrevNextBidiLevels(nsIContent* aNode,
604
                                             uint32_t aContentOffset,
605
                                             bool aJumpLines) const;
606
607
  /** GetFrameFromLevel will scan in a given direction
608
   *   until it finds a frame with a Bidi level less than or equal to a given level.
609
   *   It will return the last frame before this.
610
   *  @param aPresContext is the context to use
611
   *  @param aFrameIn is the frame to start from
612
   *  @param aDirection is the direction to scan
613
   *  @param aBidiLevel is the level to search for
614
   *  @param aFrameOut will hold the frame returned
615
   */
616
  nsresult GetFrameFromLevel(nsIFrame *aFrameIn,
617
                             nsDirection aDirection,
618
                             nsBidiLevel aBidiLevel,
619
                             nsIFrame **aFrameOut) const;
620
621
  /**
622
   * MaintainSelection will track the current selection as being "sticky".
623
   * Dragging or extending selection will never allow for a subset
624
   * (or the whole) of the maintained selection to become unselected.
625
   * Primary use: double click selecting then dragging on second click
626
   * @param aAmount the initial amount of text selected (word, line or paragraph).
627
   *                For "line", use eSelectBeginLine.
628
   */
629
  nsresult MaintainSelection(nsSelectionAmount aAmount = eSelectNoAmount);
630
631
  nsresult ConstrainFrameAndPointToAnchorSubtree(nsIFrame* aFrame,
632
                                                 const nsPoint& aPoint,
633
                                                 nsIFrame** aRetFrame,
634
                                                 nsPoint& aRetPoint);
635
636
  nsFrameSelection();
637
638
  void StartBatchChanges();
639
640
  MOZ_CAN_RUN_SCRIPT_BOUNDARY
641
  void EndBatchChanges(int16_t aReason = nsISelectionListener::NO_REASON);
642
643
  /*unsafe*/
644
  nsresult DeleteFromDocument();
645
646
0
  nsIPresShell *GetShell()const  { return mShell; }
647
648
  void DisconnectFromPresShell();
649
  nsresult ClearNormalSelection();
650
651
private:
652
  ~nsFrameSelection();
653
654
  MOZ_CAN_RUN_SCRIPT
655
  nsresult TakeFocus(nsIContent *aNewFocus,
656
                     uint32_t aContentOffset,
657
                     uint32_t aContentEndOffset,
658
                     CaretAssociateHint aHint,
659
                     bool aContinueSelection,
660
                     bool aMultipleSelection);
661
662
  void BidiLevelFromMove(nsIPresShell* aPresShell,
663
                         nsIContent *aNode,
664
                         uint32_t aContentOffset,
665
                         nsSelectionAmount aAmount,
666
                         CaretAssociateHint aHint);
667
  void BidiLevelFromClick(nsIContent *aNewFocus, uint32_t aContentOffset);
668
  nsPrevNextBidiLevels GetPrevNextBidiLevels(nsIContent *aNode,
669
                                             uint32_t aContentOffset,
670
                                             CaretAssociateHint aHint,
671
                                             bool aJumpLines) const;
672
673
  bool AdjustForMaintainedSelection(nsIContent *aContent, int32_t aOffset);
674
675
// post and pop reasons for notifications. we may stack these later
676
0
  void    PostReason(int16_t aReason) { mSelectionChangeReason = aReason; }
677
  int16_t PopReason()
678
0
  {
679
0
    int16_t retval = mSelectionChangeReason;
680
0
    mSelectionChangeReason = nsISelectionListener::NO_REASON;
681
0
    return retval;
682
0
  }
683
  bool IsUserSelectionReason() const
684
0
  {
685
0
    return (mSelectionChangeReason &
686
0
            (nsISelectionListener::DRAG_REASON |
687
0
             nsISelectionListener::MOUSEDOWN_REASON |
688
0
             nsISelectionListener::MOUSEUP_REASON |
689
0
             nsISelectionListener::KEYPRESS_REASON)) !=
690
0
           nsISelectionListener::NO_REASON;
691
0
  }
692
693
  friend class mozilla::dom::Selection;
694
  friend class mozilla::SelectionChangeEventDispatcher;
695
  friend struct mozilla::AutoPrepareFocusRange;
696
#ifdef DEBUG
697
  void printSelection();       // for debugging
698
#endif /* DEBUG */
699
700
  void ResizeBuffer(uint32_t aNewBufSize);
701
702
/*HELPER METHODS*/
703
  // Whether MoveCaret should use logical or visual movement,
704
  // or follow the bidi.edit.caret_movement_style preference.
705
  enum CaretMovementStyle {
706
    eLogical,
707
    eVisual,
708
    eUsePrefStyle
709
  };
710
  MOZ_CAN_RUN_SCRIPT_BOUNDARY
711
  nsresult     MoveCaret(nsDirection aDirection, bool aContinueSelection,
712
                         nsSelectionAmount aAmount,
713
                         CaretMovementStyle aMovementStyle);
714
715
  nsresult     FetchDesiredPos(nsPoint &aDesiredPos); //the position requested by the Key Handling for up down
716
  void         InvalidateDesiredPos(); //do not listen to mDesiredPos you must get another.
717
  void         SetDesiredPos(nsPoint aPos); //set the mDesiredPos
718
719
0
  uint32_t     GetBatching() const {return mBatching; }
720
0
  bool         GetNotifyFrames() const { return mNotifyFrames; }
721
0
  void         SetDirty(bool aDirty=true){if (mBatching) mChangesDuringBatching = aDirty;}
722
723
  // nsFrameSelection may get deleted when calling this,
724
  // so remember to use nsCOMPtr when needed.
725
  MOZ_CAN_RUN_SCRIPT
726
  nsresult     NotifySelectionListeners(mozilla::SelectionType aSelectionType);
727
  // Update the selection cache on repaint when the
728
  // selection being repainted is not empty.
729
  nsresult     UpdateSelectionCacheOnRepaintSelection(mozilla::dom::
730
                                                      Selection* aSel);
731
732
  // Table selection support.
733
  nsITableCellLayout* GetCellLayout(nsIContent *aCellContent) const;
734
735
  nsresult SelectBlockOfCells(nsIContent *aStartNode, nsIContent *aEndNode);
736
  nsresult SelectRowOrColumn(nsIContent *aCellContent,
737
                             mozilla::TableSelection aTarget);
738
  nsresult UnselectCells(nsIContent *aTable,
739
                         int32_t aStartRowIndex, int32_t aStartColumnIndex,
740
                         int32_t aEndRowIndex, int32_t aEndColumnIndex,
741
                         bool aRemoveOutsideOfCellRange);
742
743
  nsresult GetCellIndexes(nsIContent *aCell, int32_t &aRowIndex, int32_t &aColIndex);
744
745
  // Get our first range, if its first selected node is a cell.  If this does
746
  // not return null, then the first node in the returned range is a cell
747
  // (according to GetFirstCellNodeInRange).
748
  nsRange* GetFirstCellRange();
749
  // Get our next range, if its first selected node is a cell.  If this does
750
  // not return null, then the first node in the returned range is a cell
751
  // (according to GetFirstCellNodeInRange).
752
  nsRange* GetNextCellRange();
753
  nsIContent* GetFirstCellNodeInRange(nsRange *aRange) const;
754
  // Returns non-null table if in same table, null otherwise
755
  nsIContent* IsInSameTable(nsIContent *aContent1, nsIContent *aContent2) const;
756
  // Might return null
757
  nsIContent* GetParentTable(nsIContent *aCellNode) const;
758
  nsresult CreateAndAddRange(nsINode* aContainer, int32_t aOffset);
759
760
  ////////////BEGIN nsFrameSelection members
761
762
  RefPtr<mozilla::dom::Selection>
763
    mDomSelections[
764
      sizeof(mozilla::kPresentSelectionTypes) / sizeof(mozilla::SelectionType)];
765
766
  nsCOMPtr<nsINode> mCellParent; //used to snap to table selection
767
  nsCOMPtr<nsIContent> mStartSelectedCell;
768
  nsCOMPtr<nsIContent> mEndSelectedCell;
769
  nsCOMPtr<nsIContent> mAppendStartSelectedCell;
770
  nsCOMPtr<nsIContent> mUnselectCellOnMouseUp;
771
  mozilla::TableSelection mSelectingTableCellMode = mozilla::TableSelection::None;
772
  int32_t  mSelectedCellIndex = 0;
773
774
  // maintain selection
775
  RefPtr<nsRange> mMaintainRange;
776
  nsSelectionAmount mMaintainedAmount = eSelectNoAmount;
777
778
  //batching
779
  int32_t mBatching = 0;
780
781
  // Limit selection navigation to a child of this node.
782
  nsCOMPtr<nsIContent> mLimiter;
783
  // Limit selection navigation to a descendant of this node.
784
  nsCOMPtr<nsIContent> mAncestorLimiter;
785
786
  nsIPresShell* mShell = nullptr;
787
  // Reason for notifications of selection changing.
788
  int16_t mSelectionChangeReason = nsISelectionListener::NO_REASON;
789
  // For visual display purposes.
790
  int16_t mDisplaySelection = nsISelectionController::SELECTION_OFF;
791
792
  // Hint to tell if the selection is at the end of this line or beginning of next.
793
  CaretAssociateHint mHint = mozilla::CARET_ASSOCIATE_BEFORE;
794
  nsBidiLevel mCaretBidiLevel = BIDI_LEVEL_UNDEFINED;
795
  nsBidiLevel mKbdBidiLevel = NSBIDI_LTR;
796
797
  nsPoint mDesiredPos;
798
  bool mDelayedMouseEventValid = false;
799
  // These values are not used since they are only valid when
800
  // mDelayedMouseEventValid is true, and setting mDelayedMouseEventValid
801
  // always overrides these values.
802
  uint32_t mDelayedMouseEventClickCount = 0;
803
  bool mDelayedMouseEventIsShift = false;
804
805
  bool mChangesDuringBatching = false;
806
  bool mNotifyFrames = true;
807
  bool mDragSelectingCells = false;
808
  bool mDragState = false;   //for drag purposes
809
  bool mMouseDoubleDownState = false; //has the doubleclick down happened
810
  bool mDesiredPosSet = false;
811
  bool mAccessibleCaretEnabled = false;
812
813
  int8_t mCaretMovementStyle = 0;
814
815
  static bool sSelectionEventsEnabled;
816
  static bool sSelectionEventsOnTextControlsEnabled;
817
};
818
819
#endif /* nsFrameSelection_h___ */