From 6c313126b66df0c5927c6b4cf2e614e873f28402 Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Tue, 22 Dec 2015 14:58:48 +0900 Subject: [PATCH 01/94] Bug 1234120 part.1 IMEHandler should request all notifications which are requested by either IMMHander or TSFTextStore when IMM is available in TSF mode r=m_kato --- widget/IMEData.h | 5 +++++ widget/windows/WinIMEHandler.cpp | 11 ++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/widget/IMEData.h b/widget/IMEData.h index 4b284ffd371e..ce70be3e0f66 100644 --- a/widget/IMEData.h +++ b/widget/IMEData.h @@ -71,6 +71,11 @@ struct nsIMEUpdatePreference final { } + nsIMEUpdatePreference operator|(const nsIMEUpdatePreference& aOther) const + { + return nsIMEUpdatePreference(aOther.mWantUpdates | mWantUpdates); + } + void DontNotifyChangesCausedByComposition() { mWantUpdates &= ~DEFAULT_CONDITIONS_OF_NOTIFYING_CHANGES; diff --git a/widget/windows/WinIMEHandler.cpp b/widget/windows/WinIMEHandler.cpp index 728aac8b391d..bb719ab6b30a 100644 --- a/widget/windows/WinIMEHandler.cpp +++ b/widget/windows/WinIMEHandler.cpp @@ -334,7 +334,16 @@ IMEHandler::GetUpdatePreference() #ifdef NS_ENABLE_TSF if (IsTSFAvailable()) { - return TSFTextStore::GetIMEUpdatePreference(); + if (!sIsIMMEnabled) { + return TSFTextStore::GetIMEUpdatePreference(); + } + // Even if TSF is available, the active IME may be an IMM-IME. + // Unfortunately, changing the result of GetUpdatePreference() while an + // editor has focus isn't supported by IMEContentObserver nor + // ContentCacheInParent. Therefore, we need to request whole notifications + // which are necessary either IMMHandler or TSFTextStore. + return IMMHandler::GetIMEUpdatePreference() | + TSFTextStore::GetIMEUpdatePreference(); } #endif //NS_ENABLE_TSF From 3b8ef4f9b63309d2fe1d5c50794b5fc006fd55ba Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Tue, 22 Dec 2015 14:58:48 +0900 Subject: [PATCH 02/94] Bug 1234120 part.2 TSFTextStore should ignore unnecessary text and selection changes which are caused by composition r=m_kato --- widget/windows/TSFTextStore.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/widget/windows/TSFTextStore.cpp b/widget/windows/TSFTextStore.cpp index 232c19892801..9f530861f4c5 100644 --- a/widget/windows/TSFTextStore.cpp +++ b/widget/windows/TSFTextStore.cpp @@ -4567,6 +4567,12 @@ TSFTextStore::OnTextChangeInternal(const IMENotification& aIMENotification) GetSinkMaskNameStr(mSinkMask).get(), GetBoolName(mComposition.IsComposing()))); + if (textChangeData.mCausedByComposition) { + // Ignore text change notifications caused by composition since it's + // already been handled internally. + return NS_OK; + } + mDeferNotifyingTSF = false; if (IsReadLocked()) { @@ -4653,6 +4659,12 @@ TSFTextStore::OnSelectionChangeInternal(const IMENotification& aIMENotification) GetBoolName(mIsRecordingActionsWithoutLock), GetBoolName(mComposition.IsComposing()))); + if (selectionChangeData.mCausedByComposition) { + // Ignore selection change notifications caused by composition since it's + // already been handled internally. + return NS_OK; + } + mDeferNotifyingTSF = false; // A compositionstart event handler can change selection before actually From 9bc88b0acbf0b1020266c7b79fd82735b29e5acf Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Tue, 22 Dec 2015 14:58:48 +0900 Subject: [PATCH 03/94] Bug 1234120 part.3 IMMHandler should forget caret position specified by IME when IMMHandler doesn't set caret range to eCompositionChange event r=m_kato --- widget/windows/IMMHandler.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/widget/windows/IMMHandler.cpp b/widget/windows/IMMHandler.cpp index 0d4bfcf996da..8c5b04a7b305 100644 --- a/widget/windows/IMMHandler.cpp +++ b/widget/windows/IMMHandler.cpp @@ -2031,8 +2031,12 @@ IMMHandler::CreateTextRangeArray() if (targetClause && cursor >= targetClause->mStartOffset && cursor <= targetClause->mEndOffset) { + // Forget the caret position specified by IME since Gecko's caret position + // will be at the end of composition string. + mCursorPosition = NO_IME_CARET; MOZ_LOG(gIMMLog, LogLevel::Info, - ("IMM: CreateTextRangeArray, no caret due to it's in the target clause")); + ("IMM: CreateTextRangeArray, no caret due to it's in the target clause, " + "now, mCursorPosition is NO_IME_CARET")); return textRangeArray.forget(); } From 0fd840e0d8fb9522edd92f61b312ee362d3957e7 Mon Sep 17 00:00:00 2001 From: Ting-Yu Lin Date: Tue, 22 Dec 2015 14:14:12 +0800 Subject: [PATCH 04/94] Bug 1221459 - Remove TouchCaret and SelectionCarets. r=mtseng,roc All the files modified are straightforward deletion except TouchManager and ZoomConstraintsClient. I add some includes and wrap TouchManager by mozilla namespace to fix build errors due to the removal of TouchCaret. --HG-- extra : rebase_source : b31db322130f665e7dda53d1061cfc40f81ce411 --- b2g/installer/package-manifest.in | 12 - browser/installer/package-manifest.in | 12 - dom/base/nsFocusManager.cpp | 6 - dom/base/nsGlobalWindow.cpp | 1 - editor/composer/moz.build | 12 - editor/composer/res/text_caret.png | Bin 2130 -> 0 bytes editor/composer/res/text_caret@1.5x.png | Bin 2760 -> 0 bytes editor/composer/res/text_caret@2.25x.png | Bin 3593 -> 0 bytes editor/composer/res/text_caret@2x.png | Bin 3244 -> 0 bytes editor/composer/res/text_caret_tilt_left.png | Bin 2016 -> 0 bytes .../res/text_caret_tilt_left@1.5x.png | Bin 2572 -> 0 bytes .../res/text_caret_tilt_left@2.25x.png | Bin 3383 -> 0 bytes .../composer/res/text_caret_tilt_left@2x.png | Bin 3060 -> 0 bytes editor/composer/res/text_caret_tilt_right.png | Bin 2034 -> 0 bytes .../res/text_caret_tilt_right@1.5x.png | Bin 2594 -> 0 bytes .../res/text_caret_tilt_right@2.25x.png | Bin 3405 -> 0 bytes .../composer/res/text_caret_tilt_right@2x.png | Bin 3105 -> 0 bytes layout/base/SelectionCarets.cpp | 1340 ----------------- layout/base/SelectionCarets.h | 277 ---- layout/base/TouchCaret.cpp | 1110 -------------- layout/base/TouchCaret.h | 321 ---- layout/base/TouchManager.cpp | 11 + layout/base/TouchManager.h | 4 + layout/base/ZoomConstraintsClient.cpp | 2 + layout/base/moz.build | 7 +- layout/base/nsIPresShell.h | 27 - layout/base/nsPresShell.cpp | 134 -- layout/base/nsPresShell.h | 20 +- layout/generic/nsCanvasFrame.cpp | 111 +- layout/generic/nsCanvasFrame.h | 39 - layout/generic/nsSelection.cpp | 34 - layout/style/ua.css | 108 -- layout/tools/reftest/reftest-preferences.js | 3 - .../b2gdroid/installer/package-manifest.in | 24 +- modules/libpref/init/all.js | 19 - testing/profiles/prefs_b2g_unittest.js | 1 - 36 files changed, 34 insertions(+), 3601 deletions(-) delete mode 100644 editor/composer/res/text_caret.png delete mode 100644 editor/composer/res/text_caret@1.5x.png delete mode 100644 editor/composer/res/text_caret@2.25x.png delete mode 100644 editor/composer/res/text_caret@2x.png delete mode 100644 editor/composer/res/text_caret_tilt_left.png delete mode 100644 editor/composer/res/text_caret_tilt_left@1.5x.png delete mode 100644 editor/composer/res/text_caret_tilt_left@2.25x.png delete mode 100644 editor/composer/res/text_caret_tilt_left@2x.png delete mode 100644 editor/composer/res/text_caret_tilt_right.png delete mode 100644 editor/composer/res/text_caret_tilt_right@1.5x.png delete mode 100644 editor/composer/res/text_caret_tilt_right@2.25x.png delete mode 100644 editor/composer/res/text_caret_tilt_right@2x.png delete mode 100644 layout/base/SelectionCarets.cpp delete mode 100644 layout/base/SelectionCarets.h delete mode 100644 layout/base/TouchCaret.cpp delete mode 100644 layout/base/TouchCaret.h diff --git a/b2g/installer/package-manifest.in b/b2g/installer/package-manifest.in index 6a2ba8bd5dcf..ab27771ec1cd 100644 --- a/b2g/installer/package-manifest.in +++ b/b2g/installer/package-manifest.in @@ -813,18 +813,6 @@ @RESPATH@/res/accessiblecaret_tilt_right@1.5x.png @RESPATH@/res/accessiblecaret_tilt_right@2.25x.png @RESPATH@/res/accessiblecaret_tilt_right@2x.png -@RESPATH@/res/text_caret.png -@RESPATH@/res/text_caret@1.5x.png -@RESPATH@/res/text_caret@2.25x.png -@RESPATH@/res/text_caret@2x.png -@RESPATH@/res/text_caret_tilt_left.png -@RESPATH@/res/text_caret_tilt_left@1.5x.png -@RESPATH@/res/text_caret_tilt_left@2.25x.png -@RESPATH@/res/text_caret_tilt_left@2x.png -@RESPATH@/res/text_caret_tilt_right.png -@RESPATH@/res/text_caret_tilt_right@1.5x.png -@RESPATH@/res/text_caret_tilt_right@2.25x.png -@RESPATH@/res/text_caret_tilt_right@2x.png @RESPATH@/res/grabber.gif #ifdef XP_MACOSX @RESPATH@/res/cursors/* diff --git a/browser/installer/package-manifest.in b/browser/installer/package-manifest.in index 003a42e1c111..9862ae71a415 100644 --- a/browser/installer/package-manifest.in +++ b/browser/installer/package-manifest.in @@ -751,18 +751,6 @@ @RESPATH@/res/accessiblecaret_tilt_right@1.5x.png @RESPATH@/res/accessiblecaret_tilt_right@2.25x.png @RESPATH@/res/accessiblecaret_tilt_right@2x.png -@RESPATH@/res/text_caret.png -@RESPATH@/res/text_caret@1.5x.png -@RESPATH@/res/text_caret@2.25x.png -@RESPATH@/res/text_caret@2x.png -@RESPATH@/res/text_caret_tilt_left.png -@RESPATH@/res/text_caret_tilt_left@1.5x.png -@RESPATH@/res/text_caret_tilt_left@2.25x.png -@RESPATH@/res/text_caret_tilt_left@2x.png -@RESPATH@/res/text_caret_tilt_right.png -@RESPATH@/res/text_caret_tilt_right@1.5x.png -@RESPATH@/res/text_caret_tilt_right@2.25x.png -@RESPATH@/res/text_caret_tilt_right@2x.png @RESPATH@/res/grabber.gif #ifdef XP_MACOSX @RESPATH@/res/cursors/* diff --git a/dom/base/nsFocusManager.cpp b/dom/base/nsFocusManager.cpp index b921f854f828..ce80ca96d184 100644 --- a/dom/base/nsFocusManager.cpp +++ b/dom/base/nsFocusManager.cpp @@ -41,7 +41,6 @@ #include "nsIObjectFrame.h" #include "nsBindingManager.h" #include "nsStyleCoord.h" -#include "SelectionCarets.h" #include "TabChild.h" #include "nsFrameLoader.h" @@ -1692,11 +1691,6 @@ nsFocusManager::Blur(nsPIDOMWindow* aWindowToClear, SetCaretVisible(presShell, false, nullptr); } - RefPtr selectionCarets = presShell->GetSelectionCarets(); - if (selectionCarets) { - selectionCarets->NotifyBlur(aIsLeavingDocument || !mActiveWindow); - } - RefPtr eventHub = presShell->GetAccessibleCaretEventHub(); if (eventHub) { eventHub->NotifyBlur(aIsLeavingDocument || !mActiveWindow); diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index dc80936aa269..d39397b193c9 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -207,7 +207,6 @@ #include "prrng.h" #include "nsSandboxFlags.h" #include "TimeChangeObserver.h" -#include "TouchCaret.h" #include "mozilla/dom/AudioContext.h" #include "mozilla/dom/BrowserElementDictionariesBinding.h" #include "mozilla/dom/cache/CacheStorage.h" diff --git a/editor/composer/moz.build b/editor/composer/moz.build index b8fe63f1a900..1436fdf44f9b 100644 --- a/editor/composer/moz.build +++ b/editor/composer/moz.build @@ -59,16 +59,4 @@ RESOURCE_FILES += [ 'res/table-remove-row-active.gif', 'res/table-remove-row-hover.gif', 'res/table-remove-row.gif', - 'res/text_caret.png', - 'res/text_caret@1.5x.png', - 'res/text_caret@2.25x.png', - 'res/text_caret@2x.png', - 'res/text_caret_tilt_left.png', - 'res/text_caret_tilt_left@1.5x.png', - 'res/text_caret_tilt_left@2.25x.png', - 'res/text_caret_tilt_left@2x.png', - 'res/text_caret_tilt_right.png', - 'res/text_caret_tilt_right@1.5x.png', - 'res/text_caret_tilt_right@2.25x.png', - 'res/text_caret_tilt_right@2x.png', ] diff --git a/editor/composer/res/text_caret.png b/editor/composer/res/text_caret.png deleted file mode 100644 index 441067672e0418d6b0ae25ea2febd866e81167af..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2130 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 HQ&_ZhK&4Dpk(*aIvc4Z~lnhtYe$q>f9C$Cd;!P z=|H`*t-ZV26V}5s>DYG{Sq)UX$2zol?Gx{Q-r!UIg_^uv(pRO5Y*hTeifjjc`%HByI;HVFET$?2p-_MZwZ;RfN_;MV#K-PA(H%zG&OXT?X0 znZ`OV)#VZPDo4Dl=_mc=GkMU_gEiEQyfkRx`a%iUq0V;(6w4qo?BJ9FzgeH$P|ZJ z0`iAid#2*XF6h|6I=Yje7e<_xC#PwxhrQ8gD?K;jPF**F-%rlzP4Bx|l=BKs7~Gps z=T;3wRbBmFSx$N$u`f%nvQMFQcg+B>G)ssKP(S`YGgaD%7%-2k4{UCK@%lGss=~x& zzHr;>;7tRV!Mn0^-@C`w1?B_=f15Z2ViKAzYiFsY!1(Lsi;gPAw$?PgYk4s{v7agj zlABuPPtjErCnf|ds>!dw`dUOp+6+d3qX5Q?EZi zF_c#0Up8#o3c1i9*et&HmFS>C*5-Zn>58-g$AO`z(*c`oP`JZBO+`V!K^|!OcibLb z>S?VRL6+4@0Ta zL!Uf*c3=_~UOZu^?d@I%Evvl2>^L;8xN^n9`seN0EpoO)cYS9& zpDm|n2lqcf3op&EeZQ5yx}&7?c)3EE;k2v$u|`ytx=Afc(rnPH>bh?DN8?yTz?X`pdN> zXK~k1LZVS%w)(oA{hG}`J$1XNF1%@0wB4LuP;|y*fbRtdGoB%q1+`YhD$1?};_2@)C8azJ+U# z8L57&o)Io@n5>k-pLls~5xi@d3PlLR*Hcep42>W7EX75oBfcpS`?Cn}l&7jz)%vg1 z2RZz%B+ck&CBVh+uJlgEmqocwZY)$x7pdH~fB9D5k7n{e@9`HXIYo#|zqG(O|F-Yi O-IC$rNvov>CI1IgiF`i* diff --git a/editor/composer/res/text_caret@2.25x.png b/editor/composer/res/text_caret@2.25x.png deleted file mode 100644 index 153b7339657e245b35c339c9c7b5f063a3f9c4a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3593 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 diff --git a/editor/composer/res/text_caret@2x.png b/editor/composer/res/text_caret@2x.png deleted file mode 100644 index ae8b0f40bfbb365e1eed213ddaeee7cb4459d54d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3244 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 RZ{z>LWtY2SnSF4={{Zxbswe;e diff --git a/editor/composer/res/text_caret_tilt_left.png b/editor/composer/res/text_caret_tilt_left.png deleted file mode 100644 index 6dd2bd8beeb16e0066f5e32710d29c371bb25b29..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2016 zcmaJ?dsGv577n69u_#Y#6=H~}ppZ#IAS5KvKoZ_jc`u4hNCpUyOh^WjK;nj%m4gbh zB9-_8%0tkIdRPQnk%e!3`Rz=u}g55vd&N(x`-@WJi?)~oLoXOkE z@ijHsY=T0eO#S_sA;{^3ynyjqzw=Se{nLjc8s7=IBj9t;6_ z0%gh_kcL7T+6%*?;HcmrDjyQzczO&@A(9|$6pH4hkns3PAdHCxd;kR6G&0 z{9uu6Qb8Owgvnmcg;;cK0t`#203eskadHevJ2vZD9d?`xUl4{c-TRI^1*Ln(sXBsvnkp~{f*3BI&=cE90 z-s*ied(+c*19d4!^0aSM74@}mZ=Vx6amSHVzj<=0GUzdtYs??qh4AE|P-4m>B z3B=9M&tGXhTIgDu0SBx<^mEJL87-)WMQJ>NFm zB%3CshOL3OVOilIl^=*0Sxah2gxbuLGK9mF_XR)epxl1Vat{{W-eKiVI_fk2x_1 z4xTZLGJn%3AO)Hk7mepkwLP~#BsSB zce&(5a7TVr_4GoM&kuYniWq6~##*qVzBk43peq_ese{^&XFgmpq2Y zO#XRFJB{u=5k6}GJ$(?VD^Jgi`RZarzfOEaq3*|O#awjhX}6yS$UA#V(W7kDSKS)f zsqb7L=f75N)S_c@vt#>CRL)GyM;LYnuJfu{<4+1Hb@X()UH$penO&?q zRAsm;!G#i27us7}?{JW|rSq&Ofq#1Xps~96&B%3`A*q1(G!akW z{1`p9`EP!XyPq6QG`c?^QTl&2Z)eS@U`f*w@J!m^bfF;NM&#JOzM!GRnQLRi zBP|wDtjbPygQnCp`KN~{F{*!^szGczv{qtx!(hS7a4}S4fcj5aXGcy=o|XQe>(Ama Jb>7^p{{jIrLJ|M~ diff --git a/editor/composer/res/text_caret_tilt_left@1.5x.png b/editor/composer/res/text_caret_tilt_left@1.5x.png deleted file mode 100644 index bb26138b552711982d7a50e7bc186f06658420d2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2572 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 F{s+GhwFv+K diff --git a/editor/composer/res/text_caret_tilt_left@2x.png b/editor/composer/res/text_caret_tilt_left@2x.png deleted file mode 100644 index 103561b642e5649c46a7a2af99440ae265e10542..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3060 zcmaJ@c|4Ts7av=gvLtjvj0rbo%+R2jNMjaPm~1h~GG-`K6p#&#=udH?5Xlk8S}EoL zfP@a!g}@=$+aXB|njvw`$1t466rlkCbIWihkrYJXfcz-_RJsLt_HH8>L?v5*-AwFZ z_DnP-fci@$i{c!KcOgXvkq~6C<$jQPI8qdVM&S@a;j~~n8yRi^{vH=8lGn^oFzCAr zC&&W)Cn#K*k~+3fl`chCyHmq{$v6%oz0J z0*kV-$VZV*7~GFsBFzFEz~L~FP-s|Km|@r+Lk7zqYJ@-_pfF>ou`xvC0bxhbImB=X zoxNi{0*1mSv8YTAl|cusMI`z$LO2#+5z{}nKx5k5{}q_d{!u7V$)MpxCe+9f2Bp!~ z_VwMH&2ggqP2(TE*)9=G3e<_hW`wXvqJA9Ru?`m1?!ObQIf~dIF$_`&jY8+xU@X8Q ziy@gxMxsp7rYH;!jzZw9jEt~w6bcQ;!Esh*a1$6D1xKx8ZRl(ckxrtlW2qvnnK8-) zu@?sWPb?D6q7XR@mJ5Rsyxu*B00xJ_4qz}rXlGNxTrb&%A5V_=5c`|k|?#FGDE=ik|z;Sm3dg^I{P*IN63tzI{Y=4Va(Yj8!%U!zZ< zi{_mr8f>qH$a4UI%uyQ*$|d~SRQ|@`Eg>2$vt6OX&q63yNis4($sAvB7ob6@S7v`v zQpV;FDmG_xOFnG2hoAeD@;dhD5czuj`$pOi%LR1bATqmda=vBdV-9l89_pETV z@hd(Xi+(;dGxKp(cXj?*b@po1%<<9D+32N4^|GBn^yTm-M@eOvl-)#QGrU`cXRxnm z^y$#E8$mH03*2ws-)c_aRO}#ry((=sRweihW35vd>1|m0>7|X2Uw0CKwXl-ld(&=- z7g9zozs#lLMrMME5j_XrqqjD*Zu41R^giV#>?L89r-p(NUSdU5RI%p$k1>mINd0eX#xg@UGJnyTpFSoSyI(4s}P!ex>S_Kh3he z*xgWolhjDmdnXTzMUsZc)wn%g3V|N-zOVCJga&{Xx%3wXPwh$JM=wQA-NL@{c`wL{ zdW`o`MJctEE2MVh4tIXj2r`DAN^7gSGq-2F2|t<|a)bQg#A4xj9c$&h0EVXJ@wp)d zRCSBkOua|EEx7*~W=b0fNxpNLDs>xE9dfa%cTOd>ddT3$ONYs`j4yW|Xo5SHJfz$4 zCqB{c&b`wu(`HxpqN}y#7xNE>u8zlIwetvKd{;wTS@kV5i{-y>C>)I%{1u(NeX5ZmM%u5A$ zX*G2ZBYrZ!q^4K3iO-0x>UOR1Egl&=mtNFF*VoitOmEZWXR5*UA9t99ncq=8$m2(9 z;BBo++zvA;79Dm8BrB+oK3{uzguk-CzMwMQ&s{*(@ZISl-riRcK0*uqHQM&+&+%78 zvrua0whECND>pgoPH0Sd8D3K$w)-s^J}`bvUu=%6>A7#1tThL^JeS^+yz_qFCf_3O zGf_g5v}VP@^5cTmS|Fhd=sQyV=44H)W0V;w-q&5%XF+ufv;TM*qt;))nWcgody?(u z;aH#R0CQ)Y9|~!5dIV}ZJV;B3+u0@`cI4*chi-$fw@JYmVXhMyt*NGCDxp=wp+jI{jz|VCQU=qCgsAh*2ibmX##S-sxUAwP)ESCaL&EqgTFj=}}y z4+Hz+;$(eAXT|2Sm{9Tyce(%m!+l$c2Lyfs?vkm>Mjp6W35D)DOxEvzrra$)HYJ;J zR&mNi$p^7*_9;f<-NIf+0$jk)$@ht^$TvRkmgz zBz_;8NjrJ!Aeg2s_~2~Gr8*b6DjTGTF)$i$mWLIW?d`DA4JUo145(r-N4iyj#n=4J zfS-@!S9KnOCv%S++!&+sqDOZ0PTy$rNZQ-&%v$Qe$yYB{exgDM@o}vndDHQ5Nj|!aI9X<=2|+ zv&y*&GyPX1R|-OBUkx;%1&Cp;fSm={)dqcWnNj}FW1m;|tA zu4TJ4EIQZ;O6}9HFJ7{HFuQGVS(88D*1yr`(sE*b?4u1%xl+LDL_Z1F!*+TQ1^E;8 zG$3lDq#pSMmPv9~TMI zS^bGI308fcKtX9ra^mtNr@QAv+eedh^E$Y!S!Pm5W%SqS!DOvN_n)8iV-_ zxr6SNKTXXBMn?>(1NhF)Os>%-#>B>;9o9?S@p|dLy!s)Y!$Ou4FFrYrQwN=1xxF%V z#&*PRA>ZPvRIRUcY(-z%y=`B=J-IjzL8MKigA}dBYg}RyQ)eWnPAJ&u_!oH1<0l`F zL|u0Gx)Le85bRSuU;XBTM8_4M67O?^PJplnD}L6Wee2A%Qhv){khr1bAy*~a8R&IJ ztMZ3-G%3-kP-K9zr9McdUDCsyeKJ9n&+c`Ehf3& z!|}a?E;rv+&p$2p6%Kp1e5){bZ^gIs35&Ls_2+IARvTM)rx^Ua?@+-{gA3ygolVol zOu%?^pmxk+rf@)2SUlDxeqlwQP1np*ft(s_CWvqI$h>|lvVG7~E7udT^!Z7fo?V`I zdMR<@K}@k*!2bEN=-FcHEz=#|^8*0ABbE(rj2WRP-(y3$l@K3>HQCaMkDq?9q;ju= zSn0uh{_sxSvNObl`$EsZgD~Rya2ZBrRWM1zrV?EM`&R|oI$N}4{~gZyUMKCnpT($8QfeU;WPb-FO?_TXvxX?)%?K# zRx%rtZq%)2mfhKl&Nv;5-*G`^m*?Ti2$>^vLV~eNQ)x=y%X?71y8L@sr{pb39@f0K z@9mdegwPyp$-{&X;%n`p9Lsh<=Qn;!Yx9hv&AXxiypIWp3 oE$aKKty_PHVm&+I-;{g-uba!Ol-iE8ulP0h>rg-v9sr diff --git a/editor/composer/res/text_caret_tilt_right.png b/editor/composer/res/text_caret_tilt_right.png deleted file mode 100644 index 84cde557460efe99928d07a876d99076bfde282f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2034 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 diff --git a/editor/composer/res/text_caret_tilt_right@2.25x.png b/editor/composer/res/text_caret_tilt_right@2.25x.png deleted file mode 100644 index 8ce1f9453906a258aea9df37e0a7d65a988ef745..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3405 zcmaJ^dpy(o8=uMCr6Mb2jhtL&Gv+ea8FR^`xwIT=Gh@RpW@CtQX;Q8c9VfR+MCz#N zrsRH!N`+I4gyM)?l5Q^jrc>wq{^qO*wv4XkLWDXU831S6OA+8K^2$eu32gO8mQLO<0 zNgcX3kxRt8qbV$g5qZtVh|ge)(Exz89iL66gi*PWKxzn`X#<_DzYB%XgKVICQFsKN zjiu7)F0mY{SFDFOB{qy=83eVng;?{^Vh0Q=mki-E!kLk1z76!7U$l6?riMcy-%Pk+ zHqgIG5%Hc7EQ>>hpp4956oj!U#N5)z7-eQ|X>JHXie)&$0**w$5SD0^2^xWfe1D+g zXq=#6G{F(~J(gIqfzr5KHX06(j*d2pHZfvxLg2=hmX>e?5{^W|#1^o~7$%p@hcP3y ze|T`DMp8I*HkZy~Le@Nz16e$-4OGnZ?-UqpJpLcY%*gMB5|<3lC$r(kMhG~Av6k02 z>qstv`Y(;2T1R@vu&HnYHIl{SP{jQR*8Tw&*Y5uZS~C>0K|8W2JO-7?b#=6XiZw<- z^dL0S*x1Cu1cAX=;;_cXPNo*bIW+a!)q)>lg>HlIa|1TDe z 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 diff --git a/layout/base/SelectionCarets.cpp b/layout/base/SelectionCarets.cpp deleted file mode 100644 index 04211578f343..000000000000 --- a/layout/base/SelectionCarets.cpp +++ /dev/null @@ -1,1340 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=2 sw=2 et tw=78: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "mozilla/Logging.h" -#include "SelectionCarets.h" - -#include "gfxPrefs.h" -#include "nsBidiPresUtils.h" -#include "nsCanvasFrame.h" -#include "nsCaret.h" -#include "nsContentUtils.h" -#include "nsDebug.h" -#include "nsDocShell.h" -#include "nsDOMTokenList.h" -#include "nsFocusManager.h" -#include "nsFrame.h" -#include "nsGenericHTMLElement.h" -#include "nsIDocument.h" -#include "nsIDocShell.h" -#include "nsIDOMDocument.h" -#include "nsIDOMNodeFilter.h" -#include "nsIPresShell.h" -#include "nsPresContext.h" -#include "nsRect.h" -#include "nsView.h" -#include "mozilla/dom/DOMRect.h" -#include "mozilla/dom/Element.h" -#include "mozilla/dom/ScrollViewChangeEvent.h" -#include "mozilla/dom/Selection.h" -#include "mozilla/dom/TreeWalker.h" -#include "mozilla/Preferences.h" -#include "mozilla/TouchEvents.h" -#include "Layers.h" -#include "TouchCaret.h" -#include "nsFrameSelection.h" - -using namespace mozilla; -using namespace mozilla::dom; - -static const char* kSelectionCaretsLogModuleName = "SelectionCarets"; -static mozilla::LazyLogModule gSelectionCaretsLog(kSelectionCaretsLogModuleName); - -// To enable all the SELECTIONCARETS_LOG print statements, set the environment -// variable NSPR_LOG_MODULES=SelectionCarets:5 -#define SELECTIONCARETS_LOG(message, ...) \ - MOZ_LOG(gSelectionCaretsLog, LogLevel::Debug, \ - ("SelectionCarets (%p): %s:%d : " message "\n", this, __FUNCTION__, \ - __LINE__, ##__VA_ARGS__)); - -#define SELECTIONCARETS_LOG_STATIC(message, ...) \ - MOZ_LOG(gSelectionCaretsLog, LogLevel::Debug, \ - ("SelectionCarets: %s:%d : " message "\n", __FUNCTION__, __LINE__, \ - ##__VA_ARGS__)); - -// We treat mouse/touch move as "REAL" move event once its move distance -// exceed this value, in CSS pixel. -static const int32_t kMoveStartTolerancePx = 5; - -NS_IMPL_ISUPPORTS(SelectionCarets, - nsIReflowObserver, - nsISelectionListener, - nsIScrollObserver, - nsISupportsWeakReference) - -/*static*/ int32_t SelectionCarets::sSelectionCaretsInflateSize = 0; - -SelectionCarets::SelectionCarets(nsIPresShell* aPresShell) - : mPresShell(aPresShell) - , mActiveTouchId(-1) - , mCaretCenterToDownPointOffsetY(0) - , mDragMode(NONE) - , mUseAsyncPanZoom(false) - , mInAsyncPanZoomGesture(false) - , mEndCaretVisible(false) - , mStartCaretVisible(false) - , mSelectionVisibleInScrollFrames(true) - , mVisible(false) -{ - MOZ_ASSERT(NS_IsMainThread()); - - SELECTIONCARETS_LOG("Constructor, PresShell=%p", mPresShell); - - static bool addedPref = false; - if (!addedPref) { - Preferences::AddIntVarCache(&sSelectionCaretsInflateSize, - "selectioncaret.inflatesize.threshold"); - addedPref = true; - } -} - -void -SelectionCarets::Init() -{ - nsPresContext* presContext = mPresShell->GetPresContext(); - MOZ_ASSERT(presContext, "PresContext should be given in PresShell::Init()"); - - nsIDocShell* docShell = presContext->GetDocShell(); - if (!docShell) { - return; - } - -#if defined(MOZ_WIDGET_GONK) - mUseAsyncPanZoom = mPresShell->AsyncPanZoomEnabled(); -#endif - - docShell->AddWeakReflowObserver(this); - docShell->AddWeakScrollObserver(this); - - mDocShell = static_cast(docShell); -} - -SelectionCarets::~SelectionCarets() -{ - SELECTIONCARETS_LOG("Destructor"); - MOZ_ASSERT(NS_IsMainThread()); - - mPresShell = nullptr; -} - -void -SelectionCarets::Terminate() -{ - RefPtr docShell(mDocShell.get()); - if (docShell) { - docShell->RemoveWeakReflowObserver(this); - docShell->RemoveWeakScrollObserver(this); - } - - if (mLongTapDetectorTimer) { - mLongTapDetectorTimer->Cancel(); - mLongTapDetectorTimer = nullptr; - } - - if (mScrollEndDetectorTimer) { - mScrollEndDetectorTimer->Cancel(); - mScrollEndDetectorTimer = nullptr; - } - - mPresShell = nullptr; -} - -nsEventStatus -SelectionCarets::HandleEvent(WidgetEvent* aEvent) -{ - WidgetMouseEvent *mouseEvent = aEvent->AsMouseEvent(); - if (mouseEvent && mouseEvent->reason == WidgetMouseEvent::eSynthesized) { - return nsEventStatus_eIgnore; - } - - WidgetTouchEvent *touchEvent = aEvent->AsTouchEvent(); - LayoutDeviceIntPoint movePoint; - int32_t nowTouchId = -1; - if (touchEvent && !touchEvent->touches.IsEmpty()) { - // If touch happened, just grab event with same identifier - if (mActiveTouchId >= 0) { - for (uint32_t i = 0; i < touchEvent->touches.Length(); ++i) { - if (touchEvent->touches[i]->Identifier() == mActiveTouchId) { - movePoint = touchEvent->touches[i]->mRefPoint; - nowTouchId = touchEvent->touches[i]->Identifier(); - break; - } - } - - // not found, consume it - if (nowTouchId == -1) { - return nsEventStatus_eConsumeNoDefault; - } - } else { - movePoint = touchEvent->touches[0]->mRefPoint; - nowTouchId = touchEvent->touches[0]->Identifier(); - } - } else if (mouseEvent) { - movePoint = mouseEvent->AsGUIEvent()->refPoint; - } - - // XUL has no SelectionCarets elements. - if (!mPresShell->GetSelectionCaretsStartElement() || - !mPresShell->GetSelectionCaretsEndElement()) { - return nsEventStatus_eIgnore; - } - - // Get event coordinate relative to root frame - nsIFrame* rootFrame = mPresShell->GetRootFrame(); - if (!rootFrame) { - return nsEventStatus_eIgnore; - } - nsPoint ptInRoot = - nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, movePoint, rootFrame); - - if (aEvent->mMessage == eTouchStart || - (aEvent->mMessage == eMouseDown && - mouseEvent->button == WidgetMouseEvent::eLeftButton)) { - // If having a active touch, ignore other touch down event - if (aEvent->mMessage == eTouchStart && mActiveTouchId >= 0) { - return nsEventStatus_eConsumeNoDefault; - } - - mActiveTouchId = nowTouchId; - mDownPoint = ptInRoot; - if (IsOnStartFrameInner(ptInRoot)) { - mDragMode = START_FRAME; - mCaretCenterToDownPointOffsetY = GetCaretYCenterPosition() - ptInRoot.y; - SetSelectionDirection(eDirPrevious); - SetSelectionDragState(true); - return nsEventStatus_eConsumeNoDefault; - } else if (IsOnEndFrameInner(ptInRoot)) { - mDragMode = END_FRAME; - mCaretCenterToDownPointOffsetY = GetCaretYCenterPosition() - ptInRoot.y; - SetSelectionDirection(eDirNext); - SetSelectionDragState(true); - return nsEventStatus_eConsumeNoDefault; - } else { - mDragMode = NONE; - mActiveTouchId = -1; - LaunchLongTapDetector(); - } - } else if (aEvent->mMessage == eTouchEnd || - aEvent->mMessage == eTouchCancel || - aEvent->mMessage == eMouseUp) { - CancelLongTapDetector(); - if (mDragMode != NONE) { - // Only care about same id - if (mActiveTouchId == nowTouchId) { - SetSelectionDragState(false); - mDragMode = NONE; - mActiveTouchId = -1; - } - return nsEventStatus_eConsumeNoDefault; - } - } else if (aEvent->mMessage == eTouchMove || aEvent->mMessage == eMouseMove) { - if (mDragMode == START_FRAME || mDragMode == END_FRAME) { - if (mActiveTouchId == nowTouchId) { - ptInRoot.y += mCaretCenterToDownPointOffsetY; - - if (mDragMode == START_FRAME) { - if (ptInRoot.y > mDragDownYBoundary) { - ptInRoot.y = mDragDownYBoundary; - } - } else if (mDragMode == END_FRAME) { - if (ptInRoot.y < mDragUpYBoundary) { - ptInRoot.y = mDragUpYBoundary; - } - } - return DragSelection(ptInRoot); - } - - return nsEventStatus_eConsumeNoDefault; - } - - nsPoint delta = mDownPoint - ptInRoot; - if (NS_hypot(delta.x, delta.y) > - nsPresContext::AppUnitsPerCSSPixel() * kMoveStartTolerancePx) { - CancelLongTapDetector(); - } - - } else if (aEvent->mMessage == eMouseLongTap) { - if (!mVisible) { - SELECTIONCARETS_LOG("SelectWord from eMouseLongTap"); - - mDownPoint = ptInRoot; - nsresult wordSelected = SelectWord(); - - if (NS_FAILED(wordSelected)) { - SELECTIONCARETS_LOG("SelectWord from eMouseLongTap failed!"); - return nsEventStatus_eIgnore; - } - - return nsEventStatus_eConsumeNoDefault; - } - } - return nsEventStatus_eIgnore; -} - -static void -SetElementVisibility(dom::Element* aElement, bool aVisible) -{ - if (!aElement) { - return; - } - - ErrorResult err; - aElement->ClassList()->Toggle(NS_LITERAL_STRING("hidden"), - dom::Optional(!aVisible), err); -} - -void -SelectionCarets::SetVisibility(bool aVisible) -{ - if (!mPresShell) { - return; - } - - if (mVisible == aVisible) { - SELECTIONCARETS_LOG("Set visibility %s, same as the old one", - (aVisible ? "shown" : "hidden")); - return; - } - - if (!aVisible) { - mSelectionVisibleInScrollFrames = false; - } - - mVisible = aVisible; - SELECTIONCARETS_LOG("Set visibility %s", (mVisible ? "shown" : "hidden")); - - dom::Element* startElement = mPresShell->GetSelectionCaretsStartElement(); - SetElementVisibility(startElement, mVisible && mStartCaretVisible); - - dom::Element* endElement = mPresShell->GetSelectionCaretsEndElement(); - SetElementVisibility(endElement, mVisible && mEndCaretVisible); -} - -void -SelectionCarets::SetStartFrameVisibility(bool aVisible) -{ - mStartCaretVisible = aVisible; - SELECTIONCARETS_LOG("Set start frame visibility %s", - (mStartCaretVisible ? "shown" : "hidden")); - - dom::Element* element = mPresShell->GetSelectionCaretsStartElement(); - SetElementVisibility(element, mVisible && mStartCaretVisible); -} - -void -SelectionCarets::SetEndFrameVisibility(bool aVisible) -{ - mEndCaretVisible = aVisible; - SELECTIONCARETS_LOG("Set end frame visibility %s", - (mEndCaretVisible ? "shown" : "hidden")); - - dom::Element* element = mPresShell->GetSelectionCaretsEndElement(); - SetElementVisibility(element, mVisible && mEndCaretVisible); -} - -void -SelectionCarets::SetTilted(bool aIsTilt) -{ - dom::Element* startElement = mPresShell->GetSelectionCaretsStartElement(); - dom::Element* endElement = mPresShell->GetSelectionCaretsEndElement(); - - if (!startElement || !endElement) { - return; - } - - SELECTIONCARETS_LOG("Set tilted selection carets %s", - (aIsTilt ? "enabled" : "disabled")); - - ErrorResult err; - startElement->ClassList()->Toggle(NS_LITERAL_STRING("tilt"), - dom::Optional(aIsTilt), err); - - endElement->ClassList()->Toggle(NS_LITERAL_STRING("tilt"), - dom::Optional(aIsTilt), err); -} - -static void -SetCaretDirection(dom::Element* aElement, bool aIsRight) -{ - MOZ_ASSERT(aElement); - - ErrorResult err; - if (aIsRight) { - aElement->ClassList()->Add(NS_LITERAL_STRING("moz-selectioncaret-right"), err); - aElement->ClassList()->Remove(NS_LITERAL_STRING("moz-selectioncaret-left"), err); - } else { - aElement->ClassList()->Add(NS_LITERAL_STRING("moz-selectioncaret-left"), err); - aElement->ClassList()->Remove(NS_LITERAL_STRING("moz-selectioncaret-right"), err); - } -} - -static nsIFrame* -FindFirstNodeWithFrame(nsIDocument* aDocument, - nsRange* aRange, - nsFrameSelection* aFrameSelection, - bool aBackward, - int& aOutOffset) -{ - if (!aDocument || !aRange || !aFrameSelection) { - return nullptr; - } - - nsCOMPtr startNode = - do_QueryInterface(aBackward ? aRange->GetEndParent() : aRange->GetStartParent()); - nsCOMPtr endNode = - do_QueryInterface(aBackward ? aRange->GetStartParent() : aRange->GetEndParent()); - int32_t offset = aBackward ? aRange->EndOffset() : aRange->StartOffset(); - - nsCOMPtr startContent = do_QueryInterface(startNode); - CaretAssociationHint hintStart = - aBackward ? CARET_ASSOCIATE_BEFORE : CARET_ASSOCIATE_AFTER; - nsIFrame* startFrame = aFrameSelection->GetFrameForNodeOffset(startContent, - offset, - hintStart, - &aOutOffset); - - if (startFrame) { - return startFrame; - } - - ErrorResult err; - RefPtr walker = - aDocument->CreateTreeWalker(*startNode, - nsIDOMNodeFilter::SHOW_ALL, - nullptr, - err); - - if (!walker) { - return nullptr; - } - - startFrame = startContent ? startContent->GetPrimaryFrame() : nullptr; - while (!startFrame && startNode != endNode) { - if (aBackward) { - startNode = walker->PreviousNode(err); - } else { - startNode = walker->NextNode(err); - } - - if (!startNode) { - break; - } - - startContent = do_QueryInterface(startNode); - startFrame = startContent ? startContent->GetPrimaryFrame() : nullptr; - } - return startFrame; -} - -void -SelectionCarets::UpdateSelectionCarets() -{ - if (!mPresShell) { - return; - } - - RefPtr selection = GetSelection(); - if (!selection) { - SELECTIONCARETS_LOG("Cannot get selection!"); - SetVisibility(false); - return; - } - - if (selection->IsCollapsed()) { - SELECTIONCARETS_LOG("Selection is collapsed!"); - SetVisibility(false); - return; - } - - int32_t rangeCount = selection->RangeCount(); - RefPtr firstRange = selection->GetRangeAt(0); - RefPtr lastRange = selection->GetRangeAt(rangeCount - 1); - - mPresShell->FlushPendingNotifications(Flush_Layout); - - nsIFrame* rootFrame = mPresShell->GetRootFrame(); - - if (!rootFrame) { - SetVisibility(false); - return; - } - - // Check start and end frame is rtl or ltr text - RefPtr fs = GetFrameSelection(); - if (!fs) { - SetVisibility(false); - return; - } - - int32_t startOffset; - nsIFrame* startFrame = FindFirstNodeWithFrame(mPresShell->GetDocument(), - firstRange, fs, false, startOffset); - - int32_t endOffset; - nsIFrame* endFrame = FindFirstNodeWithFrame(mPresShell->GetDocument(), - lastRange, fs, true, endOffset); - - if (!startFrame || !endFrame) { - SetVisibility(false); - return; - } - - // Check if startFrame is after endFrame. - if (nsLayoutUtils::CompareTreePosition(startFrame, endFrame) > 0) { - SetVisibility(false); - return; - } - - // If the selection is not visible, we should dispatch a event. - nsIFrame* commonAncestorFrame = - nsLayoutUtils::FindNearestCommonAncestorFrame(startFrame, endFrame); - - nsRect selectionRectInRootFrame = nsLayoutUtils::GetSelectionBoundingRect(selection); - nsRect selectionRectInCommonAncestorFrame = selectionRectInRootFrame; - nsLayoutUtils::TransformRect(rootFrame, commonAncestorFrame, - selectionRectInCommonAncestorFrame); - - mSelectionVisibleInScrollFrames = - nsLayoutUtils::IsRectVisibleInScrollFrames(commonAncestorFrame, - selectionRectInCommonAncestorFrame); - SELECTIONCARETS_LOG("Selection visibility %s", - (mSelectionVisibleInScrollFrames ? "shown" : "hidden")); - - - nsRect firstRectInStartFrame = - nsCaret::GetGeometryForFrame(startFrame, startOffset, nullptr); - nsRect lastRectInEndFrame = - nsCaret::GetGeometryForFrame(endFrame, endOffset, nullptr); - - bool startFrameVisible = - nsLayoutUtils::IsRectVisibleInScrollFrames(startFrame, firstRectInStartFrame); - bool endFrameVisible = - nsLayoutUtils::IsRectVisibleInScrollFrames(endFrame, lastRectInEndFrame); - - nsRect firstRectInRootFrame = firstRectInStartFrame; - nsRect lastRectInRootFrame = lastRectInEndFrame; - nsLayoutUtils::TransformRect(startFrame, rootFrame, firstRectInRootFrame); - nsLayoutUtils::TransformRect(endFrame, rootFrame, lastRectInRootFrame); - - SetStartFrameVisibility(startFrameVisible); - SetEndFrameVisibility(endFrameVisible); - - SetStartFramePos(firstRectInRootFrame); - SetEndFramePos(lastRectInRootFrame); - SetVisibility(true); - - // Use half of the first(last) rect as the dragup(dragdown) boundary - mDragUpYBoundary = - (firstRectInRootFrame.BottomLeft().y + firstRectInRootFrame.TopLeft().y) / 2; - mDragDownYBoundary = - (lastRectInRootFrame.BottomRight().y + lastRectInRootFrame.TopRight().y) / 2; - - nsRect rectStart = GetStartFrameRect(); - nsRect rectEnd = GetEndFrameRect(); - bool isTilt = rectStart.Intersects(rectEnd); - if (isTilt) { - SetCaretDirection(mPresShell->GetSelectionCaretsStartElement(), rectStart.x > rectEnd.x); - SetCaretDirection(mPresShell->GetSelectionCaretsEndElement(), rectStart.x <= rectEnd.x); - } - SetTilted(isTilt); -} - -nsresult -SelectionCarets::SelectWord() -{ - if (!mPresShell) { - return NS_ERROR_UNEXPECTED; - } - - nsIFrame* rootFrame = mPresShell->GetRootFrame(); - if (!rootFrame) { - return NS_ERROR_NOT_AVAILABLE; - } - - // Find content offsets for mouse down point - nsIFrame *ptFrame = nsLayoutUtils::GetFrameForPoint(rootFrame, mDownPoint, - nsLayoutUtils::IGNORE_PAINT_SUPPRESSION | nsLayoutUtils::IGNORE_CROSS_DOC); - if (!ptFrame) { - return NS_ERROR_FAILURE; - } - - bool selectable; - ptFrame->IsSelectable(&selectable, nullptr); - if (!selectable) { - SELECTIONCARETS_LOG(" frame %p is not selectable", ptFrame); - return NS_ERROR_FAILURE; - } - - nsPoint ptInFrame = mDownPoint; - nsLayoutUtils::TransformPoint(rootFrame, ptFrame, ptInFrame); - - nsIFrame* currFrame = ptFrame; - nsIContent* newFocusContent = nullptr; - while (currFrame) { - int32_t tabIndexUnused = 0; - if (currFrame->IsFocusable(&tabIndexUnused, true)) { - newFocusContent = currFrame->GetContent(); - nsCOMPtr domElement(do_QueryInterface(newFocusContent)); - if (domElement) - break; - } - currFrame = currFrame->GetParent(); - } - - - // If target frame is focusable, we should move focus to it. If target frame - // isn't focusable, and our previous focused content is editable, we should - // clear focus. - nsFocusManager* fm = nsFocusManager::GetFocusManager(); - nsIContent* editingHost = ptFrame->GetContent()->GetEditingHost(); - if (newFocusContent && currFrame) { - nsCOMPtr domElement(do_QueryInterface(newFocusContent)); - fm->SetFocus(domElement,0); - - if (editingHost && !nsContentUtils::HasNonEmptyTextContent( - editingHost, nsContentUtils::eRecurseIntoChildren)) { - SELECTIONCARETS_LOG("Select a editable content %p with empty text", - editingHost); - // Long tap on the content with empty text, no action for - // selectioncarets but need to dispatch the taponcaret event - // to support the short cut mode - DispatchSelectionStateChangedEvent(GetSelection(), - SelectionState::Taponcaret); - return NS_OK; - } - } else { - nsIContent* focusedContent = GetFocusedContent(); - if (focusedContent) { - // Clear focus if content was editable element, or contentEditable. - nsGenericHTMLElement* focusedGeneric = - nsGenericHTMLElement::FromContent(focusedContent); - if (focusedContent->GetTextEditorRootContent() || - (focusedGeneric && focusedGeneric->IsContentEditable())) { - nsIDOMWindow* win = mPresShell->GetDocument()->GetWindow(); - if (win) { - fm->ClearFocus(win); - } - } - } - } - - SetSelectionDragState(true); - nsFrame* frame = static_cast(ptFrame); - nsresult rs = frame->SelectByTypeAtPoint(mPresShell->GetPresContext(), ptInFrame, - eSelectWord, eSelectWord, 0); - -#ifdef DEBUG_FRAME_DUMP - nsCString frameTag; - frame->ListTag(frameTag); - SELECTIONCARETS_LOG("Frame=%s, ptInFrame=(%d, %d)", frameTag.get(), - ptInFrame.x, ptInFrame.y); -#endif - - SetSelectionDragState(false); - - // Clear maintain selection otherwise we cannot select less than a word - RefPtr fs = GetFrameSelection(); - if (fs) { - fs->MaintainSelection(); - } - return rs; -} - -/* - * If we're dragging start caret, we do not want to drag over previous - * character of end caret. Same as end caret. So we check if content offset - * exceed previous/next character of end/start caret base on aDragMode. - */ -static bool -CompareRangeWithContentOffset(nsRange* aRange, - nsFrameSelection* aSelection, - nsIFrame::ContentOffsets& aOffsets, - SelectionCarets::DragMode aDragMode) -{ - MOZ_ASSERT(aDragMode != SelectionCarets::NONE); - nsINode* node = nullptr; - int32_t nodeOffset = 0; - CaretAssociationHint hint; - nsDirection dir; - - if (aDragMode == SelectionCarets::START_FRAME) { - // Check previous character of end node offset - node = aRange->GetEndParent(); - nodeOffset = aRange->EndOffset(); - hint = CARET_ASSOCIATE_BEFORE; - dir = eDirPrevious; - } else { - // Check next character of start node offset - node = aRange->GetStartParent(); - nodeOffset = aRange->StartOffset(); - hint = CARET_ASSOCIATE_AFTER; - dir = eDirNext; - } - nsCOMPtr content = do_QueryInterface(node); - - int32_t offset = 0; - nsIFrame* theFrame = - aSelection->GetFrameForNodeOffset(content, nodeOffset, hint, &offset); - - if (!theFrame) { - return false; - } - - // Move one character forward/backward from point and get offset - nsPeekOffsetStruct pos(eSelectCluster, - dir, - offset, - nsPoint(0, 0), - true, - true, //limit on scrolled views - false, - false, - false); - nsresult rv = theFrame->PeekOffset(&pos); - if (NS_FAILED(rv)) { - pos.mResultContent = content; - pos.mContentOffset = nodeOffset; - } - - // Compare with current point - int32_t result = nsContentUtils::ComparePoints(aOffsets.content, - aOffsets.StartOffset(), - pos.mResultContent, - pos.mContentOffset); - if ((aDragMode == SelectionCarets::START_FRAME && result == 1) || - (aDragMode == SelectionCarets::END_FRAME && result == -1)) { - aOffsets.content = pos.mResultContent; - aOffsets.offset = pos.mContentOffset; - aOffsets.secondaryOffset = pos.mContentOffset; - } - - return true; -} - -nsEventStatus -SelectionCarets::DragSelection(const nsPoint &movePoint) -{ - nsIFrame* rootFrame = mPresShell->GetRootFrame(); - if (!rootFrame) { - return nsEventStatus_eConsumeNoDefault; - } - - // Find out which content we point to - nsIFrame *ptFrame = nsLayoutUtils::GetFrameForPoint(rootFrame, movePoint, - nsLayoutUtils::IGNORE_PAINT_SUPPRESSION | nsLayoutUtils::IGNORE_CROSS_DOC); - if (!ptFrame) { - return nsEventStatus_eConsumeNoDefault; - } - - RefPtr fs = GetFrameSelection(); - if (!fs) { - return nsEventStatus_eConsumeNoDefault; - } - - nsresult result; - nsIFrame *newFrame = nullptr; - nsPoint newPoint; - nsPoint ptInFrame = movePoint; - nsLayoutUtils::TransformPoint(rootFrame, ptFrame, ptInFrame); - result = fs->ConstrainFrameAndPointToAnchorSubtree(ptFrame, ptInFrame, &newFrame, newPoint); - if (NS_FAILED(result) || !newFrame) { - return nsEventStatus_eConsumeNoDefault; - } - - bool selectable; - newFrame->IsSelectable(&selectable, nullptr); - if (!selectable) { - return nsEventStatus_eConsumeNoDefault; - } - - nsFrame::ContentOffsets offsets = - newFrame->GetContentOffsetsFromPoint(newPoint); - if (!offsets.content) { - return nsEventStatus_eConsumeNoDefault; - } - - RefPtr selection = GetSelection(); - if (!selection) { - return nsEventStatus_eConsumeNoDefault; - } - - int32_t rangeCount = selection->RangeCount(); - if (rangeCount <= 0) { - return nsEventStatus_eConsumeNoDefault; - } - - // Limit the drag behavior not to cross the end of last selection range - // when drag the start frame and vice versa - RefPtr range = mDragMode == START_FRAME ? - selection->GetRangeAt(rangeCount - 1) : selection->GetRangeAt(0); - if (!CompareRangeWithContentOffset(range, fs, offsets, mDragMode)) { - return nsEventStatus_eConsumeNoDefault; - } - - nsIFrame* anchorFrame; - selection->GetPrimaryFrameForAnchorNode(&anchorFrame); - if (!anchorFrame) { - return nsEventStatus_eConsumeNoDefault; - } - - // Clear maintain selection so that we can drag caret freely. - fs->MaintainSelection(eSelectNoAmount); - - // Move caret postion. - nsIFrame *scrollable = - nsLayoutUtils::GetClosestFrameOfType(anchorFrame, nsGkAtoms::scrollFrame); - nsWeakFrame weakScrollable = scrollable; - fs->HandleClick(offsets.content, offsets.StartOffset(), - offsets.EndOffset(), - true, - false, - offsets.associate); - if (!weakScrollable.IsAlive()) { - return nsEventStatus_eConsumeNoDefault; - } - - // Scroll scrolled frame. - nsIScrollableFrame *saf = do_QueryFrame(scrollable); - nsIFrame *capturingFrame = saf->GetScrolledFrame(); - nsPoint ptInScrolled = movePoint; - nsLayoutUtils::TransformPoint(rootFrame, capturingFrame, ptInScrolled); - fs->StartAutoScrollTimer(capturingFrame, ptInScrolled, TouchCaret::sAutoScrollTimerDelay); - UpdateSelectionCarets(); - return nsEventStatus_eConsumeNoDefault; -} - -nscoord -SelectionCarets::GetCaretYCenterPosition() -{ - nsIFrame* rootFrame = mPresShell->GetRootFrame(); - - if (!rootFrame) { - return 0; - } - - RefPtr selection = GetSelection(); - if (!selection) { - return 0; - } - - int32_t rangeCount = selection->RangeCount(); - if (rangeCount <= 0) { - return 0; - } - - RefPtr fs = GetFrameSelection(); - if (!fs) { - return 0; - } - - MOZ_ASSERT(mDragMode != NONE); - nsCOMPtr node; - uint32_t nodeOffset; - if (mDragMode == START_FRAME) { - RefPtr range = selection->GetRangeAt(0); - node = do_QueryInterface(range->GetStartParent()); - nodeOffset = range->StartOffset(); - } else { - RefPtr range = selection->GetRangeAt(rangeCount - 1); - node = do_QueryInterface(range->GetEndParent()); - nodeOffset = range->EndOffset(); - } - - int32_t offset; - CaretAssociationHint hint = - mDragMode == START_FRAME ? CARET_ASSOCIATE_AFTER : CARET_ASSOCIATE_BEFORE; - nsIFrame* theFrame = - fs->GetFrameForNodeOffset(node, nodeOffset, hint, &offset); - - if (!theFrame) { - return 0; - } - nsRect frameRect = theFrame->GetRectRelativeToSelf(); - nsLayoutUtils::TransformRect(theFrame, rootFrame, frameRect); - return frameRect.Center().y; -} - -void -SelectionCarets::SetSelectionDragState(bool aState) -{ - RefPtr fs = GetFrameSelection(); - if (fs) { - fs->SetDragState(aState); - } -} - -void -SelectionCarets::SetSelectionDirection(nsDirection aDir) -{ - RefPtr selection = GetSelection(); - if (selection) { - selection->AdjustAnchorFocusForMultiRange(aDir); - } -} - -static void -SetFramePos(dom::Element* aElement, const nsRect& aCaretRect) -{ - if (!aElement) { - return; - } - - nsAutoString styleStr; - styleStr.AppendLiteral("left: "); - styleStr.AppendFloat(nsPresContext::AppUnitsToFloatCSSPixels(aCaretRect.Center().x)); - styleStr.AppendLiteral("px; top: "); - styleStr.AppendFloat(nsPresContext::AppUnitsToFloatCSSPixels(aCaretRect.y)); - styleStr.AppendLiteral("px; padding-top: "); - styleStr.AppendFloat(nsPresContext::AppUnitsToFloatCSSPixels(aCaretRect.height)); - styleStr.AppendLiteral("px;"); - - SELECTIONCARETS_LOG_STATIC("Set style: %s", - NS_ConvertUTF16toUTF8(styleStr).get()); - - aElement->SetAttr(kNameSpaceID_None, nsGkAtoms::style, styleStr, true); -} - -void -SelectionCarets::SetStartFramePos(const nsRect& aCaretRect) -{ - SELECTIONCARETS_LOG("x=%d, y=%d, w=%d, h=%d", - aCaretRect.x, aCaretRect.y, aCaretRect.width, aCaretRect.height); - SetFramePos(mPresShell->GetSelectionCaretsStartElement(), aCaretRect); -} - -void -SelectionCarets::SetEndFramePos(const nsRect& aCaretRect) -{ - SELECTIONCARETS_LOG("x=%d, y=%d, w=%d, h=%d", - aCaretRect.x, aCaretRect.y, aCaretRect.width, aCaretRect.height); - SetFramePos(mPresShell->GetSelectionCaretsEndElement(), aCaretRect); -} - -bool -SelectionCarets::IsOnStartFrameInner(const nsPoint& aPosition) -{ - return mVisible && - nsLayoutUtils::ContainsPoint(GetStartFrameRectInner(), aPosition, - SelectionCaretsInflateSize()); -} - -bool -SelectionCarets::IsOnEndFrameInner(const nsPoint& aPosition) -{ - return mVisible && - nsLayoutUtils::ContainsPoint(GetEndFrameRectInner(), aPosition, - SelectionCaretsInflateSize()); -} - -nsRect -SelectionCarets::GetStartFrameRect() -{ - dom::Element* element = mPresShell->GetSelectionCaretsStartElement(); - nsIFrame* rootFrame = mPresShell->GetRootFrame(); - return nsLayoutUtils::GetRectRelativeToFrame(element, rootFrame); -} - -nsRect -SelectionCarets::GetEndFrameRect() -{ - dom::Element* element = mPresShell->GetSelectionCaretsEndElement(); - nsIFrame* rootFrame = mPresShell->GetRootFrame(); - return nsLayoutUtils::GetRectRelativeToFrame(element, rootFrame); -} - -nsRect -SelectionCarets::GetStartFrameRectInner() -{ - dom::Element* element = mPresShell->GetSelectionCaretsStartElement(); - dom::Element* childElement = element->GetFirstElementChild(); - nsIFrame* rootFrame = mPresShell->GetRootFrame(); - return nsLayoutUtils::GetRectRelativeToFrame(childElement, rootFrame); -} - -nsRect -SelectionCarets::GetEndFrameRectInner() -{ - dom::Element* element = mPresShell->GetSelectionCaretsEndElement(); - dom::Element* childElement = element->GetFirstElementChild(); - nsIFrame* rootFrame = mPresShell->GetRootFrame(); - return nsLayoutUtils::GetRectRelativeToFrame(childElement, rootFrame); -} - -nsIContent* -SelectionCarets::GetFocusedContent() -{ - nsFocusManager* fm = nsFocusManager::GetFocusManager(); - if (fm) { - return fm->GetFocusedContent(); - } - - return nullptr; -} - -Selection* -SelectionCarets::GetSelection() -{ - RefPtr fs = GetFrameSelection(); - if (fs) { - return fs->GetSelection(nsISelectionController::SELECTION_NORMAL); - } - return nullptr; -} - -already_AddRefed -SelectionCarets::GetFrameSelection() -{ - nsIContent* focusNode = GetFocusedContent(); - if (focusNode) { - nsIFrame* focusFrame = focusNode->GetPrimaryFrame(); - if (!focusFrame) { - return nullptr; - } - - // Prevent us from touching the nsFrameSelection associated to other - // PresShell. - RefPtr fs = focusFrame->GetFrameSelection(); - if (!fs || fs->GetShell() != mPresShell) { - return nullptr; - } - - return fs.forget(); - } else { - return mPresShell->FrameSelection(); - } -} - -static dom::Sequence -GetSelectionStates(int16_t aReason) -{ - dom::Sequence states; - if (aReason & nsISelectionListener::DRAG_REASON) { - states.AppendElement(SelectionState::Drag, fallible); - } - if (aReason & nsISelectionListener::MOUSEDOWN_REASON) { - states.AppendElement(SelectionState::Mousedown, fallible); - } - if (aReason & nsISelectionListener::MOUSEUP_REASON) { - states.AppendElement(SelectionState::Mouseup, fallible); - } - if (aReason & nsISelectionListener::KEYPRESS_REASON) { - states.AppendElement(SelectionState::Keypress, fallible); - } - if (aReason & nsISelectionListener::SELECTALL_REASON) { - states.AppendElement(SelectionState::Selectall, fallible); - } - if (aReason & nsISelectionListener::COLLAPSETOSTART_REASON) { - states.AppendElement(SelectionState::Collapsetostart, fallible); - } - if (aReason & nsISelectionListener::COLLAPSETOEND_REASON) { - states.AppendElement(SelectionState::Collapsetoend, fallible); - } - return states; -} - -void -SelectionCarets::DispatchCustomEvent(const nsAString& aEvent) -{ - SELECTIONCARETS_LOG("dispatch %s event", NS_ConvertUTF16toUTF8(aEvent).get()); - bool defaultActionEnabled = true; - nsIDocument* doc = mPresShell->GetDocument(); - MOZ_ASSERT(doc); - nsContentUtils::DispatchTrustedEvent(doc, - ToSupports(doc), - aEvent, - true, - false, - &defaultActionEnabled); -} - -void -SelectionCarets::DispatchSelectionStateChangedEvent(Selection* aSelection, - SelectionState aState) -{ - dom::Sequence state; - state.AppendElement(aState, fallible); - DispatchSelectionStateChangedEvent(aSelection, state); -} - -void -SelectionCarets::DispatchSelectionStateChangedEvent(Selection* aSelection, - const Sequence& aStates) -{ - nsIDocument* doc = mPresShell->GetDocument(); - - MOZ_ASSERT(doc); - - SelectionStateChangedEventInit init; - init.mBubbles = true; - - if (aSelection) { - // XXX: Do we need to flush layout? - mPresShell->FlushPendingNotifications(Flush_Layout); - nsRect rect = nsLayoutUtils::GetSelectionBoundingRect(aSelection); - RefPtrdomRect = new DOMRect(ToSupports(doc)); - - domRect->SetLayoutRect(rect); - init.mBoundingClientRect = domRect; - init.mVisible = mSelectionVisibleInScrollFrames; - - aSelection->Stringify(init.mSelectedText); - } - init.mStates = aStates; - - RefPtr event = - SelectionStateChangedEvent::Constructor(doc, NS_LITERAL_STRING("mozselectionstatechanged"), init); - - event->SetTrusted(true); - event->GetInternalNSEvent()->mFlags.mOnlyChromeDispatch = true; - bool ret; - doc->DispatchEvent(event, &ret); -} - -void -SelectionCarets::NotifyBlur(bool aIsLeavingDocument) -{ - SELECTIONCARETS_LOG("Send out the blur event"); - SetVisibility(false); - if (aIsLeavingDocument) { - CancelLongTapDetector(); - } - CancelScrollEndDetector(); - mInAsyncPanZoomGesture = false; - DispatchSelectionStateChangedEvent(nullptr, SelectionState::Blur); -} - -nsresult -SelectionCarets::NotifySelectionChanged(nsIDOMDocument* aDoc, - nsISelection* aSel, - int16_t aReason) -{ - SELECTIONCARETS_LOG("aSel (%p), Reason=%d", aSel, aReason); - - if (aSel != GetSelection()) { - SELECTIONCARETS_LOG("Return for selection mismatch!"); - return NS_OK; - } - - if (!aReason || (aReason & (nsISelectionListener::DRAG_REASON | - nsISelectionListener::KEYPRESS_REASON | - nsISelectionListener::MOUSEDOWN_REASON))) { - SetVisibility(false); - } else { - UpdateSelectionCarets(); - } - - DispatchSelectionStateChangedEvent(static_cast(aSel), - GetSelectionStates(aReason)); - return NS_OK; -} - -static void -DispatchScrollViewChangeEvent(nsIPresShell *aPresShell, const dom::ScrollState aState) -{ - nsCOMPtr doc = aPresShell->GetDocument(); - if (doc) { - bool ret; - ScrollViewChangeEventInit detail; - detail.mBubbles = true; - detail.mCancelable = false; - detail.mState = aState; - RefPtr event = - ScrollViewChangeEvent::Constructor(doc, NS_LITERAL_STRING("scrollviewchange"), detail); - - event->SetTrusted(true); - event->GetInternalNSEvent()->mFlags.mOnlyChromeDispatch = true; - doc->DispatchEvent(event, &ret); - } -} - -void -SelectionCarets::AsyncPanZoomStarted() -{ - if (mVisible) { - mInAsyncPanZoomGesture = true; - SetVisibility(false); - SELECTIONCARETS_LOG("Dispatch scroll started"); - DispatchScrollViewChangeEvent(mPresShell, dom::ScrollState::Started); - } else { - RefPtr selection = GetSelection(); - if (selection && selection->RangeCount() && selection->IsCollapsed()) { - mInAsyncPanZoomGesture = true; - DispatchScrollViewChangeEvent(mPresShell, dom::ScrollState::Started); - } - } -} - -void -SelectionCarets::AsyncPanZoomStopped() -{ - if (mInAsyncPanZoomGesture) { - mInAsyncPanZoomGesture = false; - SELECTIONCARETS_LOG("Update selection carets after APZ is stopped!"); - UpdateSelectionCarets(); - - // SelectionStateChangedEvent should be dispatched before ScrollViewChangeEvent. - DispatchSelectionStateChangedEvent(GetSelection(), - SelectionState::Updateposition); - - SELECTIONCARETS_LOG("Dispatch scroll stopped"); - - DispatchScrollViewChangeEvent(mPresShell, dom::ScrollState::Stopped); - } -} - -void -SelectionCarets::ScrollPositionChanged() -{ - if (mVisible) { - if (!mUseAsyncPanZoom) { - SetVisibility(false); - //TODO: handling scrolling for selection bubble when APZ is off - // Dispatch event to notify gaia to hide selection bubble. - // Positions will be updated when scroll is end, so no need to calculate - // and keep scroll positions here. An arbitrary (0, 0) is sent instead. - DispatchScrollViewChangeEvent(mPresShell, dom::ScrollState::Started); - - SELECTIONCARETS_LOG("Launch scroll end detector"); - LaunchScrollEndDetector(); - } else { - if (!mInAsyncPanZoomGesture) { - UpdateSelectionCarets(); - DispatchSelectionStateChangedEvent(GetSelection(), - SelectionState::Updateposition); - } - } - } else { - RefPtr selection = GetSelection(); - if (selection && selection->RangeCount() && selection->IsCollapsed()) { - DispatchSelectionStateChangedEvent(selection, - SelectionState::Updateposition); - } - } -} - -void -SelectionCarets::LaunchLongTapDetector() -{ - if (mUseAsyncPanZoom) { - return; - } - - if (!mLongTapDetectorTimer) { - mLongTapDetectorTimer = do_CreateInstance("@mozilla.org/timer;1"); - } - - MOZ_ASSERT(mLongTapDetectorTimer); - CancelLongTapDetector(); - int32_t longTapDelay = gfxPrefs::UiClickHoldContextMenusDelay(); - - SELECTIONCARETS_LOG("Will fire long tap after %d ms", longTapDelay); - mLongTapDetectorTimer->InitWithFuncCallback(FireLongTap, - this, - longTapDelay, - nsITimer::TYPE_ONE_SHOT); -} - -void -SelectionCarets::CancelLongTapDetector() -{ - if (mUseAsyncPanZoom) { - return; - } - - if (!mLongTapDetectorTimer) { - return; - } - - SELECTIONCARETS_LOG("Cancel long tap detector!"); - mLongTapDetectorTimer->Cancel(); -} - -/* static */void -SelectionCarets::FireLongTap(nsITimer* aTimer, void* aSelectionCarets) -{ - RefPtr self = static_cast(aSelectionCarets); - NS_PRECONDITION(aTimer == self->mLongTapDetectorTimer, - "Unexpected timer"); - - SELECTIONCARETS_LOG_STATIC("SelectWord from non-APZ"); - nsresult wordSelected = self->SelectWord(); - - if (NS_FAILED(wordSelected)) { - SELECTIONCARETS_LOG_STATIC("SelectWord from non-APZ failed!"); - } -} - -void -SelectionCarets::LaunchScrollEndDetector() -{ - if (!mScrollEndDetectorTimer) { - mScrollEndDetectorTimer = do_CreateInstance("@mozilla.org/timer;1"); - } - - MOZ_ASSERT(mScrollEndDetectorTimer); - - SELECTIONCARETS_LOG("Will fire scroll end after %d ms", - TouchCaret::sScrollEndTimerDelay); - mScrollEndDetectorTimer->InitWithFuncCallback(FireScrollEnd, - this, - TouchCaret::sScrollEndTimerDelay, - nsITimer::TYPE_ONE_SHOT); -} - -void -SelectionCarets::CancelScrollEndDetector() -{ - if (!mScrollEndDetectorTimer) { - return; - } - - SELECTIONCARETS_LOG("Cancel scroll end detector!"); - mScrollEndDetectorTimer->Cancel(); -} - - -/* static */void -SelectionCarets::FireScrollEnd(nsITimer* aTimer, void* aSelectionCarets) -{ - RefPtr self = static_cast(aSelectionCarets); - NS_PRECONDITION(aTimer == self->mScrollEndDetectorTimer, - "Unexpected timer"); - - SELECTIONCARETS_LOG_STATIC("Update selection carets!"); - self->UpdateSelectionCarets(); - self->DispatchSelectionStateChangedEvent(self->GetSelection(), - SelectionState::Updateposition); -} - -NS_IMETHODIMP -SelectionCarets::Reflow(DOMHighResTimeStamp aStart, DOMHighResTimeStamp aEnd) -{ - if (mVisible) { - SELECTIONCARETS_LOG("Update selection carets after reflow!"); - UpdateSelectionCarets(); - - // We don't care selection state when we're at drag mode. We always hide - // bubble in drag mode. So, don't dispatch event here. - if (mDragMode == NONE) { - DispatchSelectionStateChangedEvent(GetSelection(), - SelectionState::Updateposition); - } - } else { - RefPtr selection = GetSelection(); - if (selection && selection->RangeCount() && selection->IsCollapsed()) { - DispatchSelectionStateChangedEvent(selection, - SelectionState::Updateposition); - } - } - return NS_OK; -} - -NS_IMETHODIMP -SelectionCarets::ReflowInterruptible(DOMHighResTimeStamp aStart, - DOMHighResTimeStamp aEnd) -{ - return Reflow(aStart, aEnd); -} diff --git a/layout/base/SelectionCarets.h b/layout/base/SelectionCarets.h deleted file mode 100644 index c5fa5659192b..000000000000 --- a/layout/base/SelectionCarets.h +++ /dev/null @@ -1,277 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=2 sw=2 et tw=78: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef SelectionCarets_h__ -#define SelectionCarets_h__ - -#include "nsDirection.h" -#include "nsIReflowObserver.h" -#include "nsIScrollObserver.h" -#include "nsISelectionListener.h" -#include "nsWeakPtr.h" -#include "nsWeakReference.h" -#include "Units.h" -#include "mozilla/dom/SelectionStateChangedEvent.h" -#include "mozilla/EventForwards.h" -#include "mozilla/WeakPtr.h" - -class nsDocShell; -class nsFrameSelection; -class nsIContent; -class nsIPresShell; -class nsITimer; - -namespace mozilla { - -namespace dom { -class Selection; -} // namespace dom - -/** - * NOTE: SelectionCarets was obsoleted by AccessibleCaret, and is no longer used - * on B2G. This file is going to be removed in bug 1221459. Please see the wiki - * page for more information. https://wiki.mozilla.org/Copy_n_Paste - * - * The SelectionCarets draw a pair of carets when the selection is not - * collapsed, one at each end of the selection. - * SelectionCarets also handle visibility, dragging caret and selecting word - * when long tap event fired. - * - * The DOM structure is 2 div elements for showing start and end caret. - * Each div element has a child div element. That is, each caret consist of - * outer div and inner div. Outer div takes responsibility for detecting two - * carets are overlapping. Inner div is for actual appearance. - * - * Here is an explanation of the html class names: - * .moz-selectioncaret-left: Indicates start DIV. - * .moz-selectioncaret-right: Indicates end DIV. - * .hidden: This class name is set by SetVisibility, - * SetStartFrameVisibility and SetEndFrameVisibility. Element - * with this class name become hidden. - * .tilt: This class name is set by SetTilted. According to the - * UX spec, when selection carets are overlapping, the image of - * caret becomes tilt. - */ -class SelectionCarets final : public nsIReflowObserver, - public nsISelectionListener, - public nsIScrollObserver, - public nsSupportsWeakReference -{ -public: - /** - * Indicate which part of caret we are dragging at. - */ - enum DragMode { - NONE, - START_FRAME, - END_FRAME - }; - - explicit SelectionCarets(nsIPresShell *aPresShell); - - NS_DECL_ISUPPORTS - NS_DECL_NSIREFLOWOBSERVER - NS_DECL_NSISELECTIONLISTENER - - // Notify selection carets about the blur event to hidden itself - void NotifyBlur(bool aIsLeavingDocument); - - // nsIScrollObserver - virtual void ScrollPositionChanged() override; - - // AsyncPanZoom started/stopped callbacks from nsIScrollObserver - virtual void AsyncPanZoomStarted() override; - virtual void AsyncPanZoomStopped() override; - - void Init(); - void Terminate(); - - nsEventStatus HandleEvent(WidgetEvent* aEvent); - - bool GetVisibility() const - { - return mVisible; - } - - /** - * Get from pref "selectioncaret.inflatesize.threshold". This will inflate size of - * caret frame when we checking if user click on caret or not. In app units. - */ - static int32_t SelectionCaretsInflateSize() - { - return sSelectionCaretsInflateSize; - } - - /** - * Set visibility for selection caret. - */ - void SetVisibility(bool aVisible); - - /** - * Update selection caret position base on current selection range. - */ - void UpdateSelectionCarets(); - -private: - virtual ~SelectionCarets(); - - SelectionCarets() = delete; - - /** - * Select a word base on current position, which activates only if element is - * selectable. Triggered by long tap event. - */ - nsresult SelectWord(); - - /** - * Move selection base on current touch/mouse point - */ - nsEventStatus DragSelection(const nsPoint &movePoint); - - /** - * Get the vertical center position of selection caret relative to root - * frame. - */ - nscoord GetCaretYCenterPosition(); - - /** - * Simulate drag state when we change the selection range. - * Hence, the selection change event will fire normally. - */ - void SetSelectionDragState(bool aState); - - void SetSelectionDirection(nsDirection aDir); - - /** - * Move start frame of selection caret based on current caret pos. - * In app units. - */ - void SetStartFramePos(const nsRect& aCaretRect); - - /** - * Move end frame of selection caret based on current caret pos. - * In app units. - */ - void SetEndFramePos(const nsRect& aCaretRect); - - /** - * Check if aPosition is on the start or end frame of the - * selection caret's inner div element. - * - * @param aPosition should be relative to document's root frame - * in app units - */ - bool IsOnStartFrameInner(const nsPoint& aPosition); - bool IsOnEndFrameInner(const nsPoint& aPosition); - - /** - * Get rect of selection caret's outer div element relative - * to document's root frame, in app units. - */ - nsRect GetStartFrameRect(); - nsRect GetEndFrameRect(); - - /** - * Get rect of selection caret's inner div element relative - * to document's root frame, in app units. - */ - nsRect GetStartFrameRectInner(); - nsRect GetEndFrameRectInner(); - - /** - * Set visibility for start part of selection caret, this function - * only affects css property of start frame. So it doesn't change - * mVisible member. When caret overflows element's box we'll hide - * it by calling this function. - */ - void SetStartFrameVisibility(bool aVisible); - - /** - * Same as above function but for end frame of selection caret. - */ - void SetEndFrameVisibility(bool aVisible); - - /** - * Set tilt class name to start and end frame of selection caret. - */ - void SetTilted(bool aIsTilt); - - // Utility functions - dom::Selection* GetSelection(); - already_AddRefed GetFrameSelection(); - nsIContent* GetFocusedContent(); - void DispatchSelectionStateChangedEvent(dom::Selection* aSelection, - dom::SelectionState aState); - void DispatchSelectionStateChangedEvent(dom::Selection* aSelection, - const dom::Sequence& aStates); - void DispatchCustomEvent(const nsAString& aEvent); - - /** - * Detecting long tap using timer - */ - void LaunchLongTapDetector(); - void CancelLongTapDetector(); - static void FireLongTap(nsITimer* aTimer, void* aSelectionCarets); - - void LaunchScrollEndDetector(); - void CancelScrollEndDetector(); - static void FireScrollEnd(nsITimer* aTimer, void* aSelectionCarets); - - nsIPresShell* mPresShell; - WeakPtr mDocShell; - - // This timer is used for detecting long tap fire. If content process - // has APZC, we'll use APZC for long tap detecting. Otherwise, we use this - // timer to detect long tap. - nsCOMPtr mLongTapDetectorTimer; - - // This timer is used for detecting scroll end. We don't have - // scroll end event now, so we will fire this event with a - // const time when we scroll. So when timer triggers, we treat it - // as scroll end event. - nsCOMPtr mScrollEndDetectorTimer; - - // When touch or mouse down, we save the position for detecting - // drag distance - nsPoint mDownPoint; - - // For filter multitouch event - int32_t mActiveTouchId; - - nscoord mCaretCenterToDownPointOffsetY; - - // The horizontal boundary is defined by the first selected frame which - // determines the start-caret position. When users drag the end-caret up, - // the touch input(pos.y) will be changed to not cross this boundary. - // Otherwise, the selection range changes to one character only - // which causes the bad user experience. - nscoord mDragUpYBoundary; - // The horizontal boundary is defined by the last selected frame which - // determines the end-caret position. When users drag the start-caret down, - // the touch input(pos.y) will be changed to not cross this boundary. - // Otherwise, the selection range changes to one character only - // which causes the bad user experience. - nscoord mDragDownYBoundary; - - DragMode mDragMode; - - // True if async-pan-zoom should be used for selection carets. - bool mUseAsyncPanZoom; - // True if AsyncPanZoom is started - bool mInAsyncPanZoomGesture; - - bool mEndCaretVisible; - bool mStartCaretVisible; - bool mSelectionVisibleInScrollFrames; - bool mVisible; - - // Preference - static int32_t sSelectionCaretsInflateSize; -}; - -} // namespace mozilla - -#endif //SelectionCarets_h__ diff --git a/layout/base/TouchCaret.cpp b/layout/base/TouchCaret.cpp deleted file mode 100644 index d97952a30e1a..000000000000 --- a/layout/base/TouchCaret.cpp +++ /dev/null @@ -1,1110 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=2 sw=2 et tw=78: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "mozilla/Logging.h" -#include "TouchCaret.h" - -#include - -#include "nsBlockFrame.h" -#include "nsCanvasFrame.h" -#include "nsCaret.h" -#include "nsCOMPtr.h" -#include "nsContentUtils.h" -#include "nsDOMTokenList.h" -#include "nsFrameSelection.h" -#include "nsIContent.h" -#include "nsIDOMNode.h" -#include "nsIDOMWindow.h" -#include "nsIFrame.h" -#include "nsIInterfaceRequestorUtils.h" -#include "nsIPresShell.h" -#include "nsIScrollableFrame.h" -#include "nsISelection.h" -#include "nsISelectionController.h" -#include "nsISelectionPrivate.h" -#include "nsPresContext.h" -#include "nsQueryContentEventResult.h" -#include "nsView.h" -#include "mozilla/dom/SelectionStateChangedEvent.h" -#include "mozilla/dom/CustomEvent.h" -#include "mozilla/BasicEvents.h" -#include "mozilla/Preferences.h" - -using namespace mozilla; - -static const char* kTouchCaretLogModuleName = "TouchCaret"; -static mozilla::LazyLogModule gTouchCaretLog(kTouchCaretLogModuleName); - -// To enable all the TOUCHCARET_LOG print statements, set the environment -// variable NSPR_LOG_MODULES=TouchCaret:5 -#define TOUCHCARET_LOG(message, ...) \ - MOZ_LOG(gTouchCaretLog, LogLevel::Debug, \ - ("TouchCaret (%p): %s:%d : " message "\n", this, __FUNCTION__, \ - __LINE__, ##__VA_ARGS__)); - -#define TOUCHCARET_LOG_STATIC(message, ...) \ - MOZ_LOG(gTouchCaretLog, LogLevel::Debug, \ - ("TouchCaret: %s:%d : " message "\n", __FUNCTION__, __LINE__, \ - ##__VA_ARGS__)); - -// Click on the boundary of input/textarea will place the caret at the -// front/end of the content. To advoid this, we need to deflate the content -// boundary by 61 app units (1 pixel + 1 app unit). -static const int32_t kBoundaryAppUnits = 61; - -NS_IMPL_ISUPPORTS(TouchCaret, - nsISelectionListener, - nsIScrollObserver, - nsISupportsWeakReference) - -/*static*/ int32_t TouchCaret::sTouchCaretInflateSize = 0; -/*static*/ int32_t TouchCaret::sTouchCaretExpirationTime = 0; - -TouchCaret::TouchCaret(nsIPresShell* aPresShell) - : mState(TOUCHCARET_NONE), - mActiveTouchId(-1), - mCaretCenterToDownPointOffsetY(0), - mInAsyncPanZoomGesture(false), - mVisible(false) -{ - MOZ_ASSERT(NS_IsMainThread()); - - TOUCHCARET_LOG("Constructor, PresShell=%p", aPresShell); - - static bool addedTouchCaretPref = false; - if (!addedTouchCaretPref) { - Preferences::AddIntVarCache(&sTouchCaretInflateSize, - "touchcaret.inflatesize.threshold"); - Preferences::AddIntVarCache(&sTouchCaretExpirationTime, - "touchcaret.expiration.time"); - addedTouchCaretPref = true; - } - - // The presshell owns us, so no addref. - mPresShell = do_GetWeakReference(aPresShell); - MOZ_ASSERT(mPresShell, "Hey, pres shell should support weak refs"); -} - -void -TouchCaret::Init() -{ - nsCOMPtr presShell = do_QueryReferent(mPresShell); - if (!presShell) { - return; - } - - nsPresContext* presContext = presShell->GetPresContext(); - MOZ_ASSERT(presContext, "PresContext should be given in PresShell::Init()"); - - nsIDocShell* docShell = presContext->GetDocShell(); - if (!docShell) { - return; - } - - docShell->AddWeakScrollObserver(this); - mDocShell = static_cast(docShell); -} - -void -TouchCaret::Terminate() -{ - RefPtr docShell(mDocShell.get()); - if (docShell) { - docShell->RemoveWeakScrollObserver(this); - } - - if (mScrollEndDetectorTimer) { - mScrollEndDetectorTimer->Cancel(); - mScrollEndDetectorTimer = nullptr; - } - - mDocShell = WeakPtr(); - mPresShell = nullptr; -} - -TouchCaret::~TouchCaret() -{ - TOUCHCARET_LOG("Destructor"); - MOZ_ASSERT(NS_IsMainThread()); - - if (mTouchCaretExpirationTimer) { - mTouchCaretExpirationTimer->Cancel(); - mTouchCaretExpirationTimer = nullptr; - } -} - -nsIFrame* -TouchCaret::GetCaretFocusFrame(nsRect* aOutRect) -{ - nsCOMPtr presShell = do_QueryReferent(mPresShell); - if (!presShell) { - return nullptr; - } - - RefPtr caret = presShell->GetCaret(); - if (!caret) { - return nullptr; - } - - nsRect rect; - nsIFrame* frame = caret->GetGeometry(&rect); - - if (aOutRect) { - *aOutRect = rect; - } - - return frame; -} - -nsCanvasFrame* -TouchCaret::GetCanvasFrame() -{ - nsCOMPtr presShell = do_QueryReferent(mPresShell); - if (!presShell) { - return nullptr; - } - return presShell->GetCanvasFrame(); -} - -nsIFrame* -TouchCaret::GetRootFrame() -{ - nsCOMPtr presShell = do_QueryReferent(mPresShell); - if (!presShell) { - return nullptr; - } - return presShell->GetRootFrame(); -} - -void -TouchCaret::SetVisibility(bool aVisible) -{ - if (mVisible == aVisible) { - TOUCHCARET_LOG("Set visibility %s, same as the old one", - (aVisible ? "shown" : "hidden")); - return; - } - - nsCOMPtr presShell = do_QueryReferent(mPresShell); - if (!presShell) { - return; - } - - mozilla::dom::Element* touchCaretElement = presShell->GetTouchCaretElement(); - if (!touchCaretElement) { - return; - } - - mVisible = aVisible; - - // Set touch caret visibility. - ErrorResult err; - touchCaretElement->ClassList()->Toggle(NS_LITERAL_STRING("hidden"), - dom::Optional(!mVisible), - err); - TOUCHCARET_LOG("Set visibility %s", (mVisible ? "shown" : "hidden")); - - // Set touch caret expiration time. - mVisible ? LaunchExpirationTimer() : CancelExpirationTimer(); -} - -nsRect -TouchCaret::GetTouchFrameRect() -{ - nsCOMPtr presShell = do_QueryReferent(mPresShell); - if (!presShell) { - return nsRect(); - } - - dom::Element* touchCaretElement = presShell->GetTouchCaretElement(); - nsIFrame* canvasFrame = GetCanvasFrame(); - return nsLayoutUtils::GetRectRelativeToFrame(touchCaretElement, canvasFrame); -} - -nsRect -TouchCaret::GetContentBoundary() -{ - nsIFrame* focusFrame = GetCaretFocusFrame(); - nsIFrame* canvasFrame = GetCanvasFrame(); - if (!focusFrame || !canvasFrame) { - return nsRect(); - } - - // Get the editing host to determine the touch caret dragable boundary. - dom::Element* editingHost = focusFrame->GetContent()->GetEditingHost(); - if (!editingHost) { - return nsRect(); - } - - nsRect resultRect; - for (nsIFrame* frame = editingHost->GetPrimaryFrame(); frame; - frame = frame->GetNextContinuation()) { - nsRect rect = frame->GetContentRectRelativeToSelf(); - nsLayoutUtils::TransformRect(frame, canvasFrame, rect); - resultRect = resultRect.Union(rect); - - mozilla::layout::FrameChildListIterator lists(frame); - for (; !lists.IsDone(); lists.Next()) { - // Loop over all children to take the overflow rect in to consideration. - nsFrameList::Enumerator childFrames(lists.CurrentList()); - for (; !childFrames.AtEnd(); childFrames.Next()) { - nsIFrame* kid = childFrames.get(); - nsRect overflowRect = kid->GetScrollableOverflowRect(); - nsLayoutUtils::TransformRect(kid, canvasFrame, overflowRect); - resultRect = resultRect.Union(overflowRect); - } - } - } - // Shrink rect to make sure we never hit the boundary. - resultRect.Deflate(kBoundaryAppUnits); - - return resultRect; -} - -nscoord -TouchCaret::GetCaretYCenterPosition() -{ - nsRect caretRect; - nsIFrame* focusFrame = GetCaretFocusFrame(&caretRect); - nsIFrame* canvasFrame = GetCanvasFrame(); - - nsLayoutUtils::TransformRect(focusFrame, canvasFrame, caretRect); - - return (caretRect.y + caretRect.height / 2); -} - -void -TouchCaret::SetTouchFramePos(const nsRect& aCaretRect) -{ - nsCOMPtr presShell = do_QueryReferent(mPresShell); - if (!presShell) { - return; - } - - mozilla::dom::Element* touchCaretElement = presShell->GetTouchCaretElement(); - if (!touchCaretElement) { - return; - } - - // Convert aOrigin to CSS pixels. - RefPtr presContext = presShell->GetPresContext(); - int32_t x = presContext->AppUnitsToIntCSSPixels(aCaretRect.Center().x); - int32_t y = presContext->AppUnitsToIntCSSPixels(aCaretRect.y); - int32_t padding = presContext->AppUnitsToIntCSSPixels(aCaretRect.height); - - nsAutoString styleStr; - styleStr.AppendLiteral("left: "); - styleStr.AppendInt(x); - styleStr.AppendLiteral("px; top: "); - styleStr.AppendInt(y); - styleStr.AppendLiteral("px; padding-top: "); - styleStr.AppendInt(padding); - styleStr.AppendLiteral("px;"); - - TOUCHCARET_LOG("Set style: %s", NS_ConvertUTF16toUTF8(styleStr).get()); - - touchCaretElement->SetAttr(kNameSpaceID_None, nsGkAtoms::style, - styleStr, true); -} - -void -TouchCaret::MoveCaret(const nsPoint& movePoint) -{ - nsIFrame* focusFrame = GetCaretFocusFrame(); - nsIFrame* canvasFrame = GetCanvasFrame(); - if (!focusFrame && !canvasFrame) { - return; - } - nsIFrame* scrollable = - nsLayoutUtils::GetClosestFrameOfType(focusFrame, nsGkAtoms::scrollFrame); - - // Convert touch/mouse position to frame coordinates. - nsPoint offsetToCanvasFrame = nsPoint(0,0); - nsLayoutUtils::TransformPoint(scrollable, canvasFrame, offsetToCanvasFrame); - nsPoint pt = movePoint - offsetToCanvasFrame; - - // Evaluate offsets. - nsIFrame::ContentOffsets offsets = - scrollable->GetContentOffsetsFromPoint(pt, nsIFrame::SKIP_HIDDEN); - - // Move caret position. - nsWeakFrame weakScrollable = scrollable; - RefPtr fs = scrollable->GetFrameSelection(); - fs->HandleClick(offsets.content, offsets.StartOffset(), - offsets.EndOffset(), - false, - false, - offsets.associate); - - if (!weakScrollable.IsAlive()) { - return; - } - - // Scroll scrolled frame. - nsIScrollableFrame* saf = do_QueryFrame(scrollable); - nsIFrame* capturingFrame = saf->GetScrolledFrame(); - offsetToCanvasFrame = nsPoint(0,0); - nsLayoutUtils::TransformPoint(capturingFrame, canvasFrame, offsetToCanvasFrame); - pt = movePoint - offsetToCanvasFrame; - fs->StartAutoScrollTimer(capturingFrame, pt, sAutoScrollTimerDelay); -} - -bool -TouchCaret::IsOnTouchCaret(const nsPoint& aPoint) -{ - return mVisible && nsLayoutUtils::ContainsPoint(GetTouchFrameRect(), aPoint, - TouchCaretInflateSize()); -} - -nsresult -TouchCaret::NotifySelectionChanged(nsIDOMDocument* aDoc, nsISelection* aSel, - int16_t aReason) -{ - TOUCHCARET_LOG("aSel (%p), Reason=%d", aSel, aReason); - - // Hide touch caret while no caret exists. - nsCOMPtr presShell = do_QueryReferent(mPresShell); - if (!presShell) { - return NS_OK; - } - - RefPtr caret = presShell->GetCaret(); - if (!caret) { - SetVisibility(false); - return NS_OK; - } - - // The same touch caret is shared amongst the document and any text widgets it - // may contain. This means that the touch caret could get notifications from - // multiple selections. - // If this notification is for a selection that is not the one the - // the caret is currently interested in , then there is nothing to do! - if (aSel != caret->GetSelection()) { - TOUCHCARET_LOG("Return for selection mismatch!"); - return NS_OK; - } - - // Update touch caret position and visibility. - // Hide touch caret while key event causes selection change. - // Also hide touch caret when gecko or javascript collapse the selection. - if (aReason & nsISelectionListener::KEYPRESS_REASON || - aReason & nsISelectionListener::COLLAPSETOSTART_REASON || - aReason & nsISelectionListener::COLLAPSETOEND_REASON) { - TOUCHCARET_LOG("KEYPRESS_REASON"); - SetVisibility(false); - } else { - SyncVisibilityWithCaret(); - } - - return NS_OK; -} - -/** - * Used to update caret position after PanZoom stops for - * extended caret visibility. Never needed by MOZ_WIDGET_GONK. - */ -void -TouchCaret::AsyncPanZoomStarted() -{ -} - -void -TouchCaret::AsyncPanZoomStopped() -{ - if (mInAsyncPanZoomGesture) { - mInAsyncPanZoomGesture = false; - UpdatePosition(); - } -} - -/** - * Used to update caret position after Scroll stops for - * extended caret visibility. Never needed by MOZ_WIDGET_GONK. - */ -void -TouchCaret::ScrollPositionChanged() -{ -} - -void -TouchCaret::LaunchScrollEndDetector() -{ - if (!mScrollEndDetectorTimer) { - mScrollEndDetectorTimer = do_CreateInstance("@mozilla.org/timer;1"); - } - MOZ_ASSERT(mScrollEndDetectorTimer); - - mScrollEndDetectorTimer->InitWithFuncCallback(FireScrollEnd, - this, - sScrollEndTimerDelay, - nsITimer::TYPE_ONE_SHOT); -} - -void -TouchCaret::CancelScrollEndDetector() -{ - if (mScrollEndDetectorTimer) { - mScrollEndDetectorTimer->Cancel(); - } -} - - -/* static */void -TouchCaret::FireScrollEnd(nsITimer* aTimer, void* aTouchCaret) -{ - RefPtr self = static_cast(aTouchCaret); - NS_PRECONDITION(aTimer == self->mScrollEndDetectorTimer, - "Unexpected timer"); - self->UpdatePosition(); -} - -void -TouchCaret::SyncVisibilityWithCaret() -{ - TOUCHCARET_LOG("SyncVisibilityWithCaret"); - - if (!IsDisplayable()) { - SetVisibility(false); - return; - } - - SetVisibility(true); - if (mVisible) { - UpdatePosition(); - } -} - -void -TouchCaret::UpdatePositionIfNeeded() -{ - TOUCHCARET_LOG("UpdatePositionIfNeeded"); - - if (!IsDisplayable()) { - SetVisibility(false); - return; - } - - if (mVisible) { - UpdatePosition(); - } -} - -bool -TouchCaret::IsDisplayable() -{ - nsCOMPtr presShell = do_QueryReferent(mPresShell); - if (!presShell) { - TOUCHCARET_LOG("PresShell is nullptr!"); - return false; - } - - RefPtr caret = presShell->GetCaret(); - if (!caret) { - TOUCHCARET_LOG("Caret is nullptr!"); - return false; - } - - nsIFrame* canvasFrame = GetCanvasFrame(); - if (!canvasFrame) { - TOUCHCARET_LOG("No canvas frame!"); - return false; - } - - nsIFrame* rootFrame = GetRootFrame(); - if (!rootFrame) { - TOUCHCARET_LOG("No root frame!"); - return false; - } - - dom::Element* touchCaretElement = presShell->GetTouchCaretElement(); - if (!touchCaretElement) { - TOUCHCARET_LOG("No touch caret frame element!"); - return false; - } - - if (presShell->IsPaintingSuppressed()) { - TOUCHCARET_LOG("PresShell is suppressing painting!"); - return false; - } - - if (!caret->IsVisible()) { - TOUCHCARET_LOG("Caret is not visible!"); - return false; - } - - nsRect focusRect; - nsIFrame* focusFrame = caret->GetGeometry(&focusRect); - if (!focusFrame) { - TOUCHCARET_LOG("Focus frame is not valid!"); - return false; - } - - dom::Element* editingHost = focusFrame->GetContent()->GetEditingHost(); - if (!editingHost) { - TOUCHCARET_LOG("Cannot get editing host!"); - return false; - } - - if (focusRect.IsEmpty()) { - TOUCHCARET_LOG("Focus rect is empty!"); - return false; - } - - if (!nsContentUtils::HasNonEmptyTextContent( - editingHost, nsContentUtils::eRecurseIntoChildren)) { - TOUCHCARET_LOG("The content is empty!"); - return false; - } - - if (mState != TOUCHCARET_TOUCHDRAG_ACTIVE && - !nsLayoutUtils::IsRectVisibleInScrollFrames(focusFrame, focusRect)) { - TOUCHCARET_LOG("Caret does not show in the scrollable frame!"); - return false; - } - - TOUCHCARET_LOG("Touch caret is displayable!"); - return true; -} - -void -TouchCaret::UpdatePosition() -{ - MOZ_ASSERT(mVisible); - - nsRect rect = GetTouchCaretRect(); - rect = ClampRectToScrollFrame(rect); - SetTouchFramePos(rect); -} - -nsRect -TouchCaret::GetTouchCaretRect() -{ - nsRect focusRect; - nsIFrame* focusFrame = GetCaretFocusFrame(&focusRect); - nsIFrame* rootFrame = GetRootFrame(); - // Transform the position to make it relative to root frame. - nsLayoutUtils::TransformRect(focusFrame, rootFrame, focusRect); - - return focusRect; -} - -nsRect -TouchCaret::ClampRectToScrollFrame(const nsRect& aRect) -{ - nsRect rect = aRect; - nsIFrame* focusFrame = GetCaretFocusFrame(); - nsIFrame* rootFrame = GetRootFrame(); - - // Clamp the touch caret position to the scrollframe boundary. - nsIFrame* closestScrollFrame = - nsLayoutUtils::GetClosestFrameOfType(focusFrame, nsGkAtoms::scrollFrame); - - while (closestScrollFrame) { - nsIScrollableFrame* sf = do_QueryFrame(closestScrollFrame); - nsRect visualRect = sf->GetScrollPortRect(); - - // Clamp the touch caret in the scroll port. - nsLayoutUtils::TransformRect(closestScrollFrame, rootFrame, visualRect); - rect = rect.Intersect(visualRect); - - // Get next ancestor scroll frame. - closestScrollFrame = - nsLayoutUtils::GetClosestFrameOfType(closestScrollFrame->GetParent(), - nsGkAtoms::scrollFrame); - } - - return rect; -} - -/* static */void -TouchCaret::DisableTouchCaretCallback(nsITimer* aTimer, void* aTouchCaret) -{ - RefPtr self = static_cast(aTouchCaret); - NS_PRECONDITION(aTimer == self->mTouchCaretExpirationTimer, - "Unexpected timer"); - - self->SetVisibility(false); -} - -void -TouchCaret::LaunchExpirationTimer() -{ - if (TouchCaretExpirationTime() > 0) { - if (!mTouchCaretExpirationTimer) { - mTouchCaretExpirationTimer = do_CreateInstance("@mozilla.org/timer;1"); - } - - if (mTouchCaretExpirationTimer) { - mTouchCaretExpirationTimer->Cancel(); - mTouchCaretExpirationTimer->InitWithFuncCallback(DisableTouchCaretCallback, - this, - TouchCaretExpirationTime(), - nsITimer::TYPE_ONE_SHOT); - } - } -} - -void -TouchCaret::CancelExpirationTimer() -{ - if (mTouchCaretExpirationTimer) { - mTouchCaretExpirationTimer->Cancel(); - } -} - -void -TouchCaret::SetSelectionDragState(bool aState) -{ - nsIFrame* caretFocusFrame = GetCaretFocusFrame(); - if (!caretFocusFrame) { - return; - } - - RefPtr fs = caretFocusFrame->GetFrameSelection(); - fs->SetDragState(aState); -} - -nsEventStatus -TouchCaret::HandleEvent(WidgetEvent* aEvent) -{ - MOZ_ASSERT(NS_IsMainThread()); - if (!IsDisplayable()) { - return nsEventStatus_eIgnore; - } - - nsEventStatus status = nsEventStatus_eIgnore; - - switch (aEvent->mMessage) { - case eTouchStart: - status = HandleTouchDownEvent(aEvent->AsTouchEvent()); - break; - case eMouseDown: - status = HandleMouseDownEvent(aEvent->AsMouseEvent()); - break; - case eTouchEnd: - status = HandleTouchUpEvent(aEvent->AsTouchEvent()); - break; - case eMouseUp: - status = HandleMouseUpEvent(aEvent->AsMouseEvent()); - break; - case eTouchMove: - status = HandleTouchMoveEvent(aEvent->AsTouchEvent()); - break; - case eMouseMove: - status = HandleMouseMoveEvent(aEvent->AsMouseEvent()); - break; - case eTouchCancel: - mTouchesId.Clear(); - SetState(TOUCHCARET_NONE); - LaunchExpirationTimer(); - break; - case eKeyUp: - case eKeyDown: - case eKeyPress: - case eWheel: - case eWheelOperationStart: - case eWheelOperationEnd: - // Disable touch caret while key/wheel event is received. - TOUCHCARET_LOG("Receive key/wheel event %d", aEvent->mMessage); - SetVisibility(false); - break; - case eMouseLongTap: - if (mState == TOUCHCARET_TOUCHDRAG_ACTIVE) { - // Disable long tap event from APZ while dragging the touch caret. - status = nsEventStatus_eConsumeNoDefault; - } - break; - default: - break; - } - - return status; -} - -nsPoint -TouchCaret::GetEventPosition(WidgetTouchEvent* aEvent, int32_t aIdentifier) -{ - for (size_t i = 0; i < aEvent->touches.Length(); i++) { - if (aEvent->touches[i]->mIdentifier == aIdentifier) { - // Get event coordinate relative to canvas frame. - nsIFrame* canvasFrame = GetCanvasFrame(); - LayoutDeviceIntPoint touchIntPoint = aEvent->touches[i]->mRefPoint; - return nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, - touchIntPoint, - canvasFrame); - } - } - return nsPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE); -} - -nsPoint -TouchCaret::GetEventPosition(WidgetMouseEvent* aEvent) -{ - // Get event coordinate relative to canvas frame. - nsIFrame* canvasFrame = GetCanvasFrame(); - LayoutDeviceIntPoint mouseIntPoint = aEvent->AsGUIEvent()->refPoint; - return nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, - mouseIntPoint, - canvasFrame); -} - -nsEventStatus -TouchCaret::HandleMouseMoveEvent(WidgetMouseEvent* aEvent) -{ - TOUCHCARET_LOG("Got a mouse-move in state %d", mState); - nsEventStatus status = nsEventStatus_eIgnore; - - switch (mState) { - case TOUCHCARET_NONE: - break; - - case TOUCHCARET_MOUSEDRAG_ACTIVE: - { - nsPoint movePoint = GetEventPosition(aEvent); - movePoint.y += mCaretCenterToDownPointOffsetY; - nsRect contentBoundary = GetContentBoundary(); - movePoint = contentBoundary.ClampPoint(movePoint); - - MoveCaret(movePoint); - mIsValidTap = false; - status = nsEventStatus_eConsumeNoDefault; - } - break; - - case TOUCHCARET_TOUCHDRAG_ACTIVE: - case TOUCHCARET_TOUCHDRAG_INACTIVE: - // Consume mouse event in touch sequence. - status = nsEventStatus_eConsumeNoDefault; - break; - } - - return status; -} - -nsEventStatus -TouchCaret::HandleTouchMoveEvent(WidgetTouchEvent* aEvent) -{ - TOUCHCARET_LOG("Got a touch-move in state %d", mState); - nsEventStatus status = nsEventStatus_eIgnore; - - switch (mState) { - case TOUCHCARET_NONE: - break; - - case TOUCHCARET_MOUSEDRAG_ACTIVE: - // Consume touch event in mouse sequence. - status = nsEventStatus_eConsumeNoDefault; - break; - - case TOUCHCARET_TOUCHDRAG_ACTIVE: - { - nsPoint movePoint = GetEventPosition(aEvent, mActiveTouchId); - movePoint.y += mCaretCenterToDownPointOffsetY; - nsRect contentBoundary = GetContentBoundary(); - movePoint = contentBoundary.ClampPoint(movePoint); - - MoveCaret(movePoint); - mIsValidTap = false; - status = nsEventStatus_eConsumeNoDefault; - } - break; - - case TOUCHCARET_TOUCHDRAG_INACTIVE: - // Consume eTouchMove event in TOUCHCARET_TOUCHDRAG_INACTIVE state. - status = nsEventStatus_eConsumeNoDefault; - break; - } - - return status; -} - -nsEventStatus -TouchCaret::HandleMouseUpEvent(WidgetMouseEvent* aEvent) -{ - TOUCHCARET_LOG("Got a mouse-up in state %d", mState); - nsEventStatus status = nsEventStatus_eIgnore; - - switch (mState) { - case TOUCHCARET_NONE: - break; - - case TOUCHCARET_MOUSEDRAG_ACTIVE: - if (aEvent->button == WidgetMouseEvent::eLeftButton) { - SetSelectionDragState(false); - LaunchExpirationTimer(); - SetState(TOUCHCARET_NONE); - status = nsEventStatus_eConsumeNoDefault; - } - break; - - case TOUCHCARET_TOUCHDRAG_ACTIVE: - case TOUCHCARET_TOUCHDRAG_INACTIVE: - // Consume mouse event in touch sequence. - status = nsEventStatus_eConsumeNoDefault; - break; - } - - return status; -} - -nsEventStatus -TouchCaret::HandleTouchUpEvent(WidgetTouchEvent* aEvent) -{ - TOUCHCARET_LOG("Got a touch-end in state %d", mState); - // Remove touches from cache if the stroke is gone in TOUCHDRAG states. - if (mState == TOUCHCARET_TOUCHDRAG_ACTIVE || - mState == TOUCHCARET_TOUCHDRAG_INACTIVE) { - for (size_t i = 0; i < aEvent->touches.Length(); i++) { - nsTArray::index_type index = - mTouchesId.IndexOf(aEvent->touches[i]->mIdentifier); - MOZ_ASSERT(index != nsTArray::NoIndex); - mTouchesId.RemoveElementAt(index); - } - } - - nsEventStatus status = nsEventStatus_eIgnore; - - switch (mState) { - case TOUCHCARET_NONE: - break; - - case TOUCHCARET_MOUSEDRAG_ACTIVE: - // Consume touch event in mouse sequence. - status = nsEventStatus_eConsumeNoDefault; - break; - - case TOUCHCARET_TOUCHDRAG_ACTIVE: - if (mTouchesId.Length() == 0) { - SetSelectionDragState(false); - // No more finger on the screen. - SetState(TOUCHCARET_NONE); - LaunchExpirationTimer(); - } else { - // Still has finger touching on the screen. - if (aEvent->touches[0]->mIdentifier == mActiveTouchId) { - // Remove finger from the touch caret. - SetState(TOUCHCARET_TOUCHDRAG_INACTIVE); - LaunchExpirationTimer(); - } else { - // If the finger removed is not the finger on touch caret, remain in - // TOUCHCARET_DRAG_ACTIVE state. - } - } - status = nsEventStatus_eConsumeNoDefault; - break; - - case TOUCHCARET_TOUCHDRAG_INACTIVE: - if (mTouchesId.Length() == 0) { - // No more finger on the screen. - SetState(TOUCHCARET_NONE); - } - status = nsEventStatus_eConsumeNoDefault; - break; - } - - return status; -} - -nsEventStatus -TouchCaret::HandleMouseDownEvent(WidgetMouseEvent* aEvent) -{ - TOUCHCARET_LOG("Got a mouse-down in state %d", mState); - if (!GetVisibility()) { - // If touch caret is invisible, bypass event. - return nsEventStatus_eIgnore; - } - - nsEventStatus status = nsEventStatus_eIgnore; - - switch (mState) { - case TOUCHCARET_NONE: - if (aEvent->button == WidgetMouseEvent::eLeftButton) { - nsPoint point = GetEventPosition(aEvent); - if (IsOnTouchCaret(point)) { - SetSelectionDragState(true); - // Cache distence of the event point to the center of touch caret. - mCaretCenterToDownPointOffsetY = GetCaretYCenterPosition() - point.y; - // Enter TOUCHCARET_MOUSEDRAG_ACTIVE state and cancel the timer. - SetState(TOUCHCARET_MOUSEDRAG_ACTIVE); - CancelExpirationTimer(); - status = nsEventStatus_eConsumeNoDefault; - } else { - // Set touch caret invisible if HisTest fails. Bypass event. - SetVisibility(false); - status = nsEventStatus_eIgnore; - } - } else { - // Set touch caret invisible if not left button down event. - SetVisibility(false); - status = nsEventStatus_eIgnore; - } - break; - - case TOUCHCARET_MOUSEDRAG_ACTIVE: - SetVisibility(false); - SetState(TOUCHCARET_NONE); - break; - - case TOUCHCARET_TOUCHDRAG_ACTIVE: - case TOUCHCARET_TOUCHDRAG_INACTIVE: - // Consume mouse event in touch sequence. - status = nsEventStatus_eConsumeNoDefault; - break; - } - - return status; -} - -nsEventStatus -TouchCaret::HandleTouchDownEvent(WidgetTouchEvent* aEvent) -{ - TOUCHCARET_LOG("Got a touch-start in state %d", mState); - - nsEventStatus status = nsEventStatus_eIgnore; - - switch (mState) { - case TOUCHCARET_NONE: - if (!GetVisibility()) { - // If touch caret is invisible, bypass event. - status = nsEventStatus_eIgnore; - } else { - // Loop over all the touches and see if any of them is on the touch - // caret. - for (size_t i = 0; i < aEvent->touches.Length(); ++i) { - int32_t touchId = aEvent->touches[i]->Identifier(); - nsPoint point = GetEventPosition(aEvent, touchId); - if (IsOnTouchCaret(point)) { - SetSelectionDragState(true); - // Touch start position is contained in touch caret. - mActiveTouchId = touchId; - // Cache distance of the event point to the center of touch caret. - mCaretCenterToDownPointOffsetY = GetCaretYCenterPosition() - point.y; - // Enter TOUCHCARET_TOUCHDRAG_ACTIVE state and cancel the timer. - SetState(TOUCHCARET_TOUCHDRAG_ACTIVE); - CancelExpirationTimer(); - status = nsEventStatus_eConsumeNoDefault; - break; - } - } - // No touch is on the touch caret. Set touch caret invisible, and bypass - // the event. - if (mActiveTouchId == -1) { - SetVisibility(false); - status = nsEventStatus_eIgnore; - } - } - break; - - case TOUCHCARET_MOUSEDRAG_ACTIVE: - case TOUCHCARET_TOUCHDRAG_ACTIVE: - case TOUCHCARET_TOUCHDRAG_INACTIVE: - // Consume eTouchStart event. - status = nsEventStatus_eConsumeNoDefault; - break; - } - - // Cache active touch IDs in TOUCHDRAG states. - if (mState == TOUCHCARET_TOUCHDRAG_ACTIVE || - mState == TOUCHCARET_TOUCHDRAG_INACTIVE) { - mTouchesId.Clear(); - for (size_t i = 0; i < aEvent->touches.Length(); i++) { - mTouchesId.AppendElement(aEvent->touches[i]->mIdentifier); - } - } - - return status; -} - -void -TouchCaret::DispatchTapEvent() -{ - nsCOMPtr presShell = do_QueryReferent(mPresShell); - if (!presShell) { - return; - } - - RefPtr caret = presShell->GetCaret(); - if (!caret) { - return; - } - - dom::Selection* sel = static_cast(caret->GetSelection()); - if (!sel) { - return; - } - - nsIDocument* doc = presShell->GetDocument(); - - MOZ_ASSERT(doc); - - dom::SelectionStateChangedEventInit init; - init.mBubbles = true; - - // XXX: Do we need to flush layout? - presShell->FlushPendingNotifications(Flush_Layout); - nsRect rect = nsLayoutUtils::GetSelectionBoundingRect(sel); - RefPtrdomRect = new dom::DOMRect(ToSupports(doc)); - - domRect->SetLayoutRect(rect); - init.mBoundingClientRect = domRect; - init.mVisible = false; - - sel->Stringify(init.mSelectedText); - - dom::Sequence state; - state.AppendElement(dom::SelectionState::Taponcaret, fallible); - init.mStates = state; - - RefPtr event = - dom::SelectionStateChangedEvent::Constructor(doc, NS_LITERAL_STRING("mozselectionstatechanged"), init); - - event->SetTrusted(true); - event->GetInternalNSEvent()->mFlags.mOnlyChromeDispatch = true; - bool ret; - doc->DispatchEvent(event, &ret); -} - -void -TouchCaret::SetState(TouchCaretState aState) -{ - TOUCHCARET_LOG("state changed from %d to %d", mState, aState); - if (mState == TOUCHCARET_NONE) { - MOZ_ASSERT(aState != TOUCHCARET_TOUCHDRAG_INACTIVE, - "mState: NONE => TOUCHDRAG_INACTIVE isn't allowed!"); - } - - if (mState == TOUCHCARET_TOUCHDRAG_ACTIVE) { - MOZ_ASSERT(aState != TOUCHCARET_MOUSEDRAG_ACTIVE, - "mState: TOUCHDRAG_ACTIVE => MOUSEDRAG_ACTIVE isn't allowed!"); - } - - if (mState == TOUCHCARET_MOUSEDRAG_ACTIVE) { - MOZ_ASSERT(aState == TOUCHCARET_MOUSEDRAG_ACTIVE || - aState == TOUCHCARET_NONE, - "MOUSEDRAG_ACTIVE allowed next state: NONE!"); - } - - if (mState == TOUCHCARET_TOUCHDRAG_INACTIVE) { - MOZ_ASSERT(aState == TOUCHCARET_TOUCHDRAG_INACTIVE || - aState == TOUCHCARET_NONE, - "TOUCHDRAG_INACTIVE allowed next state: NONE!"); - } - - mState = aState; - - if (mState == TOUCHCARET_NONE) { - mActiveTouchId = -1; - mCaretCenterToDownPointOffsetY = 0; - if (mIsValidTap) { - DispatchTapEvent(); - mIsValidTap = false; - } - } else if (mState == TOUCHCARET_TOUCHDRAG_ACTIVE || - mState == TOUCHCARET_MOUSEDRAG_ACTIVE) { - mIsValidTap = true; - } -} diff --git a/layout/base/TouchCaret.h b/layout/base/TouchCaret.h deleted file mode 100644 index 4d1915d81b68..000000000000 --- a/layout/base/TouchCaret.h +++ /dev/null @@ -1,321 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=2 sw=2 et tw=78: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef mozilla_TouchCaret_h__ -#define mozilla_TouchCaret_h__ - -#include "nsISelectionListener.h" -#include "nsIScrollObserver.h" -#include "nsIWeakReferenceUtils.h" -#include "nsITimer.h" -#include "mozilla/EventForwards.h" -#include "mozilla/TouchEvents.h" -#include "Units.h" - -class nsCanvasFrame; -class nsIFrame; -class nsIPresShell; - -namespace mozilla { - -/** - * NOTE: TouchCaret was obsoleted by AccessibleCaret, and is no longer used on - * B2G. This file is going to be removed in bug 1221459. Please see the wiki - * page for more information. https://wiki.mozilla.org/Copy_n_Paste - * - * The TouchCaret places a touch caret according to caret position when the - * caret is shown. - * TouchCaret is also responsible for touch caret visibility. Touch caret - * won't be shown when timer expires or while key event causes selection change. - */ -class TouchCaret final : public nsISelectionListener, - public nsIScrollObserver, - public nsSupportsWeakReference -{ -public: - explicit TouchCaret(nsIPresShell* aPresShell); - - NS_DECL_ISUPPORTS - NS_DECL_NSISELECTIONLISTENER - - void Init(); - void Terminate(); - - // nsIScrollObserver - virtual void ScrollPositionChanged() override; - - // AsyncPanZoom started/stopped callbacks from nsIScrollObserver - virtual void AsyncPanZoomStarted() override; - virtual void AsyncPanZoomStopped() override; - - /** - * Handle mouse and touch event only. - * Depends on visibility and position of touch caret, HandleEvent may consume - * that input event and return nsEventStatus_eConsumeNoDefault to the caller. - * In that case, caller should stop bubble up that input event. - */ - nsEventStatus HandleEvent(WidgetEvent* aEvent); - - void SyncVisibilityWithCaret(); - - void UpdatePositionIfNeeded(); - - /** - * GetVisibility will get the visibility of the touch caret. - */ - bool GetVisibility() const - { - return mVisible; - } - - /** - * Open or close the Android TextSelection ActionBar based on visibility. - */ - static void UpdateAndroidActionBarVisibility(bool aVisibility, uint32_t& aViewID); - -private: - // Hide default constructor. - TouchCaret() = delete; - - ~TouchCaret(); - - bool IsDisplayable(); - - void UpdatePosition(); - - /** - * SetVisibility will set the visibility of the touch caret. - * SetVisibility performs an attribute-changed notification which could, in - * theory, destroy frames. - */ - void SetVisibility(bool aVisible); - - /** - * Helper function to get caret's focus frame and caret's bounding rect. - */ - nsIFrame* GetCaretFocusFrame(nsRect* aOutRect = nullptr); - - /** - * Find the nsCanvasFrame which holds the touch caret. - */ - nsCanvasFrame* GetCanvasFrame(); - - /** - * Find the root frame to update the touch caret's position. - */ - nsIFrame* GetRootFrame(); - - /** - * Retrieve the bounding rectangle of the touch caret. - * - * @returns A nsRect representing the bounding rectangle of this touch caret. - * The returned offset is relative to the canvas frame. - */ - nsRect GetTouchFrameRect(); - - /** - * Retrieve the bounding rectangle where the caret can be positioned. - * If we're positioning a caret in an input field, make sure the touch caret - * stays within the bounds of the field. - * - * @returns A nsRect representing the bounding rectangle of this valid area. - * The returned offset is relative to the canvas frame. - */ - nsRect GetContentBoundary(); - - /** - * Retrieve the center y position of the caret. - * The returned point is relative to the canvas frame. - */ - nscoord GetCaretYCenterPosition(); - - /** - * Retrieve the rect of the touch caret. - * The returned rect is relative to the canvas frame. - */ - nsRect GetTouchCaretRect(); - - /** - * Clamp the position of the touch caret to the scroll frame boundary. - * The returned rect is relative to the canvas frame. - */ - nsRect ClampRectToScrollFrame(const nsRect& aRect); - - /** - * Set the position of the touch caret. - * Touch caret is an absolute positioned div. - */ - void SetTouchFramePos(const nsRect& aRect); - - void LaunchExpirationTimer(); - void CancelExpirationTimer(); - static void DisableTouchCaretCallback(nsITimer* aTimer, void* aPresShell); - - /** - * Move the caret to movePoint which is relative to the canvas frame. - * Caret will be scrolled into view. - * - * @param movePoint tap location relative to the canvas frame. - */ - void MoveCaret(const nsPoint& movePoint); - - /** - * Check if aPoint is inside the touch caret frame. - * - * @param aPoint tap location relative to the canvas frame. - */ - bool IsOnTouchCaret(const nsPoint& aPoint); - - /** - * These Handle* functions comprise input alphabet of the TouchCaret - * finite-state machine triggering state transitions. - */ - nsEventStatus HandleMouseMoveEvent(WidgetMouseEvent* aEvent); - nsEventStatus HandleMouseUpEvent(WidgetMouseEvent* aEvent); - nsEventStatus HandleMouseDownEvent(WidgetMouseEvent* aEvent); - nsEventStatus HandleTouchMoveEvent(WidgetTouchEvent* aEvent); - nsEventStatus HandleTouchUpEvent(WidgetTouchEvent* aEvent); - nsEventStatus HandleTouchDownEvent(WidgetTouchEvent* aEvent); - - /** - * Get the coordinates of a given touch event, relative to canvas frame. - * @param aEvent the event - * @param aIdentifier the mIdentifier of the touch which is to be converted. - * @return the point, or (NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE) if - * for some reason the coordinates for the touch are not known (e.g., - * the mIdentifier touch is not found). - */ - nsPoint GetEventPosition(WidgetTouchEvent* aEvent, int32_t aIdentifier); - - /** - * Set mouse down state in nsFrameSelection, we'll set state to true when - * user start dragging caret and set state to false when user release the - * caret. The reason for setting this state is it will fire drag reason - * when moving caret and fire mouseup reason when releasing caret. So that - * the display behavior of copy/paste menu becomes more reasonable. - */ - void SetSelectionDragState(bool aState); - - /** - * Get the coordinates of a given mouse event, relative to canvas frame. - * @param aEvent the event - * @return the point, or (NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE) if - * for some reason the coordinates for the mouse are not known. - */ - nsPoint GetEventPosition(WidgetMouseEvent* aEvent); - - /** - * States of TouchCaret finite-state machine. - */ - enum TouchCaretState { - // In this state, either there is no touch/mouse event going on, or the - // first stroke does not hit the touch caret. - // Will enter TOUCHCARET_TOUCHDRAG_ACTIVE state if the first touch stroke - // hits the touch caret. Will enter TOUCHCARET_MOUSEDRAG_ACTIVE state if - // mouse (left button) down hits the touch caret. - // Allowed next state: TOUCHCARET_MOUSEDRAG_ACTIVE, - // TOUCHCARET_TOUCHDRAG_ACTIVE. - TOUCHCARET_NONE, - // The first (left button) mouse down hits on the touch caret and is - // alive. Will enter TOUCHCARET_NONE state if the left button is release. - // Allowed next states: TOUCHCARET_NONE. - TOUCHCARET_MOUSEDRAG_ACTIVE, - // The first touch start event hits on touch caret and is alive. - // Will enter TOUCHCARET_NONE state if the finger on touch caret is - // removed and there are no more fingers on the screen; will enter - // TOUCHCARET_TOUCHDRAG_INACTIVE state if the finger on touch caret is - // removed but still has fingers touching on the screen. - // Allowed next states: TOUCHCARET_NONE, TOUCHCARET_TOUCHDRAG_INACTIVE. - TOUCHCARET_TOUCHDRAG_ACTIVE, - // The first touch stroke, which hit on touch caret, is dead, but still has - // fingers touching on the screen. - // Will enter TOUCHCARET_NONE state if all the fingers are removed from the - // screen. - // Allowed next state: TOUCHCARET_NONE. - TOUCHCARET_TOUCHDRAG_INACTIVE, - }; - - /** - * Do actual state transition and reset substates. - */ - void SetState(TouchCaretState aState); - - /** - * Dispatch touch caret tap event to chrome. - */ - void DispatchTapEvent(); - - /** - * Current state we're dealing with. - */ - TouchCaretState mState; - - /** - * Array containing all active touch IDs. When a touch happens, it gets added - * to this array, even if we choose not to handle it. When it ends, we remove - * it. We need to maintain this array in order to detect the end of the - * "multitouch" states because touch start events contain all current touches, - * but touch end events contain only those touches that have gone. - */ - nsTArray mTouchesId; - - /** - * The mIdentifier of the touch which is on the touch caret. - */ - int32_t mActiveTouchId; - - /** - * The offset between the tap location and the center of caret along y axis. - */ - nscoord mCaretCenterToDownPointOffsetY; - - /** - * Get from pref "touchcaret.inflatesize.threshold". This will inflate the - * size of the touch caret frame when checking if user clicks on the caret - * or not. In app units. - */ - static int32_t TouchCaretInflateSize() { return sTouchCaretInflateSize; } - - static int32_t TouchCaretExpirationTime() - { - return sTouchCaretExpirationTime; - } - - void LaunchScrollEndDetector(); - void CancelScrollEndDetector(); - static void FireScrollEnd(nsITimer* aTimer, void* aSelectionCarets); - - // This timer is used for detecting scroll end. We don't have - // scroll end event now, so we will fire this event with a - // const time when we scroll. So when timer triggers, we treat it - // as scroll end event. - nsCOMPtr mScrollEndDetectorTimer; - - nsWeakPtr mPresShell; - WeakPtr mDocShell; - - // True if AsyncPanZoom is started - bool mInAsyncPanZoomGesture; - - // Touch caret visibility - bool mVisible; - // Use for detecting single tap on touch caret. - bool mIsValidTap; - // Touch caret timer - nsCOMPtr mTouchCaretExpirationTimer; - - // Preference - static int32_t sTouchCaretInflateSize; - static int32_t sTouchCaretExpirationTime; - - // The auto scroll timer's interval in miliseconds. - friend class SelectionCarets; - static const int32_t sAutoScrollTimerDelay = 30; - // Time for trigger scroll end event, in miliseconds. - static const int32_t sScrollEndTimerDelay = 300; -}; -} //namespace mozilla -#endif //mozilla_TouchCaret_h__ diff --git a/layout/base/TouchManager.cpp b/layout/base/TouchManager.cpp index fe90d3f15e8a..b9ce753332d2 100644 --- a/layout/base/TouchManager.cpp +++ b/layout/base/TouchManager.cpp @@ -6,7 +6,16 @@ */ #include "TouchManager.h" + +#include "mozilla/TouchEvents.h" +#include "mozilla/dom/EventTarget.h" +#include "nsIFrame.h" #include "nsPresShell.h" +#include "nsView.h" + +namespace mozilla { + +using EventTarget = ::mozilla::dom::EventTarget; nsRefPtrHashtable* TouchManager::gCaptureTouchList; @@ -222,3 +231,5 @@ TouchManager::PreHandleEvent(WidgetEvent* aEvent, } return true; } + +} // namespace mozilla diff --git a/layout/base/TouchManager.h b/layout/base/TouchManager.h index 43731542e004..5bab34cb1a33 100644 --- a/layout/base/TouchManager.h +++ b/layout/base/TouchManager.h @@ -15,6 +15,8 @@ class PresShell; class nsIDocument; +namespace mozilla { + class TouchManager { public: // Initialize and release static variables @@ -39,4 +41,6 @@ private: nsCOMPtr mDocument; }; +} // namespace mozilla + #endif /* !defined(TouchManager_h_) */ diff --git a/layout/base/ZoomConstraintsClient.cpp b/layout/base/ZoomConstraintsClient.cpp index cd33e3d31dd5..9e6e9c1fd8e7 100644 --- a/layout/base/ZoomConstraintsClient.cpp +++ b/layout/base/ZoomConstraintsClient.cpp @@ -7,8 +7,10 @@ #include #include "FrameMetrics.h" +#include "gfxPrefs.h" #include "LayersLogging.h" #include "mozilla/layers/APZCCallbackHelper.h" +#include "mozilla/Preferences.h" #include "nsDocument.h" #include "nsIFrame.h" #include "nsLayoutUtils.h" diff --git a/layout/base/moz.build b/layout/base/moz.build index bdcbebe4022e..34842b8de7ee 100644 --- a/layout/base/moz.build +++ b/layout/base/moz.build @@ -40,9 +40,8 @@ with Files('nsChangeHint.h'): with Files('nsBidi*'): BUG_COMPONENT = ('Core', 'Layout: Text') -for caret_file in ('AccessibleCaret*', 'TouchCaret*', 'SelectionCarets*'): - with Files(caret_file): - BUG_COMPONENT = ('Core', 'Selection') +with Files('AccessibleCaret*'): + BUG_COMPONENT = ('Core', 'Selection') XPIDL_SOURCES += [ 'nsIStyleSheetService.idl', @@ -147,9 +146,7 @@ UNIFIED_SOURCES += [ 'RestyleManager.cpp', 'RestyleTracker.cpp', 'ScrollbarStyles.cpp', - 'SelectionCarets.cpp', 'StackArena.cpp', - 'TouchCaret.cpp', 'TouchManager.cpp', 'ZoomConstraintsClient.cpp', ] diff --git a/layout/base/nsIPresShell.h b/layout/base/nsIPresShell.h index 4bf20043b3f6..ce77c1af3426 100644 --- a/layout/base/nsIPresShell.h +++ b/layout/base/nsIPresShell.h @@ -63,8 +63,6 @@ class nsCaret; namespace mozilla { class AccessibleCaretEventHub; class CSSStyleSheet; -class TouchCaret; -class SelectionCarets; } // namespace mozilla class nsFrameSelection; class nsFrameManager; @@ -807,31 +805,6 @@ public: */ virtual void NotifyDestroyingFrame(nsIFrame* aFrame) = 0; - /** - * Get the touch caret, if it exists. AddRefs it. - */ - virtual already_AddRefed GetTouchCaret() const = 0; - - /** - * Returns the touch caret element of the presshell. - */ - virtual mozilla::dom::Element* GetTouchCaretElement() const = 0; - - /** - * Get the selection caret, if it exists. AddRefs it. - */ - virtual already_AddRefed GetSelectionCarets() const = 0; - - /** - * Returns the start part of selection caret element of the presshell. - */ - virtual mozilla::dom::Element* GetSelectionCaretsStartElement() const = 0; - - /** - * Returns the end part of selection caret element of the presshell. - */ - virtual mozilla::dom::Element* GetSelectionCaretsEndElement() const = 0; - /** * Get the AccessibleCaretEventHub, if it exists. AddRefs it. */ diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index 6bb8e81fa100..e470a0191b26 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -78,8 +78,6 @@ #include "nsIMozBrowserFrame.h" #include "nsCaret.h" #include "AccessibleCaretEventHub.h" -#include "TouchCaret.h" -#include "SelectionCarets.h" #include "nsIDOMHTMLDocument.h" #include "nsFrameManager.h" #include "nsXPCOM.h" @@ -705,33 +703,9 @@ nsIPresShell::FrameSelection() static bool sSynthMouseMove = true; static uint32_t sNextPresShellId; static bool sPointerEventEnabled = true; -static bool sTouchCaretEnabled = false; -static bool sSelectionCaretEnabled = false; static bool sAccessibleCaretEnabled = false; static bool sBeforeAfterKeyboardEventEnabled = false; -/* static */ bool -PresShell::TouchCaretPrefEnabled() -{ - static bool initialized = false; - if (!initialized) { - Preferences::AddBoolVarCache(&sTouchCaretEnabled, "touchcaret.enabled"); - initialized = true; - } - return sTouchCaretEnabled; -} - -/* static */ bool -PresShell::SelectionCaretPrefEnabled() -{ - static bool initialized = false; - if (!initialized) { - Preferences::AddBoolVarCache(&sSelectionCaretEnabled, "selectioncaret.enabled"); - initialized = true; - } - return sSelectionCaretEnabled; -} - /* static */ bool PresShell::AccessibleCaretEnabled() { @@ -882,18 +856,6 @@ PresShell::Init(nsIDocument* aDocument, // Add the preference style sheet. UpdatePreferenceStyles(); - if (TouchCaretPrefEnabled() && !AccessibleCaretEnabled()) { - // Create touch caret handle - mTouchCaret = new TouchCaret(this); - mTouchCaret->Init(); - } - - if (SelectionCaretPrefEnabled() && !AccessibleCaretEnabled()) { - // Create selection caret handle - mSelectionCarets = new SelectionCarets(this); - mSelectionCarets->Init(); - } - if (AccessibleCaretEnabled()) { // Need to happen before nsFrameSelection has been set up. mAccessibleCaretEventHub = new AccessibleCaretEventHub(this); @@ -1195,16 +1157,6 @@ PresShell::Destroy() mSelection->DisconnectFromPresShell(); } - if (mTouchCaret) { - mTouchCaret->Terminate(); - mTouchCaret = nullptr; - } - - if (mSelectionCarets) { - mSelectionCarets->Terminate(); - mSelectionCarets = nullptr; - } - if (mAccessibleCaretEventHub) { mAccessibleCaretEventHub->Terminate(); mAccessibleCaretEventHub = nullptr; @@ -1991,19 +1943,6 @@ already_AddRefed PresShell::GetCaret() const return caret.forget(); } -// TouchCaret -already_AddRefed PresShell::GetTouchCaret() const -{ - RefPtr touchCaret = mTouchCaret; - return touchCaret.forget(); -} - -already_AddRefed PresShell::GetSelectionCarets() const -{ - RefPtr selectionCaret = mSelectionCarets; - return selectionCaret.forget(); -} - already_AddRefed PresShell::GetAccessibleCaretEventHub() const { RefPtr eventHub = mAccessibleCaretEventHub; @@ -2034,12 +1973,6 @@ NS_IMETHODIMP PresShell::SetCaretEnabled(bool aInEnable) } } - // We should sync touch caret's visibility with caret every time since touch - // caret might be hidden due to timeout while caret is enabled. - if (mTouchCaret) { - mTouchCaret->SyncVisibilityWithCaret(); - } - return NS_OK; } @@ -2370,24 +2303,6 @@ PresShell::GetCanvasFrame() const return do_QueryFrame(frame); } -Element* -PresShell::GetTouchCaretElement() const -{ - return GetCanvasFrame() ? GetCanvasFrame()->GetTouchCaretElement() : nullptr; -} - -Element* -PresShell::GetSelectionCaretsStartElement() const -{ - return GetCanvasFrame() ? GetCanvasFrame()->GetSelectionCaretsStartElement() : nullptr; -} - -Element* -PresShell::GetSelectionCaretsEndElement() const -{ - return GetCanvasFrame() ? GetCanvasFrame()->GetSelectionCaretsEndElement() : nullptr; -} - void PresShell::BeginUpdate(nsIDocument *aDocument, nsUpdateType aUpdateType) { @@ -3786,10 +3701,6 @@ PresShell::UnsuppressAndInvalidate() if (rootFrame) { // let's assume that outline on a root frame is not supported rootFrame->InvalidateFrame(); - - if (mTouchCaret) { - mTouchCaret->SyncVisibilityWithCaret(); - } } // now that painting is unsuppressed, focus may be set on the document @@ -6980,47 +6891,6 @@ PresShell::HandleEvent(nsIFrame* aFrame, RecordMouseLocation(aEvent); - // Determine whether event need to be consumed by touch caret or not. - if (TouchCaretPrefEnabled() || SelectionCaretPrefEnabled()) { - // We have to target the focus window because regardless of where the - // touch goes, we want to access the touch caret when user is typing on an - // editable element. - nsCOMPtr window = GetFocusedDOMWindowInOurWindow(); - nsCOMPtr retargetEventDoc = window ? window->GetExtantDoc() : nullptr; - nsCOMPtr presShell = retargetEventDoc ? - retargetEventDoc->GetShell() : - nullptr; - - // Bug 1057256: Touch caret should handle the event before selection carets. - // Otherwise, a long tap on touch caret will be incorrectly handled by - // selection carets which makes moving touch caret failed. - RefPtr touchCaret = presShell ? - presShell->GetTouchCaret() : - nullptr; - if (touchCaret) { - *aEventStatus = touchCaret->HandleEvent(aEvent); - if (*aEventStatus == nsEventStatus_eConsumeNoDefault) { - // If the event is consumed by the touch caret, cancel APZC panning by - // setting mMultipleActionsPrevented. - aEvent->mFlags.mMultipleActionsPrevented = true; - return NS_OK; - } - } - - RefPtr selectionCaret = presShell ? - presShell->GetSelectionCarets() : - nullptr; - if (selectionCaret) { - *aEventStatus = selectionCaret->HandleEvent(aEvent); - if (*aEventStatus == nsEventStatus_eConsumeNoDefault) { - // If the event is consumed by the selection carets, cancel APZC panning by - // setting mMultipleActionsPrevented. - aEvent->mFlags.mMultipleActionsPrevented = true; - return NS_OK; - } - } - } - if (AccessibleCaretEnabled()) { // We have to target the focus window because regardless of where the // touch goes, we want to access the copy paste manager. @@ -8841,10 +8711,6 @@ PresShell::DidDoReflow(bool aInterruptible) SynthesizeMouseMove(false); } - if (mTouchCaret) { - mTouchCaret->UpdatePositionIfNeeded(); - } - mPresContext->NotifyMissingFonts(); } diff --git a/layout/base/nsPresShell.h b/layout/base/nsPresShell.h index 5479bd504b16..1e7b0470f392 100644 --- a/layout/base/nsPresShell.h +++ b/layout/base/nsPresShell.h @@ -73,12 +73,6 @@ public: // nsISupports NS_DECL_ISUPPORTS - // Touch caret preference - static bool TouchCaretPrefEnabled(); - - // Selection caret preference - static bool SelectionCaretPrefEnabled(); - static bool AccessibleCaretEnabled(); // BeforeAfterKeyboardEvent preference @@ -246,14 +240,6 @@ public: virtual void ClearMouseCaptureOnView(nsView* aView) override; virtual bool IsVisible() override; - // touch caret - virtual already_AddRefed GetTouchCaret() const override; - virtual mozilla::dom::Element* GetTouchCaretElement() const override; - // selection caret - virtual already_AddRefed GetSelectionCarets() const override; - virtual mozilla::dom::Element* GetSelectionCaretsStartElement() const override; - virtual mozilla::dom::Element* GetSelectionCaretsEndElement() const override; - virtual already_AddRefed GetAccessibleCaretEventHub() const override; // caret handling @@ -816,15 +802,11 @@ protected: nsCallbackEventRequest* mFirstCallbackEventRequest; nsCallbackEventRequest* mLastCallbackEventRequest; - // TouchManager - TouchManager mTouchManager; + mozilla::TouchManager mTouchManager; RefPtr mZoomConstraintsClient; RefPtr mMobileViewportManager; - // TouchCaret - RefPtr mTouchCaret; - RefPtr mSelectionCarets; RefPtr mAccessibleCaretEventHub; // This timer controls painting suppression. Until it fires diff --git a/layout/generic/nsCanvasFrame.cpp b/layout/generic/nsCanvasFrame.cpp index 344a305a2a56..1180c860ee3e 100644 --- a/layout/generic/nsCanvasFrame.cpp +++ b/layout/generic/nsCanvasFrame.cpp @@ -23,11 +23,6 @@ #include "gfxPlatform.h" #include "nsPrintfCString.h" #include "mozilla/dom/AnonymousContent.h" -// for touchcaret -#include "nsContentList.h" -#include "nsContentCreatorFunctions.h" -#include "nsContentUtils.h" -#include "nsStyleSet.h" // for focus #include "nsIScrollableFrame.h" #ifdef DEBUG_CANVAS_FOCUS @@ -54,8 +49,6 @@ NS_QUERYFRAME_HEAD(nsCanvasFrame) NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator) NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame) -NS_IMPL_ISUPPORTS(nsCanvasFrame::DummyTouchListener, nsIDOMEventListener) - void nsCanvasFrame::ShowCustomContentContainer() { @@ -83,66 +76,6 @@ nsCanvasFrame::CreateAnonymousContent(nsTArray& aElements) nsCOMPtr doc = mContent->OwnerDoc(); nsresult rv = NS_OK; - ErrorResult er; - // We won't create touch caret element if preference is not enabled. - if (PresShell::TouchCaretPrefEnabled()) { - RefPtr nodeInfo; - - // Create and append touch caret frame. - nodeInfo = doc->NodeInfoManager()->GetNodeInfo(nsGkAtoms::div, nullptr, - kNameSpaceID_XHTML, - nsIDOMNode::ELEMENT_NODE); - NS_ENSURE_TRUE(nodeInfo, NS_ERROR_OUT_OF_MEMORY); - - rv = NS_NewHTMLElement(getter_AddRefs(mTouchCaretElement), nodeInfo.forget(), - NOT_FROM_PARSER); - NS_ENSURE_SUCCESS(rv, rv); - aElements.AppendElement(mTouchCaretElement); - - // Set touch caret to visibility: hidden by default. - nsAutoString classValue; - classValue.AppendLiteral("moz-touchcaret hidden"); - rv = mTouchCaretElement->SetAttr(kNameSpaceID_None, nsGkAtoms::_class, - classValue, true); - - if (!mDummyTouchListener) { - mDummyTouchListener = new DummyTouchListener(); - } - mTouchCaretElement->AddEventListener(NS_LITERAL_STRING("touchstart"), - mDummyTouchListener, false); - NS_ENSURE_SUCCESS(rv, rv); - } - - if (PresShell::SelectionCaretPrefEnabled()) { - // Selection caret - mSelectionCaretsStartElement = doc->CreateHTMLElement(nsGkAtoms::div); - aElements.AppendElement(mSelectionCaretsStartElement); - nsCOMPtr selectionCaretsStartElementInner = doc->CreateHTMLElement(nsGkAtoms::div); - mSelectionCaretsStartElement->AppendChildTo(selectionCaretsStartElementInner, false); - - mSelectionCaretsEndElement = doc->CreateHTMLElement(nsGkAtoms::div); - aElements.AppendElement(mSelectionCaretsEndElement); - nsCOMPtr selectionCaretsEndElementInner = doc->CreateHTMLElement(nsGkAtoms::div); - mSelectionCaretsEndElement->AppendChildTo(selectionCaretsEndElementInner, false); - - rv = mSelectionCaretsStartElement->SetAttr(kNameSpaceID_None, nsGkAtoms::_class, - NS_LITERAL_STRING("moz-selectioncaret-left hidden"), - true); - NS_ENSURE_SUCCESS(rv, rv); - - rv = mSelectionCaretsEndElement->SetAttr(kNameSpaceID_None, nsGkAtoms::_class, - NS_LITERAL_STRING("moz-selectioncaret-right hidden"), - true); - - if (!mDummyTouchListener) { - mDummyTouchListener = new DummyTouchListener(); - } - mSelectionCaretsStartElement->AddEventListener(NS_LITERAL_STRING("touchstart"), - mDummyTouchListener, false); - mSelectionCaretsEndElement->AddEventListener(NS_LITERAL_STRING("touchstart"), - mDummyTouchListener, false); - NS_ENSURE_SUCCESS(rv, rv); - } // Create the custom content container. mCustomContentContainer = doc->CreateHTMLElement(nsGkAtoms::div); @@ -188,18 +121,6 @@ nsCanvasFrame::CreateAnonymousContent(nsTArray& aElements) void nsCanvasFrame::AppendAnonymousContentTo(nsTArray& aElements, uint32_t aFilter) { - if (mTouchCaretElement) { - aElements.AppendElement(mTouchCaretElement); - } - - if (mSelectionCaretsStartElement) { - aElements.AppendElement(mSelectionCaretsStartElement); - } - - if (mSelectionCaretsEndElement) { - aElements.AppendElement(mSelectionCaretsEndElement); - } - aElements.AppendElement(mCustomContentContainer); } @@ -212,25 +133,6 @@ nsCanvasFrame::DestroyFrom(nsIFrame* aDestructRoot) sf->RemoveScrollPositionListener(this); } - if (mTouchCaretElement) { - mTouchCaretElement->RemoveEventListener(NS_LITERAL_STRING("touchstart"), - mDummyTouchListener, false); - } - - if (mSelectionCaretsStartElement) { - mSelectionCaretsStartElement->RemoveEventListener(NS_LITERAL_STRING("touchstart"), - mDummyTouchListener, false); - } - - if (mSelectionCaretsEndElement) { - mSelectionCaretsEndElement->RemoveEventListener(NS_LITERAL_STRING("touchstart"), - mDummyTouchListener, false); - } - - nsContentUtils::DestroyAnonymousContent(&mTouchCaretElement); - nsContentUtils::DestroyAnonymousContent(&mSelectionCaretsStartElement); - nsContentUtils::DestroyAnonymousContent(&mSelectionCaretsEndElement); - // Elements inserted in the custom content container have the same lifetime as // the document, so before destroying the container, make sure to keep a clone // of each of them at document level so they can be re-appended on reframe. @@ -297,8 +199,8 @@ nsCanvasFrame::AppendFrames(ChildListID aListID, MOZ_ASSERT(aListID == kPrincipalList, "unexpected child list"); if (!mFrames.IsEmpty()) { for (nsFrameList::Enumerator e(aFrameList); !e.AtEnd(); e.Next()) { - // We only allow native anonymous child frame for touch caret, - // which its placeholder is added to the Principal child lists. + // We only allow native anonymous child frames to be in principal child + // list in canvas frame. MOZ_ASSERT(e.get()->GetContent()->IsInNativeAnonymousSubtree(), "invalid child list"); } @@ -527,15 +429,6 @@ nsCanvasFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, nsIFrame* kid; for (kid = GetFirstPrincipalChild(); kid; kid = kid->GetNextSibling()) { - // Skip touch/selection caret frame if we do not build caret. - if (!aBuilder->IsBuildingCaret()) { - if(kid->GetContent() == mTouchCaretElement || - kid->GetContent() == mSelectionCaretsStartElement|| - kid->GetContent() == mSelectionCaretsEndElement) { - continue; - } - } - // Put our child into its own pseudo-stack. BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aLists); } diff --git a/layout/generic/nsCanvasFrame.h b/layout/generic/nsCanvasFrame.h index 4381755a56cc..062a8394bfae 100644 --- a/layout/generic/nsCanvasFrame.h +++ b/layout/generic/nsCanvasFrame.h @@ -14,7 +14,6 @@ #include "nsIScrollPositionListener.h" #include "nsDisplayList.h" #include "nsIAnonymousContentCreator.h" -#include "nsIDOMEventListener.h" class nsPresContext; class nsRenderingContext; @@ -83,23 +82,6 @@ public: virtual nsresult CreateAnonymousContent(nsTArray& aElements) override; virtual void AppendAnonymousContentTo(nsTArray& aElements, uint32_t aFilter) override; - // Touch caret handle function - mozilla::dom::Element* GetTouchCaretElement() const - { - return mTouchCaretElement; - } - - // Selection Caret Handle function - mozilla::dom::Element* GetSelectionCaretsStartElement() const - { - return mSelectionCaretsStartElement; - } - - mozilla::dom::Element* GetSelectionCaretsEndElement() const - { - return mSelectionCaretsEndElement; - } - mozilla::dom::Element* GetCustomContentContainer() const { return mCustomContentContainer; @@ -165,28 +147,7 @@ protected: bool mDoPaintFocus; bool mAddedScrollPositionListener; - nsCOMPtr mTouchCaretElement; - nsCOMPtr mSelectionCaretsStartElement; - nsCOMPtr mSelectionCaretsEndElement; nsCOMPtr mCustomContentContainer; - - class DummyTouchListener final : public nsIDOMEventListener - { - public: - NS_DECL_ISUPPORTS - - NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent) override - { - return NS_OK; - } - private: - ~DummyTouchListener() {} - }; - - /** - * A no-op touch-listener used for APZ purposes. - */ - RefPtr mDummyTouchListener; }; /** diff --git a/layout/generic/nsSelection.cpp b/layout/generic/nsSelection.cpp index ad78d5475e5c..80962fb7aaf2 100644 --- a/layout/generic/nsSelection.cpp +++ b/layout/generic/nsSelection.cpp @@ -51,9 +51,6 @@ static NS_DEFINE_CID(kFrameTraversalCID, NS_FRAMETRAVERSAL_CID); #include "nsPresContext.h" #include "nsIPresShell.h" #include "nsCaret.h" -#include "TouchCaret.h" -#include "SelectionCarets.h" - #include "AccessibleCaretEventHub.h" #include "mozilla/MouseEvents.h" @@ -823,24 +820,6 @@ nsFrameSelection::Init(nsIPresShell *aShell, nsIContent *aLimiter) "dom.select_events.enabled", false); } - // Set touch caret as selection listener - RefPtr touchCaret = mShell->GetTouchCaret(); - if (touchCaret) { - int8_t index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL); - if (mDomSelections[index]) { - mDomSelections[index]->AddSelectionListener(touchCaret); - } - } - - // Set selection caret as selection listener - RefPtr selectionCarets = mShell->GetSelectionCarets(); - if (selectionCarets) { - int8_t index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL); - if (mDomSelections[index]) { - mDomSelections[index]->AddSelectionListener(selectionCarets); - } - } - RefPtr eventHub = mShell->GetAccessibleCaretEventHub(); if (eventHub) { int8_t index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL); @@ -3290,19 +3269,6 @@ nsFrameSelection::SetDelayedCaretData(WidgetMouseEvent* aMouseEvent) void nsFrameSelection::DisconnectFromPresShell() { - // Remove touch caret as selection listener - RefPtr touchCaret = mShell->GetTouchCaret(); - if (touchCaret) { - int8_t index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL); - mDomSelections[index]->RemoveSelectionListener(touchCaret); - } - - RefPtr selectionCarets = mShell->GetSelectionCarets(); - if (selectionCarets) { - int8_t index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL); - mDomSelections[index]->RemoveSelectionListener(selectionCarets); - } - RefPtr eventHub = mShell->GetAccessibleCaretEventHub(); if (eventHub) { int8_t index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL); diff --git a/layout/style/ua.css b/layout/style/ua.css index 8eda88b11bdb..d91a1e1167df 100644 --- a/layout/style/ua.css +++ b/layout/style/ua.css @@ -417,114 +417,6 @@ div:-moz-native-anonymous.moz-accessiblecaret.none { } } -div:-moz-native-anonymous.moz-touchcaret, -div:-moz-native-anonymous.moz-selectioncaret-left, -div:-moz-native-anonymous.moz-selectioncaret-right { - position: fixed; - width: 44px; - height: 47px; -} - -div:-moz-native-anonymous.moz-selectioncaret-left > div, -div:-moz-native-anonymous.moz-selectioncaret-right > div { - position: absolute; - width: 100%; - height: 100%; - bottom: 0; -} - -div:-moz-native-anonymous.moz-touchcaret, -div:-moz-native-anonymous.moz-selectioncaret-left, -div:-moz-native-anonymous.moz-selectioncaret-right, -div:-moz-native-anonymous.moz-selectioncaret-left > div, -div:-moz-native-anonymous.moz-selectioncaret-right > div { - background-position: center bottom; - background-size: 100%; - background-repeat: no-repeat; - z-index: 2147483647; -} - -div:-moz-native-anonymous.moz-touchcaret, -div:-moz-native-anonymous.moz-selectioncaret-left > div, -div:-moz-native-anonymous.moz-selectioncaret-right > div { - background-image: url("resource://gre/res/text_caret.png"); -} - -div:-moz-native-anonymous.moz-touchcaret, -div:-moz-native-anonymous.moz-selectioncaret-left, -div:-moz-native-anonymous.moz-selectioncaret-right { - margin-left: -23px; -} - -div:-moz-native-anonymous.moz-selectioncaret-left.tilt > div { - background-image: url("resource://gre/res/text_caret_tilt_left.png"); - margin-left: -17px; -} - -div:-moz-native-anonymous.moz-selectioncaret-right.tilt > div { - background-image: url("resource://gre/res/text_caret_tilt_right.png"); - margin-left: 18px; -} - -@media (min-resolution: 1.5dppx) { - div:-moz-native-anonymous.moz-touchcaret, - div:-moz-native-anonymous.moz-selectioncaret-left > div, - div:-moz-native-anonymous.moz-selectioncaret-right > div { - background-image: url("resource://gre/res/text_caret@1.5x.png"); - } - - div:-moz-native-anonymous.moz-selectioncaret-left.tilt > div { - background-image: url("resource://gre/res/text_caret_tilt_left@1.5x.png"); - } - - div:-moz-native-anonymous.moz-selectioncaret-right.tilt > div { - background-image: url("resource://gre/res/text_caret_tilt_right@1.5x.png"); - } -} - -@media (min-resolution: 2dppx) { - div:-moz-native-anonymous.moz-touchcaret, - div:-moz-native-anonymous.moz-selectioncaret-left > div, - div:-moz-native-anonymous.moz-selectioncaret-right > div { - background-image: url("resource://gre/res/text_caret@2x.png"); - } - - div:-moz-native-anonymous.moz-selectioncaret-left.tilt > div { - background-image: url("resource://gre/res/text_caret_tilt_left@2x.png"); - } - - div:-moz-native-anonymous.moz-selectioncaret-right.tilt > div { - background-image: url("resource://gre/res/text_caret_tilt_right@2x.png"); - } -} - -@media (min-resolution: 2.25dppx) { - div:-moz-native-anonymous.moz-touchcaret, - div:-moz-native-anonymous.moz-selectioncaret-left > div, - div:-moz-native-anonymous.moz-selectioncaret-right > div { - background-image: url("resource://gre/res/text_caret@2.25x.png"); - } - - div:-moz-native-anonymous.moz-selectioncaret-left.tilt > div { - background-image: url("resource://gre/res/text_caret_tilt_left@2.25x.png"); - } - - div:-moz-native-anonymous.moz-selectioncaret-right.tilt > div { - background-image: url("resource://gre/res/text_caret_tilt_right@2.25x.png"); - } -} - -div:-moz-native-anonymous.moz-touchcaret.hidden, -div:-moz-native-anonymous.moz-selectioncaret-left.hidden, -div:-moz-native-anonymous.moz-selectioncaret-right.hidden, -div:-moz-native-anonymous.moz-selectioncaret-left.hidden > div, -div:-moz-native-anonymous.moz-selectioncaret-right.hidden > div { - width: 0px; - height: 0px; - margin: 0px; - visibility: hidden; -} - /* Custom content container in the CanvasFrame, fixed positioned on top of everything else, not reacting to pointer events. */ div:-moz-native-anonymous.moz-custom-content-container { diff --git a/layout/tools/reftest/reftest-preferences.js b/layout/tools/reftest/reftest-preferences.js index 66e31fd25e4f..ecf2ab111fea 100644 --- a/layout/tools/reftest/reftest-preferences.js +++ b/layout/tools/reftest/reftest-preferences.js @@ -51,9 +51,6 @@ // reflow so that that rare edge case doesn't lead to reftest // failures. branch.setBoolPref("layout.interruptible-reflow.enabled", false); - // Disable the auto-hide feature of touch caret to avoid potential - // intermittent issues. - branch.setIntPref("touchcaret.expiration.time", 0); // Tell the search service we are running in the US. This also has the // desired side-effect of preventing our geoip lookup. diff --git a/mobile/android/b2gdroid/installer/package-manifest.in b/mobile/android/b2gdroid/installer/package-manifest.in index 3b91dfe21189..becbfe2b1a9f 100644 --- a/mobile/android/b2gdroid/installer/package-manifest.in +++ b/mobile/android/b2gdroid/installer/package-manifest.in @@ -543,18 +543,18 @@ @BINPATH@/res/language.properties @BINPATH@/res/entityTables/* #ifdef NIGHTLY_BUILD -@BINPATH@/res/text_caret.png -@BINPATH@/res/text_caret@1.5x.png -@BINPATH@/res/text_caret@2.25x.png -@BINPATH@/res/text_caret@2x.png -@BINPATH@/res/text_caret_tilt_left.png -@BINPATH@/res/text_caret_tilt_left@1.5x.png -@BINPATH@/res/text_caret_tilt_left@2.25x.png -@BINPATH@/res/text_caret_tilt_left@2x.png -@BINPATH@/res/text_caret_tilt_right.png -@BINPATH@/res/text_caret_tilt_right@1.5x.png -@BINPATH@/res/text_caret_tilt_right@2.25x.png -@BINPATH@/res/text_caret_tilt_right@2x.png +@BINPATH@/res/accessiblecaret.png +@BINPATH@/res/accessiblecaret@1.5x.png +@BINPATH@/res/accessiblecaret@2.25x.png +@BINPATH@/res/accessiblecaret@2x.png +@BINPATH@/res/accessiblecaret_tilt_left.png +@BINPATH@/res/accessiblecaret_tilt_left@1.5x.png +@BINPATH@/res/accessiblecaret_tilt_left@2.25x.png +@BINPATH@/res/accessiblecaret_tilt_left@2x.png +@BINPATH@/res/accessiblecaret_tilt_right.png +@BINPATH@/res/accessiblecaret_tilt_right@1.5x.png +@BINPATH@/res/accessiblecaret_tilt_right@2.25x.png +@BINPATH@/res/accessiblecaret_tilt_right@2x.png #endif #ifndef MOZ_ANDROID_EXCLUDE_FONTS diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 56ef23022b84..36a63580e590 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -4856,25 +4856,6 @@ pref("browser.safebrowsing.allowOverride", true); // Turn off Spatial navigation by default. pref("snav.enabled", false); -// Original caret implementation on collapsed selection. -pref("touchcaret.enabled", false); - -// This will inflate the size of the touch caret frame when checking if user -// clicks on the caret or not. In app units. -pref("touchcaret.inflatesize.threshold", 40); - -// We'll start to increment time when user release the control of touch caret. -// When time exceed this expiration time, we'll hide touch caret. -// In milliseconds. (0 means disable this feature) -pref("touchcaret.expiration.time", 3000); - -// Original caret implementation on non-collapsed selection. -pref("selectioncaret.enabled", false); - -// This will inflate size of selection caret frame when we checking if -// user click on selection caret or not. In app units. -pref("selectioncaret.inflatesize.threshold", 40); - // New implementation to unify touch-caret and selection-carets. pref("layout.accessiblecaret.enabled", false); diff --git a/testing/profiles/prefs_b2g_unittest.js b/testing/profiles/prefs_b2g_unittest.js index d1885730fb89..1a8264a24763 100644 --- a/testing/profiles/prefs_b2g_unittest.js +++ b/testing/profiles/prefs_b2g_unittest.js @@ -9,4 +9,3 @@ user_pref("dom.mozBrowserFramesEnabled", "%(OOP)s"); user_pref("dom.mozBrowserFramesWhitelist","app://test-container.gaiamobile.org,http://mochi.test:8888"); user_pref("dom.testing.datastore_enabled_for_hosted_apps", true); user_pref("marionette.force-local", true); -user_pref("touchcaret.expiration.time", 0); From 010e08ad0b315bce344580dbb4500e41a46710a6 Mon Sep 17 00:00:00 2001 From: Ting-Yu Lin Date: Tue, 22 Dec 2015 14:14:12 +0800 Subject: [PATCH 05/94] Bug 1121459 - Remove TouchCaret and SelectionCarets prefs in test files. r=mtseng,roc For test_bug648573.html and test_bug644768.html, we no longer need to create an iframe to turn off the preferences. I move the content of iframe.src back to the test files. --HG-- extra : rebase_source : 5cf321bf3280e032cc6645810e3e7faa7a6ff615 --- dom/events/test/bug648573.html | 106 ---------------- dom/events/test/mochitest.ini | 1 - dom/events/test/test_bug648573.html | 117 +++++++++++++++--- dom/events/test/test_clickevent_on_input.html | 7 +- editor/reftests/reftest.list | 18 +-- layout/base/tests/bug644768.html | 58 --------- layout/base/tests/mochitest.ini | 3 - layout/base/tests/test_bug1070851.html | 59 --------- layout/base/tests/test_bug558663.html | 5 +- layout/base/tests/test_bug644768.html | 70 ++++++++--- .../base/tests/test_reftests_with_caret.html | 16 +-- .../tests/test_touchcaret_visibility.html | 97 --------------- 12 files changed, 168 insertions(+), 389 deletions(-) delete mode 100644 dom/events/test/bug648573.html delete mode 100644 layout/base/tests/bug644768.html delete mode 100644 layout/base/tests/test_bug1070851.html delete mode 100644 layout/base/tests/test_touchcaret_visibility.html diff --git a/dom/events/test/bug648573.html b/dom/events/test/bug648573.html deleted file mode 100644 index a70642370b0e..000000000000 --- a/dom/events/test/bug648573.html +++ /dev/null @@ -1,106 +0,0 @@ - - - - - Test for Bug 648573 - - - - -Mozilla Bug 648573 -

- -
-
-
- - - diff --git a/dom/events/test/mochitest.ini b/dom/events/test/mochitest.ini index e23b950136f2..5583b4b6aff6 100644 --- a/dom/events/test/mochitest.ini +++ b/dom/events/test/mochitest.ini @@ -5,7 +5,6 @@ support-files = bug299673.js bug322588-popup.html bug426082.html - bug648573.html bug656379-1.html bug418986-3.js error_event_worker.js diff --git a/dom/events/test/test_bug648573.html b/dom/events/test/test_bug648573.html index ac5b2d166479..0a4a9e7e3708 100644 --- a/dom/events/test/test_bug648573.html +++ b/dom/events/test/test_bug648573.html @@ -4,27 +4,106 @@ + - Bug 648573 test - + Test for Bug 648573 + + -
+ Mozilla Bug 648573 +

+ +
+      
+    
- diff --git a/dom/events/test/test_clickevent_on_input.html b/dom/events/test/test_clickevent_on_input.html index a426f8b1df24..07fe6ade6286 100644 --- a/dom/events/test/test_clickevent_on_input.html +++ b/dom/events/test/test_clickevent_on_input.html @@ -49,11 +49,10 @@ function isEnabledMiddleClickPaste() } } -function isEnabledTouchCaret() +function isEnabledAccessibleCaret() { try { - return SpecialPowers.getBoolPref("touchcaret.enabled") || - SpecialPowers.getBoolPref("layout.accessiblecaret.enabled"); + return SpecialPowers.getBoolPref("layout.accessiblecaret.enabled"); } catch (e) { return false; } @@ -69,7 +68,7 @@ function doTest(aButton) // then, the click event isn't generated. if (aButton != 2 && (aButton != 1 || !isEnabledMiddleClickPaste()) && - (aButton != 0 || !isEnabledTouchCaret())) { + (aButton != 0 || !isEnabledAccessibleCaret())) { gClickCount = 0; // click on border of input synthesizeMouse(input, 5, 5, { button: aButton }); diff --git a/editor/reftests/reftest.list b/editor/reftests/reftest.list index 74a57189ac8e..f66c422cb6e3 100644 --- a/editor/reftests/reftest.list +++ b/editor/reftests/reftest.list @@ -57,10 +57,10 @@ skip-if(B2G||Mulet) random-if(Android) needs-focus != spellcheck-textarea-attr-d skip-if(B2G||Mulet) random-if(Android) needs-focus != spellcheck-textarea-attr-dynamic-override-inherit.html spellcheck-textarea-ref.html # Initial mulet triage: parity with B2G/B2G Desktop skip-if(B2G||Mulet) random-if(Android) needs-focus != spellcheck-textarea-property-dynamic-override.html spellcheck-textarea-ref.html # Initial mulet triage: parity with B2G/B2G Desktop skip-if(B2G||Mulet) random-if(Android) needs-focus != spellcheck-textarea-property-dynamic-override-inherit.html spellcheck-textarea-ref.html # Initial mulet triage: parity with B2G/B2G Desktop -needs-focus pref(touchcaret.enabled,false) == caret_on_focus.html caret_on_focus-ref.html +needs-focus == caret_on_focus.html caret_on_focus-ref.html needs-focus != caret_on_textarea_lastline.html caret_on_textarea_lastline-ref.html -needs-focus pref(touchcaret.enabled,false) pref(selectioncaret.enabled,false) == input-text-onfocus-reframe.html input-text-onfocus-reframe-ref.html -needs-focus pref(touchcaret.enabled,false) pref(selectioncaret.enabled,false) == input-text-notheme-onfocus-reframe.html input-text-notheme-onfocus-reframe-ref.html +needs-focus == input-text-onfocus-reframe.html input-text-onfocus-reframe-ref.html +needs-focus == input-text-notheme-onfocus-reframe.html input-text-notheme-onfocus-reframe-ref.html skip-if(B2G||Mulet) needs-focus == caret_after_reframe.html caret_after_reframe-ref.html # B2G timed out waiting for reftest-wait to be removed # Initial mulet triage: parity with B2G/B2G Desktop == nobogusnode-1.html nobogusnode-ref.html == nobogusnode-2.html nobogusnode-ref.html @@ -104,15 +104,15 @@ skip-if(Android||B2G||Mulet) needs-focus == 462758-grabbers-resizers.html 462758 == 388980-1.html 388980-1-ref.html needs-focus == spellcheck-superscript-1.html spellcheck-superscript-1-ref.html skip-if(B2G||Mulet) fails-if(Android) needs-focus != spellcheck-superscript-2.html spellcheck-superscript-2-ref.html # bug 783658 # Initial mulet triage: parity with B2G/B2G Desktop -needs-focus pref(selectioncaret.enabled,false) pref(layout.accessiblecaret.enabled,false) == 824080-1.html 824080-1-ref.html -needs-focus pref(selectioncaret.enabled,false) pref(layout.accessiblecaret.enabled,false) == 824080-2.html 824080-2-ref.html -needs-focus pref(selectioncaret.enabled,false) pref(layout.accessiblecaret.enabled,false) == 824080-3.html 824080-3-ref.html +needs-focus pref(layout.accessiblecaret.enabled,false) == 824080-1.html 824080-1-ref.html +needs-focus pref(layout.accessiblecaret.enabled,false) == 824080-2.html 824080-2-ref.html +needs-focus pref(layout.accessiblecaret.enabled,false) == 824080-3.html 824080-3-ref.html needs-focus != 824080-2.html 824080-3.html -needs-focus pref(selectioncaret.enabled,false) pref(layout.accessiblecaret.enabled,false) == 824080-4.html 824080-4-ref.html -needs-focus pref(selectioncaret.enabled,false) pref(layout.accessiblecaret.enabled,false) == 824080-5.html 824080-5-ref.html +needs-focus pref(layout.accessiblecaret.enabled,false) == 824080-4.html 824080-4-ref.html +needs-focus pref(layout.accessiblecaret.enabled,false) == 824080-5.html 824080-5-ref.html needs-focus != 824080-4.html 824080-5.html needs-focus == 824080-6.html 824080-6-ref.html -needs-focus pref(selectioncaret.enabled,false) pref(layout.accessiblecaret.enabled,false) == 824080-7.html 824080-7-ref.html +needs-focus pref(layout.accessiblecaret.enabled,false) == 824080-7.html 824080-7-ref.html needs-focus != 824080-6.html 824080-7.html # Bug 674927: copy spellcheck-textarea tests to contenteditable == spellcheck-contenteditable-attr.html spellcheck-contenteditable-nofocus-ref.html diff --git a/layout/base/tests/bug644768.html b/layout/base/tests/bug644768.html deleted file mode 100644 index 385739321b7c..000000000000 --- a/layout/base/tests/bug644768.html +++ /dev/null @@ -1,58 +0,0 @@ - - - - - Test for Bug 644768 - - - - - - -Mozilla Bug 644768 -

-
- - -
-
-
-
- - diff --git a/layout/base/tests/mochitest.ini b/layout/base/tests/mochitest.ini index c3de8be102df..a33a7e19d00a 100644 --- a/layout/base/tests/mochitest.ini +++ b/layout/base/tests/mochitest.ini @@ -12,7 +12,6 @@ support-files = file_bug842853.html ../../../dom/plugins/test/mochitest/plugin-utils.js bug558663.html - bug644768.html bug956530-1.html bug956530-1-ref.html bug989012-1.html @@ -247,7 +246,6 @@ support-files = bug687297_b.html bug687297_c.html [test_bug990340.html] -[test_bug1070851.html] [test_bug1080360.html] support-files = bug1080360_inner.html [test_bug1078327.html] @@ -255,7 +253,6 @@ support-files = bug1078327_inner.html [test_bug1080361.html] support-files = bug1080361_inner.html [test_frame_reconstruction_for_pseudo_elements.html] -[test_touchcaret_visibility.html] [test_bug1093686.html] support-files = bug1093686_inner.html [test_bug1120705.html] diff --git a/layout/base/tests/test_bug1070851.html b/layout/base/tests/test_bug1070851.html deleted file mode 100644 index 94c0d25f7881..000000000000 --- a/layout/base/tests/test_bug1070851.html +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - Test for Bug 1070851 - - - - - - - - - - Mozilla Bug 1070851 - - -
test
- - diff --git a/layout/base/tests/test_bug558663.html b/layout/base/tests/test_bug558663.html index 737d32d62845..2e20deec322a 100644 --- a/layout/base/tests/test_bug558663.html +++ b/layout/base/tests/test_bug558663.html @@ -26,10 +26,9 @@ SimpleTest.expectAssertions(0, 2); } SimpleTest.waitForExplicitFinish(); - // Selection caret's pref is checked only when PresShell is initialized. To turn + // AccessibleCaret's pref is checked only when PresShell is initialized. To turn // off the pref, we test bug 558663 in an iframe. - SpecialPowers.pushPrefEnv({"set": [['selectioncaret.enabled', false], - ['layout.accessiblecaret.enabled', false]]}, function() { + SpecialPowers.pushPrefEnv({"set": [['layout.accessiblecaret.enabled', false]]}, function() { var iframe = document.createElement("iframe"); iframe.src = "bug558663.html"; document.getElementById('container').appendChild(iframe); diff --git a/layout/base/tests/test_bug644768.html b/layout/base/tests/test_bug644768.html index 0404551f7c14..24f3d29e1a3f 100644 --- a/layout/base/tests/test_bug644768.html +++ b/layout/base/tests/test_bug644768.html @@ -4,25 +4,59 @@ + - Bug 644768 test - + Test for Bug 644768 + + + + - -
+ + Mozilla Bug 644768 +

