/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___ */ |