+
+ + +
+
+      
+    
- diff --git a/layout/base/tests/test_reftests_with_caret.html b/layout/base/tests/test_reftests_with_caret.html index cc617ba24465..1a8f7599afb8 100644 --- a/layout/base/tests/test_reftests_with_caret.html +++ b/layout/base/tests/test_reftests_with_caret.html @@ -107,11 +107,9 @@ var tests = [ [ 'bug1082486-1.html', 'bug1082486-1-ref.html'] , [ 'bug1082486-2.html', 'bug1082486-2-ref.html'] , // The following test cases are all involving with one sending - // synthesizeKey(), the other without. They fail when the touch - // or selection caret is enabled. Test them with these preferences off. - function() {SpecialPowers.pushPrefEnv({'set': [['touchcaret.enabled', false], - ['selectioncaret.enabled', false], - ['layout.accessiblecaret.enabled', false]]}, nextTest);} , + // synthesizeKey(), the other without. They fail when accessiblecaret + // is enabled. Test them with the preference off. + function() {SpecialPowers.pushPrefEnv({'set': [['layout.accessiblecaret.enabled', false]]}, nextTest);} , [ 'bug240933-1.html' , 'bug240933-1-ref.html' ] , [ 'bug240933-2.html' , 'bug240933-1-ref.html' ] , [ 'bug389321-1.html' , 'bug389321-1-ref.html' ] , @@ -157,18 +155,14 @@ var tests = [ [ 'bug1123067-2.html' , 'bug1123067-ref.html' ] , [ 'bug1123067-3.html' , 'bug1123067-ref.html' ] , [ 'bug1132768-1.html' , 'bug1132768-1-ref.html'] , - function() {SpecialPowers.pushPrefEnv({'clear': [['touchcaret.enabled'], - ['selectioncaret.enabled'], - ['layout.accessiblecaret.enabled']]}, nextTest);} , + function() {SpecialPowers.pushPrefEnv({'clear': [['layout.accessiblecaret.enabled']]}, nextTest);} , ]; if (navigator.appVersion.indexOf("Android") == -1 && SpecialPowers.Services.appinfo.name != "B2G") { - tests.push(function() {SpecialPowers.pushPrefEnv({'set': [['touchcaret.enabled', false]]}, nextTest);}); tests.push([ 'bug512295-1.html' , 'bug512295-1-ref.html' ]); tests.push([ 'bug512295-2.html' , 'bug512295-2-ref.html' ]); tests.push([ 'bug923376.html' , 'bug923376-ref.html' ]); - tests.push(function() {SpecialPowers.pushPrefEnv({'clear': [['touchcaret.enabled']]}, nextTest);}); tests.push(function() {SpecialPowers.pushPrefEnv({'set': [['layout.css.overflow-clip-box.enabled', true]]}, nextTest);}); tests.push([ 'bug966992-1.html' , 'bug966992-1-ref.html' ]); tests.push([ 'bug966992-2.html' , 'bug966992-2-ref.html' ]); @@ -181,7 +175,6 @@ if (navigator.appVersion.indexOf("Android") == -1 && if (navigator.platform.indexOf("Linux") >= 0 && SpecialPowers.Services.appinfo.name != "B2G") { tests = tests.concat([ - function() {SpecialPowers.pushPrefEnv({'set': [['touchcaret.enabled', false]]}, nextTest);} , // eDirPrevious, Shift+click [ 'multi-range-user-select.html#prev1S_' , 'multi-range-user-select-ref.html#prev1S_' ] , [ 'multi-range-user-select.html#prev2S_' , 'multi-range-user-select-ref.html#prev2S_' ] , @@ -274,7 +267,6 @@ if (navigator.platform.indexOf("Linux") >= 0 && // eDirNext, VK_RIGHT / LEFT [ 'multi-range-script-select.html#next1SR' , 'multi-range-script-select-ref.html#next1SR' ] , [ 'multi-range-script-select.html#next1SL' , 'multi-range-script-select-ref.html#next1SL' ] , - function() {SpecialPowers.pushPrefEnv({'clear': [['touchcaret.enabled']]}, nextTest);} , ]); } diff --git a/layout/base/tests/test_touchcaret_visibility.html b/layout/base/tests/test_touchcaret_visibility.html deleted file mode 100644 index e363d38f12e9..000000000000 --- a/layout/base/tests/test_touchcaret_visibility.html +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - Test for Bug 1070851 - - - - - - - - - - - Mozilla Bug 1059165 - - -
- - From 749adb0ce3d2fcb5e7fcf4f2a4267d01ade5236a Mon Sep 17 00:00:00 2001 From: Ting-Yu Lin Date: Tue, 22 Dec 2015 14:14:12 +0800 Subject: [PATCH 06/94] Bug 1121459 - Remove TouchCaret and SelectionCarets from marionette tests. r=mtseng --HG-- rename : layout/base/tests/marionette/test_touchcaret.py => layout/base/tests/marionette/test_accessiblecaret_cursor_mode.py rename : layout/base/tests/marionette/test_selectioncarets.py => layout/base/tests/marionette/test_accessiblecaret_selection_mode.py extra : rebase_source : 5d30a91c32a95fca4c1857fba57ef582b2fd2c06 --- layout/base/tests/marionette/manifest.ini | 4 +- ...py => test_accessiblecaret_cursor_mode.py} | 57 ++++--------------- ...=> test_accessiblecaret_selection_mode.py} | 42 ++++---------- 3 files changed, 24 insertions(+), 79 deletions(-) rename layout/base/tests/marionette/{test_touchcaret.py => test_accessiblecaret_cursor_mode.py} (90%) rename layout/base/tests/marionette/{test_selectioncarets.py => test_accessiblecaret_selection_mode.py} (97%) diff --git a/layout/base/tests/marionette/manifest.ini b/layout/base/tests/marionette/manifest.ini index 8f9f6706953f..e14f964105ba 100644 --- a/layout/base/tests/marionette/manifest.ini +++ b/layout/base/tests/marionette/manifest.ini @@ -11,5 +11,5 @@ b2g = true ; true if the test should be skipped skip = false -[test_touchcaret.py] -[test_selectioncarets.py] +[test_accessiblecaret_cursor_mode.py] +[test_accessiblecaret_selection_mode.py] diff --git a/layout/base/tests/marionette/test_touchcaret.py b/layout/base/tests/marionette/test_accessiblecaret_cursor_mode.py similarity index 90% rename from layout/base/tests/marionette/test_touchcaret.py rename to layout/base/tests/marionette/test_accessiblecaret_cursor_mode.py index cdaa663c0222..de7bbc34b24a 100644 --- a/layout/base/tests/marionette/test_touchcaret.py +++ b/layout/base/tests/marionette/test_accessiblecaret_cursor_mode.py @@ -12,16 +12,21 @@ from marionette_driver.marionette import Actions from marionette_driver.selection import SelectionManager -class CommonCaretTestCase(object): - '''Common test cases for a collapsed selection with a single caret. - - To run these test cases, a subclass must inherit from both this class and - MarionetteTestCase. +class AccessibleCaretCursorModeTestCase(MarionetteTestCase): + '''Test cases for AccessibleCaret under cursor mode, aka touch caret. ''' + def setUp(self): # Code to execute before a test is being run. - super(CommonCaretTestCase, self).setUp() + super(AccessibleCaretCursorModeTestCase, self).setUp() + self.caret_tested_pref = 'layout.accessiblecaret.enabled' + self.caret_timeout_ms_pref = 'layout.accessiblecaret.timeout_ms' + self.prefs = { + self.caret_tested_pref: True, + self.caret_timeout_ms_pref: 0, + } + self.marionette.set_prefs(self.prefs) self.actions = Actions(self.marionette) def timeout_ms(self): @@ -295,46 +300,6 @@ class CommonCaretTestCase(object): self.open_test_html() self._test_move_caret_to_front_by_dragging_touch_caret_to_front_of_content(self._contenteditable, self.assertNotEqual) - -class TouchCaretTestCase(CommonCaretTestCase, MarionetteTestCase): - def setUp(self): - super(TouchCaretTestCase, self).setUp() - self.caret_tested_pref = 'touchcaret.enabled' - self.caret_timeout_ms_pref = 'touchcaret.expiration.time' - - self.prefs = { - 'layout.accessiblecaret.enabled': False, - self.caret_tested_pref: True, - self.caret_timeout_ms_pref: 0, - } - self.marionette.set_prefs(self.prefs) - - def test_input_touch_caret_hides_after_receiving_wheel_event(self): - self.open_test_html() - self._test_touch_caret_hides_after_receiving_wheel_event(self._input, self.assertNotEqual) - - def test_textarea_touch_caret_hides_after_receiving_wheel_event(self): - self.open_test_html() - self._test_touch_caret_hides_after_receiving_wheel_event(self._textarea, self.assertNotEqual) - - def test_contenteditable_touch_caret_hides_after_receiving_wheel_event(self): - self.open_test_html() - self._test_touch_caret_hides_after_receiving_wheel_event(self._contenteditable, self.assertNotEqual) - - -class AccessibleCaretCursorModeTestCase(CommonCaretTestCase, MarionetteTestCase): - def setUp(self): - super(AccessibleCaretCursorModeTestCase, self).setUp() - self.caret_tested_pref = 'layout.accessiblecaret.enabled' - self.caret_timeout_ms_pref = 'layout.accessiblecaret.timeout_ms' - - self.prefs = { - 'touchcaret.enabled': False, - self.caret_tested_pref: True, - self.caret_timeout_ms_pref: 0, - } - self.marionette.set_prefs(self.prefs) - def test_caret_does_not_jump_when_dragging_to_editable_content_boundary(self): self.open_test_html() el = self._input diff --git a/layout/base/tests/marionette/test_selectioncarets.py b/layout/base/tests/marionette/test_accessiblecaret_selection_mode.py similarity index 97% rename from layout/base/tests/marionette/test_selectioncarets.py rename to layout/base/tests/marionette/test_accessiblecaret_selection_mode.py index 0717f042c179..c5552fade74d 100644 --- a/layout/base/tests/marionette/test_selectioncarets.py +++ b/layout/base/tests/marionette/test_accessiblecaret_selection_mode.py @@ -18,16 +18,21 @@ def skip_if_not_rotatable(target): return wrapper -class CommonCaretsTestCase(object): - '''Common test cases for a selection with a two carets. - - To run these test cases, a subclass must inherit from both this class and - MarionetteTestCase. +class AccessibleCaretSelectionModeTestCase(MarionetteTestCase): + '''Test cases for AccessibleCaret under selection mode, aka selection carets. ''' + def setUp(self): # Code to execute before a tests are run. - super(CommonCaretsTestCase, self).setUp() + super(AccessibleCaretSelectionModeTestCase, self).setUp() + self.carets_tested_pref = 'layout.accessiblecaret.enabled' + self.prefs = { + 'layout.word_select.eat_space_to_next_word': False, + 'layout.accessiblecaret.use_long_tap_injector': False, + self.carets_tested_pref: True, + } + self.marionette.set_prefs(self.prefs) self.actions = Actions(self.marionette) def open_test_html(self): @@ -690,31 +695,6 @@ class CommonCaretsTestCase(object): self.open_test_html2() self._test_minimum_select_one_character(self._content2, self.assertEqual) - -class SelectionCaretsTestCase(CommonCaretsTestCase, MarionetteTestCase): - def setUp(self): - super(SelectionCaretsTestCase, self).setUp() - self.carets_tested_pref = 'selectioncaret.enabled' - self.prefs = { - 'layout.accessiblecaret.enabled': False, - 'layout.word_select.eat_space_to_next_word': False, - self.carets_tested_pref: True, - } - self.marionette.set_prefs(self.prefs) - - -class AccessibleCaretSelectionModeTestCase(CommonCaretsTestCase, MarionetteTestCase): - def setUp(self): - super(AccessibleCaretSelectionModeTestCase, self).setUp() - self.carets_tested_pref = 'layout.accessiblecaret.enabled' - self.prefs = { - 'selectioncaret.enabled': False, - 'layout.word_select.eat_space_to_next_word': False, - 'layout.accessiblecaret.use_long_tap_injector': False, - self.carets_tested_pref: True, - } - self.marionette.set_prefs(self.prefs) - def test_long_press_to_select_when_partial_visible_word_is_selected(self): self.open_test_html() el = self._input From 69a670793a8f758fc93436a3435f83c2a0c49f96 Mon Sep 17 00:00:00 2001 From: Ting-Yu Lin Date: Tue, 22 Dec 2015 14:14:12 +0800 Subject: [PATCH 07/94] Bug 1221459 - Remove SelectionStateChangedEvent. r=mtseng,smaug SelectionStateChangedEvent is dispatched only by SelectionCarets. Hence the removal. The modification in mochitest browserElement_CopyPaste.js is effectively the reverting of [1] with AccessibleCaret enabled. The DoCommandHelper is shell.js is removed as well, which handles the 'do-command' event dispatched from old text_selection_dialog.js in Gaia. [1] https://bugzilla.mozilla.org/page.cgi?id=splinter.html&bug=1155493&attachment=8612154 --HG-- extra : commitid : GWwMqChxnUT extra : source : 3f2c650804415aa98f42369bc2061ab2ada98661 extra : amend_source : b8f3a445248397f140723a07ea5bc85ed67d6054 --- b2g/chrome/content/shell.js | 43 -------- .../BrowserElementChildPreload.js | 98 ------------------- dom/browser-element/BrowserElementParent.js | 9 +- .../mochitest/browserElementTestHelpers.js | 4 - .../mochitest/browserElement_CopyPaste.js | 57 ++++------- .../browserElement_SelectionStateBlur.js | 57 ----------- .../mochitest/mochitest-oop.ini | 3 - dom/browser-element/mochitest/mochitest.ini | 4 - ...wserElement_inproc_SelectionStateBlur.html | 18 ---- ...browserElement_oop_SelectionStateBlur.html | 18 ---- dom/webidl/SelectionStateChangedEvent.webidl | 34 ------- dom/webidl/moz.build | 1 - 12 files changed, 18 insertions(+), 328 deletions(-) delete mode 100644 dom/browser-element/mochitest/browserElement_SelectionStateBlur.js delete mode 100644 dom/browser-element/mochitest/test_browserElement_inproc_SelectionStateBlur.html delete mode 100644 dom/browser-element/mochitest/test_browserElement_oop_SelectionStateBlur.html delete mode 100644 dom/webidl/SelectionStateChangedEvent.webidl diff --git a/b2g/chrome/content/shell.js b/b2g/chrome/content/shell.js index cd1c7b066f3d..f51901fd9eaa 100644 --- a/b2g/chrome/content/shell.js +++ b/b2g/chrome/content/shell.js @@ -430,7 +430,6 @@ var shell = { window.addEventListener('sizemodechange', this); window.addEventListener('unload', this); this.contentBrowser.addEventListener('mozbrowserloadstart', this, true); - this.contentBrowser.addEventListener('mozbrowserselectionstatechanged', this, true); this.contentBrowser.addEventListener('mozbrowserscrollviewchange', this, true); this.contentBrowser.addEventListener('mozbrowsercaretstatechanged', this); @@ -464,7 +463,6 @@ var shell = { window.removeEventListener('MozApplicationManifest', this); window.removeEventListener('sizemodechange', this); this.contentBrowser.removeEventListener('mozbrowserloadstart', this, true); - this.contentBrowser.removeEventListener('mozbrowserselectionstatechanged', this, true); this.contentBrowser.removeEventListener('mozbrowserscrollviewchange', this, true); this.contentBrowser.removeEventListener('mozbrowsercaretstatechanged', this); ppmm.removeMessageListener("content-handler", this); @@ -584,29 +582,6 @@ var shell = { detail: evt.detail, }); break; - case 'mozbrowserselectionstatechanged': - // The mozbrowserselectionstatechanged event, may have crossed the chrome-content boundary. - // This event always dispatch to shell.js. But the offset we got from this event is - // based on tab's coordinate. So get the actual offsets between shell and evt.target. - let elt = evt.target; - let win = elt.ownerDocument.defaultView; - let offsetX = win.mozInnerScreenX - window.mozInnerScreenX; - let offsetY = win.mozInnerScreenY - window.mozInnerScreenY; - - let rect = elt.getBoundingClientRect(); - offsetX += rect.left; - offsetY += rect.top; - - let data = evt.detail; - data.offsetX = offsetX; - data.offsetY = offsetY; - - DoCommandHelper.setEvent(evt); - shell.sendChromeEvent({ - type: 'selectionstatechanged', - detail: data, - }); - break; case 'mozbrowsercaretstatechanged': { let elt = evt.target; @@ -883,9 +858,6 @@ var CustomEventManager = { case 'inputregistry-remove': KeyboardHelper.handleEvent(detail); break; - case 'do-command': - DoCommandHelper.handleEvent(detail.cmd); - break; case 'copypaste-do-command': Services.obs.notifyObservers({ wrappedJSObject: shell.contentBrowser }, 'ask-children-to-execute-copypaste-command', detail.cmd); @@ -933,21 +905,6 @@ var CustomEventManager = { } } -var DoCommandHelper = { - _event: null, - setEvent: function docommand_setEvent(evt) { - this._event = evt; - }, - - handleEvent: function docommand_handleEvent(cmd) { - if (this._event) { - Services.obs.notifyObservers({ wrappedJSObject: this._event.target }, - 'copypaste-docommand', cmd); - this._event = null; - } - } -} - var WebappsHelper = { _installers: {}, _count: 0, diff --git a/dom/browser-element/BrowserElementChildPreload.js b/dom/browser-element/BrowserElementChildPreload.js index d80e1537603a..3ae6461558c9 100644 --- a/dom/browser-element/BrowserElementChildPreload.js +++ b/dom/browser-element/BrowserElementChildPreload.js @@ -139,7 +139,6 @@ function BrowserElementChild() { this._isContentWindowCreated = false; this._pendingSetInputMethodActive = []; - this._selectionStateChangedTarget = null; this.forwarder = new BrowserElementProxyForwarder(); @@ -224,11 +223,6 @@ BrowserElementChild.prototype = { /* useCapture = */ true, /* wantsUntrusted = */ false); - addEventListener('mozselectionstatechanged', - this._selectionStateChangedHandler.bind(this), - /* useCapture = */ true, - /* wantsUntrusted = */ false); - addEventListener('scrollviewchange', this._ScrollViewChangeHandler.bind(this), /* useCapture = */ true, @@ -719,97 +713,6 @@ BrowserElementChild.prototype = { } }, - _selectionStateChangedHandler: function(e) { - e.stopPropagation(); - - if (!this._isContentWindowCreated) { - return; - } - - let boundingClientRect = e.boundingClientRect; - - let isCollapsed = (e.selectedText.length == 0); - let isMouseUp = (e.states.indexOf('mouseup') == 0); - let canPaste = this._isCommandEnabled("paste"); - - if (this._selectionStateChangedTarget != e.target) { - // SelectionStateChanged events with the following states are not - // necessary to trigger the text dialog, bypass these events - // by default. - // - if(e.states.length == 0 || - e.states.indexOf('drag') == 0 || - e.states.indexOf('keypress') == 0 || - e.states.indexOf('mousedown') == 0) { - return; - } - - // The collapsed SelectionStateChanged event is unnecessary to dispatch, - // bypass this event by default, but here comes some exceptional cases - if (isCollapsed) { - if (isMouseUp && canPaste) { - // Always dispatch to support shortcut mode which can paste previous - // copied content easily - } else if (e.states.indexOf('blur') == 0) { - // Always dispatch to notify the blur for the focus content - } else if (e.states.indexOf('taponcaret') == 0) { - // Always dispatch to notify the caret be touched - } else { - return; - } - } - } - - // If we select something and selection range is visible, we cache current - // event's target to selectionStateChangedTarget. - // And dispatch the next SelectionStateChagne event if target is matched, so - // that the parent side can hide the text dialog. - // We clear selectionStateChangedTarget if selection carets are invisible. - if (e.visible && !isCollapsed) { - this._selectionStateChangedTarget = e.target; - } else if (canPaste && isCollapsed) { - this._selectionStateChangedTarget = e.target; - } else { - this._selectionStateChangedTarget = null; - } - - let zoomFactor = content.screen.width / content.innerWidth; - - let detail = { - rect: { - width: boundingClientRect ? boundingClientRect.width : 0, - height: boundingClientRect ? boundingClientRect.height : 0, - top: boundingClientRect ? boundingClientRect.top : 0, - bottom: boundingClientRect ? boundingClientRect.bottom : 0, - left: boundingClientRect ? boundingClientRect.left : 0, - right: boundingClientRect ? boundingClientRect.right : 0, - }, - commands: { - canSelectAll: this._isCommandEnabled("selectall"), - canCut: this._isCommandEnabled("cut"), - canCopy: this._isCommandEnabled("copy"), - canPaste: this._isCommandEnabled("paste"), - }, - zoomFactor: zoomFactor, - states: e.states, - isCollapsed: (e.selectedText.length == 0), - visible: e.visible, - }; - - // Get correct geometry information if we have nested iframe. - let currentWindow = e.target.defaultView; - while (currentWindow.realFrameElement) { - let currentRect = currentWindow.realFrameElement.getBoundingClientRect(); - detail.rect.top += currentRect.top; - detail.rect.bottom += currentRect.top; - detail.rect.left += currentRect.left; - detail.rect.right += currentRect.left; - currentWindow = currentWindow.realFrameElement.ownerDocument.defaultView; - } - - sendAsyncMsg('selectionstatechanged', detail); - }, - _genericMetaHandler: function(name, eventType, target) { let meta = { name: name, @@ -1481,7 +1384,6 @@ BrowserElementChild.prototype = { _recvDoCommand: function(data) { if (this._isCommandEnabled(data.json.command)) { - this._selectionStateChangedTarget = null; docShell.doCommand(COMMAND_MAP[data.json.command]); } }, diff --git a/dom/browser-element/BrowserElementParent.js b/dom/browser-element/BrowserElementParent.js index b8dc9cb08b1f..ce6e775a3a75 100644 --- a/dom/browser-element/BrowserElementParent.js +++ b/dom/browser-element/BrowserElementParent.js @@ -81,7 +81,7 @@ BrowserElementParentProxyCallHandler.prototype = { "contextmenu", "securitychange", "locationchange", "iconchange", "scrollareachanged", "titlechange", "opensearch", "manifestchange", "metachange", - "resize", "selectionstatechanged", "scrollviewchange", + "resize", "scrollviewchange", "caretstatechanged", "activitydone", "scroll", "opentab"]), init: function(frameElement, mm) { @@ -380,7 +380,6 @@ BrowserElementParent.prototype = { "got-visible": this._gotDOMRequestResult, "visibilitychange": this._childVisibilityChange, "got-set-input-method-active": this._gotDOMRequestResult, - "selectionstatechanged": this._handleSelectionStateChanged, "scrollviewchange": this._handleScrollViewChange, "caretstatechanged": this._handleCaretStateChanged, "findchange": this._handleFindChange, @@ -619,12 +618,6 @@ BrowserElementParent.prototype = { } }, - _handleSelectionStateChanged: function(data) { - let evt = this._createEvent('selectionstatechanged', data.json, - /* cancelable = */ false); - this._frameElement.dispatchEvent(evt); - }, - // Called when state of accessible caret in child has changed. // The fields of data is as following: // - rect: Contains bounding rectangle of selection, Include width, height, diff --git a/dom/browser-element/mochitest/browserElementTestHelpers.js b/dom/browser-element/mochitest/browserElementTestHelpers.js index 8c92e0fe0905..96038a032bb3 100644 --- a/dom/browser-element/mochitest/browserElementTestHelpers.js +++ b/dom/browser-element/mochitest/browserElementTestHelpers.js @@ -65,10 +65,6 @@ const browserElementTestHelpers = { this._setPref('dom.mozBrowserFramesEnabled', value); }, - setSelectionChangeEnabledPref: function(value) { - this._setPref('selectioncaret.enabled', value); - }, - setAccessibleCaretEnabledPref: function(value) { this._setPref('layout.accessiblecaret.enabled', value); }, diff --git a/dom/browser-element/mochitest/browserElement_CopyPaste.js b/dom/browser-element/mochitest/browserElement_CopyPaste.js index 148e205e00b2..20d505d912ab 100644 --- a/dom/browser-element/mochitest/browserElement_CopyPaste.js +++ b/dom/browser-element/mochitest/browserElement_CopyPaste.js @@ -1,14 +1,12 @@ /* Any copyright is dedicated to the public domain. http://creativecommons.org/publicdomain/zero/1.0/ */ -// Test that "cut, copy, paste, selectall" and selectionstatechanged event works from inside an